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