]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkcolor-x11.c
Fix spacing in a bunch of for (i=0; i<ncolors; i++).
[~andy/gtk] / gdk / x11 / gdkcolor-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <time.h>
28
29 #include "gdkcolor.h"
30 #include "gdkinternals.h"
31 #include "gdkx.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkscreen-x11.h"
34
35 typedef struct _GdkColormapPrivateX11  GdkColormapPrivateX11;
36
37 struct _GdkColormapPrivateX11
38 {
39   GdkScreen *screen;
40   Colormap xcolormap;
41   gint private_val;
42
43   GHashTable *hash;
44   GdkColorInfo *info;
45   time_t last_sync_time;
46
47   guint foreign : 1;
48 };
49
50 #define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateX11 *) GDK_COLORMAP (cmap)->windowing_data)
51
52 static gint     gdk_colormap_match_color (GdkColormap *cmap,
53                                           GdkColor    *color,
54                                           const gchar *available);
55 static void     gdk_colormap_add         (GdkColormap *cmap);
56 static void     gdk_colormap_remove      (GdkColormap *cmap);
57
58 static GdkColormap *gdk_colormap_lookup   (GdkScreen   *screen,
59                                            Colormap     xcolormap);
60
61 static guint    gdk_colormap_hash        (Colormap    *cmap);
62 static gboolean gdk_colormap_equal       (Colormap    *a,
63                                           Colormap    *b);
64 static void     gdk_colormap_sync        (GdkColormap *colormap,
65                                           gboolean     force);
66
67 static void gdk_colormap_init       (GdkColormap      *colormap);
68 static void gdk_colormap_class_init (GdkColormapClass *klass);
69 static void gdk_colormap_finalize   (GObject              *object);
70
71 static gpointer parent_class = NULL;
72
73 GType
74 gdk_colormap_get_type (void)
75 {
76   static GType object_type = 0;
77
78   if (!object_type)
79     {
80       static const GTypeInfo object_info =
81       {
82         sizeof (GdkColormapClass),
83         (GBaseInitFunc) NULL,
84         (GBaseFinalizeFunc) NULL,
85         (GClassInitFunc) gdk_colormap_class_init,
86         NULL,           /* class_finalize */
87         NULL,           /* class_data */
88         sizeof (GdkColormap),
89         0,              /* n_preallocs */
90         (GInstanceInitFunc) gdk_colormap_init,
91       };
92       
93       object_type = g_type_register_static (G_TYPE_OBJECT,
94                                             "GdkColormap",
95                                             &object_info, 0);
96     }
97   
98   return object_type;
99 }
100
101 static void
102 gdk_colormap_init (GdkColormap *colormap)
103 {
104   GdkColormapPrivateX11 *private;
105
106   private = g_new (GdkColormapPrivateX11, 1);
107
108   colormap->windowing_data = private;
109   
110   private->screen = NULL;
111   private->hash = NULL;
112   private->last_sync_time = 0;
113   private->info = NULL;
114
115   colormap->size = 0;
116   colormap->colors = NULL;
117 }
118
119 static void
120 gdk_colormap_class_init (GdkColormapClass *klass)
121 {
122   GObjectClass *object_class = G_OBJECT_CLASS (klass);
123
124   parent_class = g_type_class_peek_parent (klass);
125
126   object_class->finalize = gdk_colormap_finalize;
127 }
128
129 static void
130 gdk_colormap_finalize (GObject *object)
131 {
132   GdkColormap *colormap = GDK_COLORMAP (object);
133   GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
134
135   gdk_colormap_remove (colormap);
136
137   if (!private->screen->closed)
138     XFreeColormap (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap);
139
140   if (private->hash)
141     g_hash_table_destroy (private->hash);
142   
143   g_free (private->info);
144   g_free (colormap->colors);
145   g_free (private);
146   
147   G_OBJECT_CLASS (parent_class)->finalize (object);
148 }
149
150 /**
151  * gdk_colormap_new:
152  * @visual: a #GdkVisual.
153  * @allocate: if %TRUE, the newly created colormap will be
154  * a private colormap, and all colors in it will be
155  * allocated for the applications use.
156  * 
157  * Creates a new colormap for the given visual.
158  * 
159  * Return value: the new #GdkColormap.
160  **/
161 GdkColormap*
162 gdk_colormap_new (GdkVisual *visual,
163                   gboolean   allocate)
164 {
165   GdkColormap *colormap;
166   GdkColormapPrivateX11 *private;
167   Visual *xvisual;
168   Display *xdisplay;
169   Window xrootwin;
170   int size;
171   int i;
172
173   /* FIXME when object properties settle down, there needs to be some
174    * kind of default construction (and construct-only arguments)
175    */
176   
177   g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
178
179   colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
180   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
181
182   colormap->visual = visual;
183   private->screen = gdk_visual_get_screen (visual);
184   
185   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
186   xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
187   xrootwin = GDK_SCREEN_XROOTWIN (private->screen);
188
189   colormap->size = visual->colormap_size;
190
191   switch (visual->type)
192     {
193     case GDK_VISUAL_GRAYSCALE:
194     case GDK_VISUAL_PSEUDO_COLOR:
195       private->info = g_new0 (GdkColorInfo, colormap->size);
196       colormap->colors = g_new (GdkColor, colormap->size);
197       
198       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
199                                         (GEqualFunc) gdk_color_equal);
200       
201       private->private_val = allocate;
202       private->xcolormap = XCreateColormap (xdisplay, xrootwin,
203                                             xvisual, (allocate) ? (AllocAll) : (AllocNone));
204
205       if (allocate)
206         {
207           GdkVisual *system_visual;
208           XColor *default_colors;
209           gint n_default_colors;
210
211           system_visual = gdk_screen_get_system_visual (private->screen);
212           n_default_colors = MIN (system_visual->colormap_size, colormap->size);
213
214           default_colors = g_new (XColor, colormap->size);
215
216           for (i = 0; i < n_default_colors; i++)
217             default_colors[i].pixel = i;
218           
219           XQueryColors (xdisplay,
220                         DefaultColormapOfScreen (GDK_SCREEN_X11 (private->screen)->xscreen),
221                         default_colors, n_default_colors);
222
223           for (i = 0; i < n_default_colors; i++)
224             {
225               colormap->colors[i].pixel = default_colors[i].pixel;
226               colormap->colors[i].red = default_colors[i].red;
227               colormap->colors[i].green = default_colors[i].green;
228               colormap->colors[i].blue = default_colors[i].blue;
229             }
230
231           gdk_colormap_change (colormap, n_default_colors);
232           
233           g_free (default_colors);
234         }
235       break;
236
237     case GDK_VISUAL_DIRECT_COLOR:
238       private->private_val = TRUE;
239       private->xcolormap = XCreateColormap (xdisplay, xrootwin,
240                                             xvisual, AllocAll);
241       colormap->colors = g_new (GdkColor, colormap->size);
242
243       size = 1 << visual->red_prec;
244       for (i = 0; i < size; i++)
245         colormap->colors[i].red = i * 65535 / (size - 1);
246
247       size = 1 << visual->green_prec;
248       for (i = 0; i < size; i++)
249         colormap->colors[i].green = i * 65535 / (size - 1);
250
251       size = 1 << visual->blue_prec;
252       for (i = 0; i < size; i++)
253         colormap->colors[i].blue = i * 65535 / (size - 1);
254
255       gdk_colormap_change (colormap, colormap->size);
256       break;
257
258     case GDK_VISUAL_STATIC_GRAY:
259     case GDK_VISUAL_STATIC_COLOR:
260       private->private_val = FALSE;
261       private->xcolormap = XCreateColormap (xdisplay, xrootwin,
262                                             xvisual, AllocNone);
263       
264       colormap->colors = g_new (GdkColor, colormap->size);
265       gdk_colormap_sync (colormap, TRUE);
266       break;
267       
268     case GDK_VISUAL_TRUE_COLOR:
269       private->private_val = FALSE;
270       private->xcolormap = XCreateColormap (xdisplay, xrootwin,
271                                             xvisual, AllocNone);
272       break;
273     }
274
275   gdk_colormap_add (colormap);
276
277   return colormap;
278 }
279
280 static void
281 gdk_colormap_sync_palette (GdkColormap *colormap)
282 {
283   GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
284   XColor *xpalette;
285   gint nlookup;
286   gint i;
287
288   nlookup = 0;
289   xpalette = g_new (XColor, colormap->size);
290   
291   for (i = 0; i < colormap->size; i++)
292     {
293       if (!private->info || private->info[i].ref_count == 0)
294         {
295           xpalette[nlookup].pixel = i;
296           xpalette[nlookup].red = 0;
297           xpalette[nlookup].green = 0;
298           xpalette[nlookup].blue = 0;
299           nlookup++;
300         }
301     }
302
303   XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
304                 private->xcolormap, xpalette, nlookup);
305   
306   for (i = 0; i < nlookup; i++)
307     {
308       gulong pixel = xpalette[i].pixel;
309       colormap->colors[pixel].pixel = pixel;
310       colormap->colors[pixel].red = xpalette[i].red;
311       colormap->colors[pixel].green = xpalette[i].green;
312       colormap->colors[pixel].blue = xpalette[i].blue;
313     }
314   
315   g_free (xpalette);
316 }
317
318 static void
319 gdk_colormap_sync_direct_color (GdkColormap *colormap)
320 {
321   GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
322   GdkVisual *visual = colormap->visual;
323   XColor *xpalette;
324   gint i;
325
326   xpalette = g_new (XColor, colormap->size);
327   
328   for (i = 0; i < colormap->size; i++)
329     {
330       xpalette[i].pixel =
331         (((i << visual->red_shift)   & visual->red_mask)   |
332          ((i << visual->green_shift) & visual->green_mask) |
333          ((i << visual->blue_shift)  & visual->blue_mask));
334     }
335
336   XQueryColors (GDK_SCREEN_XDISPLAY (private->screen),
337                 private->xcolormap, xpalette, colormap->size);
338   
339   for (i = 0; i < colormap->size; i++)
340     {
341       colormap->colors[i].pixel = xpalette[i].pixel;
342       colormap->colors[i].red = xpalette[i].red;
343       colormap->colors[i].green = xpalette[i].green;
344       colormap->colors[i].blue = xpalette[i].blue;
345     }
346   
347   g_free (xpalette);
348 }
349
350 #define MIN_SYNC_TIME 2
351
352 static void
353 gdk_colormap_sync (GdkColormap *colormap,
354                    gboolean     force)
355 {
356   time_t current_time;
357   GdkColormapPrivateX11 *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
358
359   g_return_if_fail (GDK_IS_COLORMAP (colormap));
360
361   if (private->screen->closed)
362     return;
363
364   current_time = time (NULL);
365   if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
366     return;
367
368   private->last_sync_time = current_time;
369
370   if (colormap->visual->type == GDK_VISUAL_DIRECT_COLOR)
371     gdk_colormap_sync_direct_color (colormap);
372   else
373     gdk_colormap_sync_palette (colormap);
374 }
375                    
376 /**
377  * gdk_screen_get_system_colormap:
378  * @screen: a #GdkScreen
379  *
380  * Gets the system's default colormap for @screen
381  *
382  * Returns: the default colormap for @screen.
383  *
384  * Since: 2.2
385  */
386 GdkColormap *
387 gdk_screen_get_system_colormap (GdkScreen *screen)
388 {
389   GdkColormap *colormap = NULL;
390   GdkColormapPrivateX11 *private;
391   GdkScreenX11 *screen_x11;
392
393   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
394   screen_x11 = GDK_SCREEN_X11 (screen);
395
396   if (screen_x11->system_colormap)
397     return screen_x11->system_colormap;
398
399   colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
400   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
401
402   private->screen = screen;
403   colormap->visual = gdk_screen_get_system_visual (screen);
404   
405   private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
406   private->private_val = FALSE;
407
408   private->hash = NULL;
409   private->last_sync_time = 0;
410   private->info = NULL;
411
412   colormap->colors = NULL;
413   colormap->size = colormap->visual->colormap_size;
414
415   switch (colormap->visual->type)
416     {
417     case GDK_VISUAL_GRAYSCALE:
418     case GDK_VISUAL_PSEUDO_COLOR:
419       private->info = g_new0 (GdkColorInfo, colormap->size);
420       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
421                                         (GEqualFunc) gdk_color_equal);
422       /* Fall through */
423     case GDK_VISUAL_STATIC_GRAY:
424     case GDK_VISUAL_STATIC_COLOR:
425     case GDK_VISUAL_DIRECT_COLOR:
426       colormap->colors = g_new (GdkColor, colormap->size);
427       gdk_colormap_sync (colormap, TRUE);
428       
429     case GDK_VISUAL_TRUE_COLOR:
430       break;
431     }
432   
433   gdk_colormap_add (colormap);
434   screen_x11->system_colormap = colormap;
435   
436   return colormap;
437 }
438
439 /**
440  * gdk_colormap_get_system_size:
441  * 
442  * Returns the size of the system's default colormap.
443  * (See the description of struct #GdkColormap for an
444  * explanation of the size of a colormap.)
445  * 
446  * Return value: the size of the system's default colormap.
447  **/
448 gint
449 gdk_colormap_get_system_size (void)
450 {
451   return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
452                        GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
453 }
454
455 /**
456  * gdk_colormap_change:
457  * @colormap: a #GdkColormap.
458  * @ncolors: the number of colors to change.
459  * 
460  * Changes the value of the first @ncolors in a private colormap
461  * to match the values in the <structfield>colors</structfield>
462  * array in the colormap. This function is obsolete and
463  * should not be used. See gdk_color_change().
464  **/
465 void
466 gdk_colormap_change (GdkColormap *colormap,
467                      gint         ncolors)
468 {
469   GdkColormapPrivateX11 *private;
470   GdkVisual *visual;
471   XColor *palette;
472   Display *xdisplay;
473   gint shift;
474   int max_colors;
475   int size;
476   int i;
477
478   g_return_if_fail (GDK_IS_COLORMAP (colormap));
479
480   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
481
482   if (private->screen->closed)
483     return;
484
485   xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
486   palette = g_new (XColor, ncolors);
487
488   switch (colormap->visual->type)
489     {
490     case GDK_VISUAL_GRAYSCALE:
491     case GDK_VISUAL_PSEUDO_COLOR:
492       for (i = 0; i < ncolors; i++)
493         {
494           palette[i].pixel = colormap->colors[i].pixel;
495           palette[i].red = colormap->colors[i].red;
496           palette[i].green = colormap->colors[i].green;
497           palette[i].blue = colormap->colors[i].blue;
498           palette[i].flags = DoRed | DoGreen | DoBlue;
499         }
500
501       XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
502       break;
503
504     case GDK_VISUAL_DIRECT_COLOR:
505       visual = colormap->visual;
506
507       shift = visual->red_shift;
508       max_colors = 1 << visual->red_prec;
509       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
510
511       for (i = 0; i < size; i++)
512         {
513           palette[i].pixel = i << shift;
514           palette[i].red = colormap->colors[i].red;
515           palette[i].flags = DoRed;
516         }
517
518       XStoreColors (xdisplay, private->xcolormap, palette, size);
519
520       shift = visual->green_shift;
521       max_colors = 1 << visual->green_prec;
522       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
523
524       for (i = 0; i < size; i++)
525         {
526           palette[i].pixel = i << shift;
527           palette[i].green = colormap->colors[i].green;
528           palette[i].flags = DoGreen;
529         }
530
531       XStoreColors (xdisplay, private->xcolormap, palette, size);
532
533       shift = visual->blue_shift;
534       max_colors = 1 << visual->blue_prec;
535       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
536
537       for (i = 0; i < size; i++)
538         {
539           palette[i].pixel = i << shift;
540           palette[i].blue = colormap->colors[i].blue;
541           palette[i].flags = DoBlue;
542         }
543
544       XStoreColors (xdisplay, private->xcolormap, palette, size);
545       break;
546
547     default:
548       break;
549     }
550
551   g_free (palette);
552 }
553
554 /**
555  * gdk_colors_alloc:
556  * @colormap: a #GdkColormap.
557  * @contiguous: if %TRUE, the colors should be allocated
558  *    in contiguous color cells.
559  * @planes: an array in which to store the plane masks.
560  * @nplanes: the number of planes to allocate. (Or zero,
561  *    to indicate that the color allocation should not be planar.)
562  * @pixels: an array into which to store allocated pixel values.
563  * @npixels: the number of pixels in each plane to allocate.
564  * 
565  * Allocates colors from a colormap. This function
566  * is obsolete. See gdk_colormap_alloc_colors().
567  * For full documentation of the fields, see 
568  * the Xlib documentation for <function>XAllocColorCells()</function>.
569  * 
570  * Return value: 
571  **/
572 gboolean
573 gdk_colors_alloc (GdkColormap   *colormap,
574                   gboolean       contiguous,
575                   gulong        *planes,
576                   gint           nplanes,
577                   gulong        *pixels,
578                   gint           npixels)
579 {
580   GdkColormapPrivateX11 *private;
581   gint return_val;
582   gint i;
583
584   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
585
586   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
587
588   if (private->screen->closed)
589     return FALSE;
590
591   return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
592                                  private->xcolormap,contiguous, planes,
593                                  nplanes, pixels, npixels);
594   if (return_val)
595     {
596       for (i = 0; i < npixels; i++)
597         {
598           private->info[pixels[i]].ref_count++;
599           private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
600         }
601     }
602
603   return return_val != 0;
604 }
605
606 /* This is almost identical to gdk_colormap_free_colors.
607  * Keep them in sync!
608  */
609
610
611 /**
612  * gdk_colors_free:
613  * @colormap: a #GdkColormap.
614  * @pixels: the pixel values of the colors to free.
615  * @npixels: the number of values in @pixels.
616  * @planes: the plane masks for all planes to free, OR'd together.
617  * 
618  * Frees colors allocated with gdk_colors_alloc(). This
619  * function is obsolete. See gdk_colormap_free_colors().
620  **/
621 void
622 gdk_colors_free (GdkColormap *colormap,
623                  gulong      *pixels,
624                  gint         npixels,
625                  gulong       planes)
626 {
627   GdkColormapPrivateX11 *private;
628   gulong *pixels_to_free;
629   gint npixels_to_free = 0;
630   gint i;
631
632   g_return_if_fail (GDK_IS_COLORMAP (colormap));
633   g_return_if_fail (pixels != NULL);
634
635   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
636
637   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
638       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
639     return;
640   
641   pixels_to_free = g_new (gulong, npixels);
642
643   for (i = 0; i < npixels; i++)
644     {
645       gulong pixel = pixels[i];
646       
647       if (private->info[pixel].ref_count)
648         {
649           private->info[pixel].ref_count--;
650
651           if (private->info[pixel].ref_count == 0)
652             {
653               pixels_to_free[npixels_to_free++] = pixel;
654               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
655                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
656               private->info[pixel].flags = 0;
657             }
658         }
659     }
660
661   if (npixels_to_free && !private->private_val && !private->screen->closed)
662     XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
663                  pixels_to_free, npixels_to_free, planes);
664   g_free (pixels_to_free);
665 }
666
667 /* This is almost identical to gdk_colors_free.
668  * Keep them in sync!
669  */
670
671 /**
672  * gdk_colormap_free_colors:
673  * @colormap: a #GdkColormap.
674  * @colors: the colors to free.
675  * @ncolors: the number of colors in @colors.
676  * 
677  * Frees previously allocated colors.
678  **/
679 void
680 gdk_colormap_free_colors (GdkColormap *colormap,
681                           GdkColor    *colors,
682                           gint         ncolors)
683 {
684   GdkColormapPrivateX11 *private;
685   gulong *pixels;
686   gint npixels = 0;
687   gint i;
688
689   g_return_if_fail (GDK_IS_COLORMAP (colormap));
690   g_return_if_fail (colors != NULL);
691
692   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
693
694   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
695       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
696     return;
697
698   pixels = g_new (gulong, ncolors);
699
700   for (i = 0; i < ncolors; i++)
701     {
702       gulong pixel = colors[i].pixel;
703       
704       if (private->info[pixel].ref_count)
705         {
706           private->info[pixel].ref_count--;
707
708           if (private->info[pixel].ref_count == 0)
709             {
710               pixels[npixels++] = pixel;
711               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
712                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
713               private->info[pixel].flags = 0;
714             }
715         }
716     }
717
718   if (npixels && !private->private_val && !private->screen->closed)
719     XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
720                  pixels, npixels, 0);
721
722   g_free (pixels);
723 }
724
725 /********************
726  * Color allocation *
727  ********************/
728
729 /* Try to allocate a single color using XAllocColor. If it succeeds,
730  * cache the result in our colormap, and store in ret.
731  */
732 static gboolean 
733 gdk_colormap_alloc1 (GdkColormap *colormap,
734                      GdkColor    *color,
735                      GdkColor    *ret)
736 {
737   GdkColormapPrivateX11 *private;
738   XColor xcolor;
739
740   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
741
742   xcolor.red = color->red;
743   xcolor.green = color->green;
744   xcolor.blue = color->blue;
745   xcolor.pixel = color->pixel;
746   xcolor.flags = DoRed | DoGreen | DoBlue;
747
748   if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
749     {
750       ret->pixel = xcolor.pixel;
751       ret->red = xcolor.red;
752       ret->green = xcolor.green;
753       ret->blue = xcolor.blue;
754       
755       if (ret->pixel < colormap->size)
756         {
757           if (private->info[ret->pixel].ref_count) /* got a duplicate */
758             {
759               XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
760                            &xcolor.pixel, 1, 0);
761               private->info[ret->pixel].ref_count++;
762             }
763           else
764             {
765               colormap->colors[ret->pixel] = *color;
766               colormap->colors[ret->pixel].pixel = ret->pixel;
767               private->info[ret->pixel].ref_count = 1;
768
769               g_hash_table_insert (private->hash,
770                                    &colormap->colors[ret->pixel],
771                                    &colormap->colors[ret->pixel]);
772             }
773         }
774       return TRUE;
775     }
776   else
777     {
778       return FALSE;
779     }
780 }
781
782 static gint
783 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
784                                      GdkColor    *colors,
785                                      gint         ncolors,
786                                      gboolean     writeable,
787                                      gboolean     best_match,
788                                      gboolean    *success)
789 {
790   GdkColormapPrivateX11 *private;
791   gulong *pixels;
792   Status status;
793   gint i, index;
794
795   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
796
797   if (private->private_val)
798     {
799       index = 0;
800       for (i = 0; i < ncolors; i++)
801         {
802           while ((index < colormap->size) && (private->info[index].ref_count != 0))
803             index++;
804           
805           if (index < colormap->size)
806             {
807               colors[i].pixel = index;
808               success[i] = TRUE;
809               private->info[index].ref_count++;
810               private->info[i].flags |= GDK_COLOR_WRITEABLE;
811             }
812           else
813             break;
814         }
815       return ncolors - i;
816     }
817   else
818     {
819       pixels = g_new (gulong, ncolors);
820       /* Allocation of a writeable color cells */
821       
822       status =  XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
823                                   FALSE, NULL, 0, pixels, ncolors);
824       if (status)
825         {
826           for (i = 0; i < ncolors; i++)
827             {
828               colors[i].pixel = pixels[i];
829               success[i] = TRUE;
830               private->info[pixels[i]].ref_count++;
831               private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
832             }
833         }
834       
835       g_free (pixels);
836
837       return status ? 0 : ncolors; 
838     }
839 }
840
841 static gint
842 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
843                                    GdkColor    *colors,
844                                    gint         ncolors,
845                                    gboolean     writeable,
846                                    gboolean     best_match,
847                                    gboolean    *success)
848 {
849   GdkColormapPrivateX11 *private;
850   gint i, index;
851   XColor *store = g_new (XColor, ncolors);
852   gint nstore = 0;
853   gint nremaining = 0;
854   
855   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
856
857   /* First, store the colors we have room for */
858
859   index = 0;
860   for (i = 0; i < ncolors; i++)
861     {
862       if (!success[i])
863         {
864           while ((index < colormap->size) && (private->info[index].ref_count != 0))
865             index++;
866
867           if (index < colormap->size)
868             {
869               store[nstore].red = colors[i].red;
870               store[nstore].blue = colors[i].blue;
871               store[nstore].green = colors[i].green;
872               store[nstore].pixel = index;
873               store[nstore].flags = DoRed | DoGreen | DoBlue;
874               nstore++;
875
876               success[i] = TRUE;
877               colors[i].pixel = index;
878
879               colormap->colors[i] = colors[i];
880               private->info[index].ref_count++;
881
882               g_hash_table_insert (private->hash,
883                                    &colormap->colors[index],
884                                    &colormap->colors[index]);
885             }
886           else
887             nremaining++;
888         }
889     }
890   
891   XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
892                 store, nstore);
893   g_free (store);
894
895   if (nremaining > 0 && best_match)
896     {
897       /* Get best matches for remaining colors */
898
899       gchar *available = g_new (gchar, colormap->size);
900       for (i = 0; i < colormap->size; i++)
901         available[i] = !(private->info[i].flags & GDK_COLOR_WRITEABLE);
902
903       for (i = 0; i < ncolors; i++)
904         {
905           if (!success[i])
906             {
907               index = gdk_colormap_match_color (colormap, 
908                                                 &colors[i], 
909                                                 available);
910               if (index != -1)
911                 {
912                   colors[i] = colormap->colors[index];
913                   private->info[index].ref_count++;
914
915                   success[i] = TRUE;
916                   nremaining--;
917                 }
918             }
919         }
920       g_free (available);
921     }
922
923   return nremaining;
924 }
925
926 static gint
927 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
928                                   GdkColor    *colors,
929                                   gint         ncolors,
930                                   gboolean     writeable,
931                                   gboolean     best_match,
932                                   gboolean    *success)
933 {
934   GdkColormapPrivateX11 *private;
935   gint i, index;
936   gint nremaining = 0;
937   gint nfailed = 0;
938
939   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
940
941   for (i = 0; i < ncolors; i++)
942     {
943       if (!success[i])
944         {
945           if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
946             success[i] = TRUE;
947           else
948             nremaining++;
949         }
950     }
951
952
953   if (nremaining > 0 && best_match)
954     {
955       gchar *available = g_new (gchar, colormap->size);
956       for (i = 0; i < colormap->size; i++)
957         available[i] = ((private->info[i].ref_count == 0) ||
958                         !(private->info[i].flags & GDK_COLOR_WRITEABLE));
959       gdk_colormap_sync (colormap, FALSE);
960       
961       while (nremaining > 0)
962         {
963           for (i = 0; i < ncolors; i++)
964             {
965               if (!success[i])
966                 {
967                   index = gdk_colormap_match_color (colormap, &colors[i], available);
968                   if (index != -1)
969                     {
970                       if (private->info[index].ref_count)
971                         {
972                           private->info[index].ref_count++;
973                           colors[i] = colormap->colors[index];
974                           success[i] = TRUE;
975                           nremaining--;
976                         }
977                       else
978                         {
979                           if (gdk_colormap_alloc1 (colormap, 
980                                                    &colormap->colors[index],
981                                                    &colors[i]))
982                             {
983                               success[i] = TRUE;
984                               nremaining--;
985                               break;
986                             }
987                           else
988                             {
989                               available[index] = FALSE;
990                             }
991                         }
992                     }
993                   else
994                     {
995                       nfailed++;
996                       nremaining--;
997                       success[i] = 2; /* flag as permanent failure */
998                     }
999                 }
1000             }
1001         }
1002       g_free (available);
1003     }
1004
1005   /* Change back the values we flagged as permanent failures */
1006   if (nfailed > 0)
1007     {
1008       for (i = 0; i < ncolors; i++)
1009         if (success[i] == 2)
1010           success[i] = FALSE;
1011       nremaining = nfailed;
1012     }
1013   
1014   return nremaining;
1015 }
1016
1017 static gint
1018 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1019                                        GdkColor    *colors,
1020                                        gint         ncolors,
1021                                        gboolean     writeable,
1022                                        gboolean     best_match,
1023                                        gboolean    *success)
1024 {
1025   GdkColormapPrivateX11 *private;
1026   GdkColor *lookup_color;
1027   gint i;
1028   gint nremaining = 0;
1029
1030   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1031
1032   /* Check for an exact match among previously allocated colors */
1033
1034   for (i = 0; i < ncolors; i++)
1035     {
1036       if (!success[i])
1037         {
1038           lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1039           if (lookup_color)
1040             {
1041               private->info[lookup_color->pixel].ref_count++;
1042               colors[i].pixel = lookup_color->pixel;
1043               success[i] = TRUE;
1044             }
1045           else
1046             nremaining++;
1047         }
1048     }
1049
1050   /* If that failed, we try to allocate a new color, or approxmiate
1051    * with what we can get if best_match is TRUE.
1052    */
1053   if (nremaining > 0)
1054     {
1055       if (private->private_val)
1056         return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1057       else
1058         return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1059     }
1060   else
1061     return 0;
1062 }
1063
1064 /**
1065  * gdk_colormap_alloc_colors:
1066  * @colormap: a #GdkColormap.
1067  * @colors: The color values to allocate. On return, the pixel
1068  *    values for allocated colors will be filled in.
1069  * @ncolors: The number of colors in @colors.
1070  * @writeable: If %TRUE, the colors are allocated writeable
1071  *    (their values can later be changed using gdk_color_change()).
1072  *    Writeable colors cannot be shared between applications.
1073  * @best_match: If %TRUE, GDK will attempt to do matching against
1074  *    existing colors if the colors cannot be allocated as requested.
1075  * @success: An array of length @ncolors. On return, this
1076  *   indicates whether the corresponding color in @colors was
1077  *   sucessfully allocated or not.
1078  * 
1079  * Allocates colors from a colormap.
1080  * 
1081  * Return value: The number of colors that were not sucessfully 
1082  * allocated.
1083  **/
1084 gint
1085 gdk_colormap_alloc_colors (GdkColormap *colormap,
1086                            GdkColor    *colors,
1087                            gint         ncolors,
1088                            gboolean     writeable,
1089                            gboolean     best_match,
1090                            gboolean    *success)
1091 {
1092   GdkColormapPrivateX11 *private;
1093   GdkVisual *visual;
1094   gint i;
1095   gint nremaining = 0;
1096   XColor xcolor;
1097
1098   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1099   g_return_val_if_fail (colors != NULL, ncolors);
1100   g_return_val_if_fail (success != NULL, ncolors);
1101
1102   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1103
1104   if (private->screen->closed)
1105     return ncolors;
1106
1107   for (i = 0; i < ncolors; i++)
1108     success[i] = FALSE;
1109
1110   switch (colormap->visual->type)
1111     {
1112     case GDK_VISUAL_PSEUDO_COLOR:
1113     case GDK_VISUAL_GRAYSCALE:
1114       if (writeable)
1115         return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1116                                                     writeable, best_match, success);
1117       else
1118         return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1119                                                     writeable, best_match, success);
1120       break;
1121
1122     case GDK_VISUAL_DIRECT_COLOR:
1123     case GDK_VISUAL_TRUE_COLOR:
1124       visual = colormap->visual;
1125
1126       for (i = 0; i < ncolors; i++)
1127         {
1128           colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1129                              ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1130                              ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1131           success[i] = TRUE;
1132         }
1133       break;
1134     case GDK_VISUAL_STATIC_GRAY:
1135     case GDK_VISUAL_STATIC_COLOR:
1136       for (i = 0; i < ncolors; i++)
1137         {
1138           xcolor.red = colors[i].red;
1139           xcolor.green = colors[i].green;
1140           xcolor.blue = colors[i].blue;
1141           xcolor.pixel = colors[i].pixel;
1142           xcolor.flags = DoRed | DoGreen | DoBlue;
1143
1144           if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1145             {
1146               colors[i].pixel = xcolor.pixel;
1147               success[i] = TRUE;
1148             }
1149           else
1150             nremaining++;
1151         }
1152       break;
1153     }
1154   return nremaining;
1155 }
1156
1157 /**
1158  * gdk_colormap_query_color:
1159  * @colormap: a #GdkColormap
1160  * @pixel: pixel value in hardware display format
1161  * @result: #GdkColor with red, green, blue fields initialized
1162  * 
1163  * Locates the RGB color in @colormap corresponding to the given
1164  * hardware pixel @pixel. @pixel must be a valid pixel in the
1165  * colormap; it's a programmer error to call this function with a
1166  * pixel which is not in the colormap. Hardware pixels are normally
1167  * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1168  * #GdkImage contains image data in hardware format, a #GdkPixbuf
1169  * contains image data in a canonical 24-bit RGB format.)
1170  *
1171  * This function is rarely useful; it's used for example to
1172  * implement the eyedropper feature in #GtkColorSelection.
1173  * 
1174  **/
1175 void
1176 gdk_colormap_query_color (GdkColormap *colormap,
1177                           gulong       pixel,
1178                           GdkColor    *result)
1179 {
1180   XColor xcolor;
1181   GdkVisual *visual;
1182   GdkColormapPrivateX11 *private;
1183   
1184   g_return_if_fail (GDK_IS_COLORMAP (colormap));
1185   
1186   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1187
1188   visual = gdk_colormap_get_visual (colormap);
1189
1190   switch (visual->type) {
1191   case GDK_VISUAL_DIRECT_COLOR:
1192   case GDK_VISUAL_TRUE_COLOR:
1193     result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1194     result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1195     result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1196     break;
1197   case GDK_VISUAL_STATIC_GRAY:
1198   case GDK_VISUAL_GRAYSCALE:
1199     result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1200     break;
1201   case GDK_VISUAL_STATIC_COLOR:
1202     xcolor.pixel = pixel;
1203     if (!private->screen->closed)
1204       {
1205         XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1206         result->red = xcolor.red;
1207         result->green = xcolor.green;
1208         result->blue =  xcolor.blue;
1209       }
1210     else
1211       result->red = result->green = result->blue = 0;
1212     break;
1213   case GDK_VISUAL_PSEUDO_COLOR:
1214     g_return_if_fail (pixel < colormap->size);
1215     result->red = colormap->colors[pixel].red;
1216     result->green = colormap->colors[pixel].green;
1217     result->blue = colormap->colors[pixel].blue;
1218     break;
1219   default:
1220     g_assert_not_reached ();
1221     break;
1222   }
1223 }
1224
1225 /**
1226  * gdk_color_change:
1227  * @colormap: a #GdkColormap.
1228  * @color: a #GdkColor, with the color to change
1229  * in the <structfield>pixel</structfield> field,
1230  * and the new value in the remaining fields.
1231  * 
1232  * Changes the value of a color that has already
1233  * been allocated. If @colormap is not a private
1234  * colormap, then the color must have been allocated
1235  * using gdk_colormap_alloc_colors() with the 
1236  * @writeable set to %TRUE.
1237  * 
1238  * Return value: %TRUE if the color was successfully changed.
1239  **/
1240 gboolean
1241 gdk_color_change (GdkColormap *colormap,
1242                   GdkColor    *color)
1243 {
1244   GdkColormapPrivateX11 *private;
1245   XColor xcolor;
1246
1247   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1248   g_return_val_if_fail (color != NULL, FALSE);
1249
1250   xcolor.pixel = color->pixel;
1251   xcolor.red = color->red;
1252   xcolor.green = color->green;
1253   xcolor.blue = color->blue;
1254   xcolor.flags = DoRed | DoGreen | DoBlue;
1255
1256   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1257   if (!private->screen->closed)
1258     XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1259
1260   return TRUE;
1261 }
1262
1263 /**
1264  * gdk_x11_colormap_foreign_new:
1265  * @visual: a #GdkVisual
1266  * @xcolormap: The XID of a colormap with visual @visual
1267  * 
1268  * If xcolormap refers to a colormap previously known to GTK+,
1269  * returns a new reference to the existing #GdkColormap object,
1270  * otherwise creates a new GdkColormap object and returns that
1271  *
1272  * Return value: the #GdkColormap object for @xcolormap.
1273  *   Free with g_object_unref(). Note that for colormap created
1274  *   with gdk_x11_colormap_foreign_new(), unref'ing the last
1275  *   reference to the object will only free the #GdkColoramp
1276  *   object and not call XFreeColormap()
1277  *
1278  * Since: 2.2
1279  **/
1280 GdkColormap *
1281 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1282                               Colormap   xcolormap)
1283 {
1284   GdkColormap *colormap;
1285   GdkScreen *screen;
1286   GdkColormapPrivateX11 *private;
1287   
1288   g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1289   g_return_val_if_fail (xcolormap != None, NULL);
1290
1291   screen = gdk_visual_get_screen (visual);
1292   
1293   if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1294                                     GDK_SCREEN_XNUMBER (screen)))
1295     return g_object_ref (gdk_screen_get_system_colormap (screen));
1296
1297   colormap = gdk_colormap_lookup (screen, xcolormap);
1298   if (colormap)
1299     return g_object_ref (colormap);
1300
1301   colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1302   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1303
1304   colormap->visual = visual;
1305
1306   private->screen = screen;
1307   private->xcolormap = xcolormap;
1308   private->private_val = FALSE;
1309
1310   colormap->size = visual->colormap_size;
1311
1312   switch (colormap->visual->type)
1313     {
1314     case GDK_VISUAL_GRAYSCALE:
1315     case GDK_VISUAL_PSEUDO_COLOR:
1316       private->info = g_new0 (GdkColorInfo, colormap->size);
1317       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1318                                         (GEqualFunc) gdk_color_equal);
1319       /* Fall through */
1320     case GDK_VISUAL_STATIC_GRAY:
1321     case GDK_VISUAL_STATIC_COLOR:
1322     case GDK_VISUAL_DIRECT_COLOR:
1323       colormap->colors = g_new (GdkColor, colormap->size);
1324       gdk_colormap_sync (colormap, TRUE);
1325       
1326     case GDK_VISUAL_TRUE_COLOR:
1327       break;
1328     }
1329
1330   gdk_colormap_add (colormap);
1331
1332   return colormap;
1333   
1334 }
1335
1336 /**
1337  * gdkx_colormap_get:
1338  * @xcolormap: the XID of a colormap for the default screen.
1339  * 
1340  * Returns a #GdkColormap corresponding to a X colormap;
1341  * this function only works if the colormap is already
1342  * known to GTK+ (a colormap created by GTK+ or the default
1343  * colormap for the screen), since GTK+ 
1344  *
1345  * Always use gdk_x11_colormap_foreign_new() instead.
1346  *
1347  * Return value: the existing #GdkColormap object if it was
1348  *  already known to GTK+, otherwise warns and return
1349  *  %NULL.
1350  **/
1351 GdkColormap*
1352 gdkx_colormap_get (Colormap xcolormap)
1353 {
1354   GdkScreen *screen = gdk_screen_get_default ();
1355   GdkColormap *colormap;
1356
1357   if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1358                                     GDK_SCREEN_XNUMBER (screen)));
1359     return g_object_ref (gdk_screen_get_system_colormap (screen));
1360
1361   colormap = gdk_colormap_lookup (screen, xcolormap);
1362   if (colormap)
1363     return g_object_ref (colormap);
1364
1365   g_warning ("Colormap passed to gdkx_colormap_get\n"
1366              "does not previously exist");
1367
1368   return NULL;
1369 }
1370
1371 static gint
1372 gdk_colormap_match_color (GdkColormap *cmap,
1373                           GdkColor    *color,
1374                           const gchar *available)
1375 {
1376   GdkColor *colors;
1377   guint sum, max;
1378   gint rdiff, gdiff, bdiff;
1379   gint i, index;
1380
1381   colors = cmap->colors;
1382   max = 3 * (65536);
1383   index = -1;
1384
1385   for (i = 0; i < cmap->size; i++)
1386     {
1387       if ((!available) || (available && available[i]))
1388         {
1389           rdiff = (color->red - colors[i].red);
1390           gdiff = (color->green - colors[i].green);
1391           bdiff = (color->blue - colors[i].blue);
1392
1393           sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1394
1395           if (sum < max)
1396             {
1397               index = i;
1398               max = sum;
1399             }
1400         }
1401     }
1402
1403   return index;
1404 }
1405
1406
1407 static GdkColormap*
1408 gdk_colormap_lookup (GdkScreen *screen,
1409                      Colormap   xcolormap)
1410 {
1411   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1412
1413   if (screen_x11->colormap_hash)
1414     return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1415   else
1416     return NULL;
1417 }
1418
1419 static void
1420 gdk_colormap_add (GdkColormap *cmap)
1421 {
1422   GdkScreenX11 *screen_x11;
1423   GdkColormapPrivateX11 *private;
1424
1425   private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1426   screen_x11 = GDK_SCREEN_X11 (private->screen);
1427
1428   if (!screen_x11->colormap_hash)
1429     screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1430                                                   (GEqualFunc) gdk_colormap_equal);
1431
1432   g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1433 }
1434
1435 static void
1436 gdk_colormap_remove (GdkColormap *cmap)
1437 {
1438   GdkScreenX11 *screen_x11;
1439   GdkColormapPrivateX11 *private;
1440
1441   private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1442   screen_x11 = GDK_SCREEN_X11 (private->screen);
1443
1444   if (screen_x11->colormap_hash)
1445     g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1446 }
1447
1448 static guint
1449 gdk_colormap_hash (Colormap *colormap)
1450 {
1451   return *colormap;
1452 }
1453
1454 static gboolean
1455 gdk_colormap_equal (Colormap *a,
1456                     Colormap *b)
1457 {
1458   return (*a == *b);
1459 }
1460
1461 /**
1462  * gdk_x11_colormap_get_xdisplay:
1463  * @colormap: a #GdkColormap.
1464  * 
1465  * Returns the display of a #GdkColormap.
1466  * 
1467  * Return value: an Xlib <type>Display*</type>.
1468  **/
1469 Display *
1470 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1471 {
1472   GdkColormapPrivateX11 *private;
1473
1474   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1475
1476   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1477
1478   return GDK_SCREEN_XDISPLAY (private->screen);
1479 }
1480
1481 /**
1482  * gdk_x11_colormap_get_xcolormap:
1483  * @colormap:  a #GdkColormap.
1484  * 
1485  * Returns the X colormap belonging to a #GdkColormap.
1486  * 
1487  * Return value: an Xlib <type>Colormap</type>.
1488  **/
1489 Colormap
1490 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1491 {
1492   GdkColormapPrivateX11 *private;
1493
1494   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1495
1496   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1497
1498   if (private->screen->closed)
1499     return None;
1500   else
1501     return private->xcolormap;
1502 }
1503
1504 /**
1505  * gdk_colormap_get_screen:
1506  * @cmap: a #GdkColormap
1507  * 
1508  * Gets the screen for which this colormap was created.
1509  * 
1510  * Return value: the screen for which this colormap was created.
1511  *
1512  * Since: 2.2
1513  **/
1514 GdkScreen *
1515 gdk_colormap_get_screen (GdkColormap *cmap)
1516 {
1517   g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1518
1519   return  GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;
1520 }