]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkcolor-x11.c
Document 2.2 API additions.
[~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  * Since: 2.2
381  */
382 GdkColormap *
383 gdk_screen_get_system_colormap (GdkScreen *screen)
384 {
385   GdkColormap *colormap = NULL;
386   GdkColormapPrivateX11 *private;
387   GdkScreenX11 *screen_x11;
388
389   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
390   screen_x11 = GDK_SCREEN_X11 (screen);
391
392   if (screen_x11->system_colormap)
393     return screen_x11->system_colormap;
394
395   colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
396   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
397
398   private->screen = screen;
399   colormap->visual = gdk_screen_get_system_visual (screen);
400   
401   private->xcolormap = DefaultColormapOfScreen (screen_x11->xscreen);
402   private->private_val = FALSE;
403
404   private->hash = NULL;
405   private->last_sync_time = 0;
406   private->info = NULL;
407
408   colormap->colors = NULL;
409   colormap->size = colormap->visual->colormap_size;
410
411   switch (colormap->visual->type)
412     {
413     case GDK_VISUAL_GRAYSCALE:
414     case GDK_VISUAL_PSEUDO_COLOR:
415       private->info = g_new0 (GdkColorInfo, colormap->size);
416       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
417                                         (GEqualFunc) gdk_color_equal);
418       /* Fall through */
419     case GDK_VISUAL_STATIC_GRAY:
420     case GDK_VISUAL_STATIC_COLOR:
421     case GDK_VISUAL_DIRECT_COLOR:
422       colormap->colors = g_new (GdkColor, colormap->size);
423       gdk_colormap_sync (colormap, TRUE);
424       
425     case GDK_VISUAL_TRUE_COLOR:
426       break;
427     }
428   
429   gdk_colormap_add (colormap);
430   screen_x11->system_colormap = colormap;
431   
432   return colormap;
433 }
434
435 /**
436  * gdk_colormap_get_system_size:
437  * 
438  * Returns the size of the system's default colormap.
439  * (See the description of struct #GdkColormap for an
440  * explanation of the size of a colormap.)
441  * 
442  * Return value: the size of the system's default colormap.
443  **/
444 gint
445 gdk_colormap_get_system_size (void)
446 {
447   return DisplayCells (GDK_SCREEN_XDISPLAY (gdk_screen_get_default()),
448                        GDK_SCREEN_X11 (gdk_screen_get_default())->screen_num);
449 }
450
451 /**
452  * gdk_colormap_change:
453  * @colormap: a #GdkColormap.
454  * @ncolors: the number of colors to change.
455  * 
456  * Changes the value of the first @ncolors in a private colormap
457  * to match the values in the <structfield>colors</structfield>
458  * array in the colormap. This function is obsolete and
459  * should not be used. See gdk_color_change().
460  **/
461 void
462 gdk_colormap_change (GdkColormap *colormap,
463                      gint         ncolors)
464 {
465   GdkColormapPrivateX11 *private;
466   GdkVisual *visual;
467   XColor *palette;
468   Display *xdisplay;
469   gint shift;
470   int max_colors;
471   int size;
472   int i;
473
474   g_return_if_fail (GDK_IS_COLORMAP (colormap));
475
476   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
477
478   if (private->screen->closed)
479     return;
480
481   xdisplay = GDK_SCREEN_XDISPLAY (private->screen);
482   palette = g_new (XColor, ncolors);
483
484   switch (colormap->visual->type)
485     {
486     case GDK_VISUAL_GRAYSCALE:
487     case GDK_VISUAL_PSEUDO_COLOR:
488       for (i = 0; i < ncolors; i++)
489         {
490           palette[i].pixel = colormap->colors[i].pixel;
491           palette[i].red = colormap->colors[i].red;
492           palette[i].green = colormap->colors[i].green;
493           palette[i].blue = colormap->colors[i].blue;
494           palette[i].flags = DoRed | DoGreen | DoBlue;
495         }
496
497       XStoreColors (xdisplay, private->xcolormap, palette, ncolors);
498       break;
499
500     case GDK_VISUAL_DIRECT_COLOR:
501       visual = colormap->visual;
502
503       shift = visual->red_shift;
504       max_colors = 1 << visual->red_prec;
505       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
506
507       for (i = 0; i < size; i++)
508         {
509           palette[i].pixel = i << shift;
510           palette[i].red = colormap->colors[i].red;
511           palette[i].flags = DoRed;
512         }
513
514       XStoreColors (xdisplay, private->xcolormap, palette, size);
515
516       shift = visual->green_shift;
517       max_colors = 1 << visual->green_prec;
518       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
519
520       for (i = 0; i < size; i++)
521         {
522           palette[i].pixel = i << shift;
523           palette[i].green = colormap->colors[i].green;
524           palette[i].flags = DoGreen;
525         }
526
527       XStoreColors (xdisplay, private->xcolormap, palette, size);
528
529       shift = visual->blue_shift;
530       max_colors = 1 << visual->blue_prec;
531       size = (ncolors < max_colors) ? (ncolors) : (max_colors);
532
533       for (i = 0; i < size; i++)
534         {
535           palette[i].pixel = i << shift;
536           palette[i].blue = colormap->colors[i].blue;
537           palette[i].flags = DoBlue;
538         }
539
540       XStoreColors (xdisplay, private->xcolormap, palette, size);
541       break;
542
543     default:
544       break;
545     }
546
547   g_free (palette);
548 }
549
550 /**
551  * gdk_colors_alloc:
552  * @colormap: a #GdkColormap.
553  * @contiguous: if %TRUE, the colors should be allocated
554  *    in contiguous color cells.
555  * @planes: an array in which to store the plane masks.
556  * @nplanes: the number of planes to allocate. (Or zero,
557  *    to indicate that the color allocation should not be planar.)
558  * @pixels: an array into which to store allocated pixel values.
559  * @npixels: the number of pixels in each plane to allocate.
560  * 
561  * Allocates colors from a colormap. This function
562  * is obsolete. See gdk_colormap_alloc_colors().
563  * For full documentation of the fields, see 
564  * the Xlib documentation for <function>XAllocColorCells()</function>.
565  * 
566  * Return value: 
567  **/
568 gboolean
569 gdk_colors_alloc (GdkColormap   *colormap,
570                   gboolean       contiguous,
571                   gulong        *planes,
572                   gint           nplanes,
573                   gulong        *pixels,
574                   gint           npixels)
575 {
576   GdkColormapPrivateX11 *private;
577   gint return_val;
578   gint i;
579
580   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), 0);
581
582   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
583
584   if (private->screen->closed)
585     return FALSE;
586
587   return_val = XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen),
588                                  private->xcolormap,contiguous, planes,
589                                  nplanes, pixels, npixels);
590   if (return_val)
591     {
592       for (i=0; i<npixels; i++)
593         {
594           private->info[pixels[i]].ref_count++;
595           private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
596         }
597     }
598
599   return return_val != 0;
600 }
601
602 /* This is almost identical to gdk_colormap_free_colors.
603  * Keep them in sync!
604  */
605
606
607 /**
608  * gdk_colors_free:
609  * @colormap: a #GdkColormap.
610  * @pixels: the pixel values of the colors to free.
611  * @npixels: the number of values in @pixels.
612  * @planes: the plane masks for all planes to free, OR'd together.
613  * 
614  * Frees colors allocated with gdk_colors_alloc(). This
615  * function is obsolete. See gdk_colormap_free_colors().
616  **/
617 void
618 gdk_colors_free (GdkColormap *colormap,
619                  gulong      *pixels,
620                  gint         npixels,
621                  gulong       planes)
622 {
623   GdkColormapPrivateX11 *private;
624   gulong *pixels_to_free;
625   gint npixels_to_free = 0;
626   gint i;
627
628   g_return_if_fail (GDK_IS_COLORMAP (colormap));
629   g_return_if_fail (pixels != NULL);
630
631   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
632
633   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
634       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
635     return;
636   
637   pixels_to_free = g_new (gulong, npixels);
638
639   for (i=0; i<npixels; i++)
640     {
641       gulong pixel = pixels[i];
642       
643       if (private->info[pixel].ref_count)
644         {
645           private->info[pixel].ref_count--;
646
647           if (private->info[pixel].ref_count == 0)
648             {
649               pixels_to_free[npixels_to_free++] = pixel;
650               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
651                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
652               private->info[pixel].flags = 0;
653             }
654         }
655     }
656
657   if (npixels_to_free && !private->screen->closed)
658     XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
659                  pixels_to_free, npixels_to_free, planes);
660   g_free (pixels_to_free);
661 }
662
663 /* This is almost identical to gdk_colors_free.
664  * Keep them in sync!
665  */
666
667 /**
668  * gdk_colormap_free_colors:
669  * @colormap: a #GdkColormap.
670  * @colors: the colors to free.
671  * @ncolors: the number of colors in @colors.
672  * 
673  * Frees previously allocated colors.
674  **/
675 void
676 gdk_colormap_free_colors (GdkColormap *colormap,
677                           GdkColor    *colors,
678                           gint         ncolors)
679 {
680   GdkColormapPrivateX11 *private;
681   gulong *pixels;
682   gint npixels = 0;
683   gint i;
684
685   g_return_if_fail (GDK_IS_COLORMAP (colormap));
686   g_return_if_fail (colors != NULL);
687
688   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
689
690   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
691       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
692     return;
693
694   pixels = g_new (gulong, ncolors);
695
696   for (i=0; i<ncolors; i++)
697     {
698       gulong pixel = colors[i].pixel;
699       
700       if (private->info[pixel].ref_count)
701         {
702           private->info[pixel].ref_count--;
703
704           if (private->info[pixel].ref_count == 0)
705             {
706               pixels[npixels++] = pixel;
707               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
708                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
709               private->info[pixel].flags = 0;
710             }
711         }
712     }
713
714   if (npixels && !private->screen->closed)
715     XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
716                  pixels, npixels, 0);
717
718   g_free (pixels);
719 }
720
721 /********************
722  * Color allocation *
723  ********************/
724
725 /* Try to allocate a single color using XAllocColor. If it succeeds,
726  * cache the result in our colormap, and store in ret.
727  */
728 static gboolean 
729 gdk_colormap_alloc1 (GdkColormap *colormap,
730                      GdkColor    *color,
731                      GdkColor    *ret)
732 {
733   GdkColormapPrivateX11 *private;
734   XColor xcolor;
735
736   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
737
738   xcolor.red = color->red;
739   xcolor.green = color->green;
740   xcolor.blue = color->blue;
741   xcolor.pixel = color->pixel;
742   xcolor.flags = DoRed | DoGreen | DoBlue;
743
744   if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
745     {
746       ret->pixel = xcolor.pixel;
747       ret->red = xcolor.red;
748       ret->green = xcolor.green;
749       ret->blue = xcolor.blue;
750       
751       if (ret->pixel < colormap->size)
752         {
753           if (private->info[ret->pixel].ref_count) /* got a duplicate */
754             {
755               XFreeColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
756                            &xcolor.pixel, 1, 0);
757             }
758           else
759             {
760               colormap->colors[ret->pixel] = *color;
761               colormap->colors[ret->pixel].pixel = ret->pixel;
762               private->info[ret->pixel].ref_count = 1;
763
764               g_hash_table_insert (private->hash,
765                                    &colormap->colors[ret->pixel],
766                                    &colormap->colors[ret->pixel]);
767             }
768         }
769       return TRUE;
770     }
771   else
772     {
773       return FALSE;
774     }
775 }
776
777 static gint
778 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
779                                      GdkColor    *colors,
780                                      gint         ncolors,
781                                      gboolean     writeable,
782                                      gboolean     best_match,
783                                      gboolean    *success)
784 {
785   GdkColormapPrivateX11 *private;
786   gulong *pixels;
787   Status status;
788   gint i, index;
789
790   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
791
792   if (private->private_val)
793     {
794       index = 0;
795       for (i=0; i<ncolors; i++)
796         {
797           while ((index < colormap->size) && (private->info[index].ref_count != 0))
798             index++;
799           
800           if (index < colormap->size)
801             {
802               colors[i].pixel = index;
803               success[i] = TRUE;
804               private->info[index].ref_count++;
805               private->info[i].flags |= GDK_COLOR_WRITEABLE;
806             }
807           else
808             break;
809         }
810       return i;
811     }
812   else
813     {
814       pixels = g_new (gulong, ncolors);
815       /* Allocation of a writeable color cells */
816       
817       status =  XAllocColorCells (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
818                                   FALSE, NULL, 0, pixels, ncolors);
819       if (status)
820         {
821           for (i=0; i<ncolors; i++)
822             {
823               colors[i].pixel = pixels[i];
824               private->info[pixels[i]].ref_count++;
825               private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
826             }
827         }
828       
829       g_free (pixels);
830
831       return status ? ncolors : 0; 
832     }
833 }
834
835 static gint
836 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
837                                    GdkColor    *colors,
838                                    gint         ncolors,
839                                    gboolean     writeable,
840                                    gboolean     best_match,
841                                    gboolean    *success)
842 {
843   GdkColormapPrivateX11 *private;
844   gint i, index;
845   XColor *store = g_new (XColor, ncolors);
846   gint nstore = 0;
847   gint nremaining = 0;
848   
849   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
850   index = -1;
851
852   /* First, store the colors we have room for */
853
854   index = 0;
855   for (i=0; i<ncolors; i++)
856     {
857       if (!success[i])
858         {
859           while ((index < colormap->size) && (private->info[index].ref_count != 0))
860             index++;
861
862           if (index < colormap->size)
863             {
864               store[nstore].red = colors[i].red;
865               store[nstore].blue = colors[i].blue;
866               store[nstore].green = colors[i].green;
867               store[nstore].pixel = index;
868               nstore++;
869
870               success[i] = TRUE;
871
872               colors[i].pixel = index;
873               private->info[index].ref_count++;
874             }
875           else
876             nremaining++;
877         }
878     }
879   
880   XStoreColors (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap,
881                 store, nstore);
882   g_free (store);
883
884   if (nremaining > 0 && best_match)
885     {
886       /* Get best matches for remaining colors */
887
888       gchar *available = g_new (gchar, colormap->size);
889       for (i = 0; i < colormap->size; i++)
890         available[i] = TRUE;
891
892       for (i=0; i<ncolors; i++)
893         {
894           if (!success[i])
895             {
896               index = gdk_colormap_match_color (colormap, 
897                                                 &colors[i], 
898                                                 available);
899               if (index != -1)
900                 {
901                   colors[i] = colormap->colors[index];
902                   private->info[index].ref_count++;
903
904                   success[i] = TRUE;
905                   nremaining--;
906                 }
907             }
908         }
909       g_free (available);
910     }
911
912   return (ncolors - nremaining);
913 }
914
915 static gint
916 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
917                                   GdkColor    *colors,
918                                   gint         ncolors,
919                                   gboolean     writeable,
920                                   gboolean     best_match,
921                                   gboolean    *success)
922 {
923   GdkColormapPrivateX11 *private;
924   gint i, index;
925   gint nremaining = 0;
926   gint nfailed = 0;
927
928   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
929   index = -1;
930
931   for (i=0; i<ncolors; i++)
932     {
933       if (!success[i])
934         {
935           if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
936             success[i] = TRUE;
937           else
938             nremaining++;
939         }
940     }
941
942
943   if (nremaining > 0 && best_match)
944     {
945       gchar *available = g_new (gchar, colormap->size);
946       for (i = 0; i < colormap->size; i++)
947         available[i] = ((private->info[i].ref_count == 0) ||
948                         !(private->info[i].flags & GDK_COLOR_WRITEABLE));
949       gdk_colormap_sync (colormap, FALSE);
950       
951       while (nremaining > 0)
952         {
953           for (i=0; i<ncolors; i++)
954             {
955               if (!success[i])
956                 {
957                   index = gdk_colormap_match_color (colormap, &colors[i], available);
958                   if (index != -1)
959                     {
960                       if (private->info[index].ref_count)
961                         {
962                           private->info[index].ref_count++;
963                           colors[i] = colormap->colors[index];
964                           success[i] = TRUE;
965                           nremaining--;
966                         }
967                       else
968                         {
969                           if (gdk_colormap_alloc1 (colormap, 
970                                                    &colormap->colors[index],
971                                                    &colors[i]))
972                             {
973                               success[i] = TRUE;
974                               nremaining--;
975                               break;
976                             }
977                           else
978                             {
979                               available[index] = FALSE;
980                             }
981                         }
982                     }
983                   else
984                     {
985                       nfailed++;
986                       nremaining--;
987                       success[i] = 2; /* flag as permanent failure */
988                     }
989                 }
990             }
991         }
992       g_free (available);
993     }
994
995   /* Change back the values we flagged as permanent failures */
996   if (nfailed > 0)
997     {
998       for (i=0; i<ncolors; i++)
999         if (success[i] == 2)
1000           success[i] = FALSE;
1001       nremaining = nfailed;
1002     }
1003   
1004   return (ncolors - nremaining);
1005 }
1006
1007 static gint
1008 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
1009                                        GdkColor    *colors,
1010                                        gint         ncolors,
1011                                        gboolean     writeable,
1012                                        gboolean     best_match,
1013                                        gboolean    *success)
1014 {
1015   GdkColormapPrivateX11 *private;
1016   GdkColor *lookup_color;
1017   gint i;
1018   gint nremaining = 0;
1019
1020   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1021
1022   /* Check for an exact match among previously allocated colors */
1023
1024   for (i=0; i<ncolors; i++)
1025     {
1026       if (!success[i])
1027         {
1028           lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
1029           if (lookup_color)
1030             {
1031               private->info[lookup_color->pixel].ref_count++;
1032               colors[i].pixel = lookup_color->pixel;
1033               success[i] = TRUE;
1034             }
1035           else
1036             nremaining++;
1037         }
1038     }
1039
1040   /* If that failed, we try to allocate a new color, or approxmiate
1041    * with what we can get if best_match is TRUE.
1042    */
1043   if (nremaining > 0)
1044     {
1045       if (private->private_val)
1046         return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
1047       else
1048         return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
1049     }
1050   else
1051     return 0;
1052 }
1053
1054 /**
1055  * gdk_colormap_alloc_colors:
1056  * @colormap: a #GdkColormap.
1057  * @colors: The color values to allocate. On return, the pixel
1058  *    values for allocated colors will be filled in.
1059  * @ncolors: The number of colors in @colors.
1060  * @writeable: If %TRUE, the colors are allocated writeable
1061  *    (their values can later be changed using gdk_color_change()).
1062  *    Writeable colors cannot be shared between applications.
1063  * @best_match: If %TRUE, GDK will attempt to do matching against
1064  *    existing colors if the colors cannot be allocated as requested.
1065  * @success: An array of length @ncolors. On return, this
1066  *   indicates whether the corresponding color in @colors was
1067  *   sucessfully allocated or not.
1068  * 
1069  * Allocates colors from a colormap.
1070  * 
1071  * Return value: The number of colors that were not sucessfully 
1072  * allocated.
1073  **/
1074 gint
1075 gdk_colormap_alloc_colors (GdkColormap *colormap,
1076                            GdkColor    *colors,
1077                            gint         ncolors,
1078                            gboolean     writeable,
1079                            gboolean     best_match,
1080                            gboolean    *success)
1081 {
1082   GdkColormapPrivateX11 *private;
1083   GdkVisual *visual;
1084   gint i;
1085   gint nremaining = 0;
1086   XColor xcolor;
1087
1088   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), ncolors);
1089   g_return_val_if_fail (colors != NULL, ncolors);
1090
1091   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1092
1093   if (private->screen->closed)
1094     return ncolors;
1095
1096   for (i=0; i<ncolors; i++)
1097     {
1098       success[i] = FALSE;
1099     }
1100
1101   switch (colormap->visual->type)
1102     {
1103     case GDK_VISUAL_PSEUDO_COLOR:
1104     case GDK_VISUAL_GRAYSCALE:
1105       if (writeable)
1106         return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
1107                                                     writeable, best_match, success);
1108       else
1109         return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
1110                                                     writeable, best_match, success);
1111       break;
1112
1113     case GDK_VISUAL_DIRECT_COLOR:
1114     case GDK_VISUAL_TRUE_COLOR:
1115       visual = colormap->visual;
1116
1117       for (i=0; i<ncolors; i++)
1118         {
1119           colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
1120                              ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
1121                              ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
1122           success[i] = TRUE;
1123         }
1124       break;
1125     case GDK_VISUAL_STATIC_GRAY:
1126     case GDK_VISUAL_STATIC_COLOR:
1127       for (i=0; i<ncolors; i++)
1128         {
1129           xcolor.red = colors[i].red;
1130           xcolor.green = colors[i].green;
1131           xcolor.blue = colors[i].blue;
1132           xcolor.pixel = colors[i].pixel;
1133           xcolor.flags = DoRed | DoGreen | DoBlue;
1134
1135           if (XAllocColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor))
1136             {
1137               colors[i].pixel = xcolor.pixel;
1138               success[i] = TRUE;
1139             }
1140           else
1141             nremaining++;
1142         }
1143       break;
1144     }
1145   return nremaining;
1146 }
1147
1148 /**
1149  * gdk_colormap_query_color:
1150  * @colormap: a #GdkColormap
1151  * @pixel: pixel value in hardware display format
1152  * @result: #GdkColor with red, green, blue fields initialized
1153  * 
1154  * Locates the RGB color in @colormap corresponding to the given
1155  * hardware pixel @pixel. @pixel must be a valid pixel in the
1156  * colormap; it's a programmer error to call this function with a
1157  * pixel which is not in the colormap. Hardware pixels are normally
1158  * obtained from gdk_colormap_alloc_colors(), or from a #GdkImage. (A
1159  * #GdkImage contains image data in hardware format, a #GdkPixbuf
1160  * contains image data in a canonical 24-bit RGB format.)
1161  *
1162  * This function is rarely useful; it's used for example to
1163  * implement the eyedropper feature in #GtkColorSelection.
1164  * 
1165  **/
1166 void
1167 gdk_colormap_query_color (GdkColormap *colormap,
1168                           gulong       pixel,
1169                           GdkColor    *result)
1170 {
1171   XColor xcolor;
1172   GdkVisual *visual;
1173   GdkColormapPrivateX11 *private;
1174   
1175   g_return_if_fail (GDK_IS_COLORMAP (colormap));
1176   
1177   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1178
1179   visual = gdk_colormap_get_visual (colormap);
1180
1181   switch (visual->type) {
1182   case GDK_VISUAL_DIRECT_COLOR:
1183   case GDK_VISUAL_TRUE_COLOR:
1184     result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
1185     result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
1186     result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
1187     break;
1188   case GDK_VISUAL_STATIC_GRAY:
1189   case GDK_VISUAL_GRAYSCALE:
1190     result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
1191     break;
1192   case GDK_VISUAL_STATIC_COLOR:
1193     xcolor.pixel = pixel;
1194     if (!private->screen->closed)
1195       {
1196         XQueryColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1197         result->red = xcolor.red;
1198         result->green = xcolor.green;
1199         result->blue =  xcolor.blue;
1200       }
1201     else
1202       result->red = result->green = result->blue = 0;
1203     break;
1204   case GDK_VISUAL_PSEUDO_COLOR:
1205     g_return_if_fail (pixel < colormap->size);
1206     result->red = colormap->colors[pixel].red;
1207     result->green = colormap->colors[pixel].green;
1208     result->blue = colormap->colors[pixel].blue;
1209     break;
1210   default:
1211     g_assert_not_reached ();
1212     break;
1213   }
1214 }
1215
1216 /**
1217  * gdk_color_change:
1218  * @colormap: a #GdkColormap.
1219  * @color: a #GdkColor, with the color to change
1220  * in the <structfield>pixel</structfield> field,
1221  * and the new value in the remaining fields.
1222  * 
1223  * Changes the value of a color that has already
1224  * been allocated. If @colormap is not a private
1225  * colormap, then the color must have been allocated
1226  * using gdk_colormap_alloc_colors() with the 
1227  * @writeable set to %TRUE.
1228  * 
1229  * Return value: %TRUE if the color was successfully changed.
1230  **/
1231 gboolean
1232 gdk_color_change (GdkColormap *colormap,
1233                   GdkColor    *color)
1234 {
1235   GdkColormapPrivateX11 *private;
1236   XColor xcolor;
1237
1238   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
1239   g_return_val_if_fail (color != NULL, FALSE);
1240
1241   xcolor.pixel = color->pixel;
1242   xcolor.red = color->red;
1243   xcolor.green = color->green;
1244   xcolor.blue = color->blue;
1245   xcolor.flags = DoRed | DoGreen | DoBlue;
1246
1247   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1248   if (!private->screen->closed)
1249     XStoreColor (GDK_SCREEN_XDISPLAY (private->screen), private->xcolormap, &xcolor);
1250
1251   return TRUE;
1252 }
1253
1254 /**
1255  * gdk_x11_colormap_foreign_new:
1256  * @visual: a #GdkVisual
1257  * @xcolormap: The XID of a colormap with visual @visual
1258  * 
1259  * If xcolormap refers to a colormap previously known to GTK+,
1260  * returns a new reference to the existing #GdkColormap object,
1261  * otherwise creates a new GdkColormap object and returns that
1262  *
1263  * Return value: the #GdkColormap object for @xcolormap.
1264  *   Free with g_object_unref(). Note that for colormap created
1265  *   with gdk_x11_colormap_foreign_new(), unref'ing the last
1266  *   reference to the object will only free the #GdkColoramp
1267  *   object and not call XFreeColormap()
1268  *
1269  * Since: 2.2
1270  **/
1271 GdkColormap *
1272 gdk_x11_colormap_foreign_new (GdkVisual *visual,
1273                               Colormap   xcolormap)
1274 {
1275   GdkColormap *colormap;
1276   GdkScreen *screen;
1277   GdkColormapPrivateX11 *private;
1278   
1279   g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
1280   g_return_val_if_fail (xcolormap != None, NULL);
1281
1282   screen = gdk_visual_get_screen (visual);
1283   
1284   if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1285                                     GDK_SCREEN_XNUMBER (screen)));
1286     return g_object_ref (gdk_screen_get_system_colormap (screen));
1287
1288   colormap = gdk_colormap_lookup (screen, xcolormap);
1289   if (colormap)
1290     return g_object_ref (colormap);
1291
1292   colormap = g_object_new (GDK_TYPE_COLORMAP, NULL);
1293   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1294
1295   colormap->visual = visual;
1296
1297   private->screen = screen;
1298   private->xcolormap = xcolormap;
1299   private->xdisplay = GDK_SCREEN_XDISPLAY (screen);
1300   private->private_val = FALSE;
1301
1302   colormap->size = visual->colormap_size;
1303
1304   switch (colormap->visual->type)
1305     {
1306     case GDK_VISUAL_GRAYSCALE:
1307     case GDK_VISUAL_PSEUDO_COLOR:
1308       private->info = g_new0 (GdkColorInfo, colormap->size);
1309       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1310                                         (GEqualFunc) gdk_color_equal);
1311       /* Fall through */
1312     case GDK_VISUAL_STATIC_GRAY:
1313     case GDK_VISUAL_STATIC_COLOR:
1314     case GDK_VISUAL_DIRECT_COLOR:
1315       colormap->colors = g_new (GdkColor, colormap->size);
1316       gdk_colormap_sync (colormap, TRUE);
1317       
1318     case GDK_VISUAL_TRUE_COLOR:
1319       break;
1320     }
1321
1322   gdk_colormap_add (colormap);
1323
1324   return colormap;
1325   
1326 }
1327
1328 /**
1329  * gdkx_colormap_get:
1330  * @xcolormap: the XID of a colormap for the default screen.
1331  * 
1332  * Returns a #GdkColormap corresponding to a X colormap;
1333  * this function only works if the colormap is already
1334  * known to GTK+ (a colormap created by GTK+ or the default
1335  * colormap for the screen), since GTK+ 
1336  *
1337  * Always use gdk_x11_colormap_foreign_new() instead.
1338  *
1339  * Return value: the existing #GdkColormap object if it was
1340  *  already known to GTK+, otherwise warns and return
1341  *  %NULL.
1342  **/
1343 GdkColormap*
1344 gdkx_colormap_get (Colormap xcolormap)
1345 {
1346   GdkScreen *screen = gdk_screen_get_default ();
1347   GdkColormap *colormap;
1348
1349   if (xcolormap == DefaultColormap (GDK_SCREEN_XDISPLAY (screen),
1350                                     GDK_SCREEN_XNUMBER (screen)));
1351     return g_object_ref (gdk_screen_get_system_colormap (screen));
1352
1353   colormap = gdk_colormap_lookup (screen, xcolormap);
1354   if (colormap)
1355     return g_object_ref (colormap);
1356
1357   g_warning ("Colormap passed to gdkx_colormap_get\n"
1358              "does not previously exist");
1359
1360   return NULL;
1361 }
1362
1363 static gint
1364 gdk_colormap_match_color (GdkColormap *cmap,
1365                           GdkColor    *color,
1366                           const gchar *available)
1367 {
1368   GdkColor *colors;
1369   guint sum, max;
1370   gint rdiff, gdiff, bdiff;
1371   gint i, index;
1372
1373   g_return_val_if_fail (cmap != NULL, 0);
1374   g_return_val_if_fail (color != NULL, 0);
1375
1376   colors = cmap->colors;
1377   max = 3 * (65536);
1378   index = -1;
1379
1380   for (i = 0; i < cmap->size; i++)
1381     {
1382       if ((!available) || (available && available[i]))
1383         {
1384           rdiff = (color->red - colors[i].red);
1385           gdiff = (color->green - colors[i].green);
1386           bdiff = (color->blue - colors[i].blue);
1387
1388           sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
1389
1390           if (sum < max)
1391             {
1392               index = i;
1393               max = sum;
1394             }
1395         }
1396     }
1397
1398   return index;
1399 }
1400
1401
1402 static GdkColormap*
1403 gdk_colormap_lookup (GdkScreen *screen,
1404                      Colormap   xcolormap)
1405 {
1406   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1407
1408   if (screen_x11->colormap_hash)
1409     return g_hash_table_lookup (screen_x11->colormap_hash, &xcolormap);
1410   else
1411     return NULL;
1412 }
1413
1414 static void
1415 gdk_colormap_add (GdkColormap *cmap)
1416 {
1417   GdkScreenX11 *screen_x11;
1418   GdkColormapPrivateX11 *private;
1419
1420   private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1421   screen_x11 = GDK_SCREEN_X11 (private->screen);
1422
1423   if (!screen_x11->colormap_hash)
1424     screen_x11->colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
1425                                                   (GEqualFunc) gdk_colormap_equal);
1426
1427   g_hash_table_insert (screen_x11->colormap_hash, &private->xcolormap, cmap);
1428 }
1429
1430 static void
1431 gdk_colormap_remove (GdkColormap *cmap)
1432 {
1433   GdkScreenX11 *screen_x11;
1434   GdkColormapPrivateX11 *private;
1435
1436   private = GDK_COLORMAP_PRIVATE_DATA (cmap);
1437   screen_x11 = GDK_SCREEN_X11 (private->screen);
1438
1439   if (screen_x11->colormap_hash)
1440     g_hash_table_remove (screen_x11->colormap_hash, &private->xcolormap);
1441 }
1442
1443 static guint
1444 gdk_colormap_hash (Colormap *colormap)
1445 {
1446   return *colormap;
1447 }
1448
1449 static gboolean
1450 gdk_colormap_equal (Colormap *a,
1451                     Colormap *b)
1452 {
1453   return (*a == *b);
1454 }
1455
1456 /**
1457  * gdk_x11_colormap_get_xdisplay:
1458  * @colormap: a #GdkColormap.
1459  * 
1460  * Returns the display of a #GdkColormap.
1461  * 
1462  * Return value: an Xlib <type>Display*</type>.
1463  **/
1464 Display *
1465 gdk_x11_colormap_get_xdisplay (GdkColormap *colormap)
1466 {
1467   GdkColormapPrivateX11 *private;
1468
1469   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), NULL);
1470
1471   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1472
1473   return private->xdisplay;
1474 }
1475
1476 /**
1477  * gdk_x11_colormap_get_xcolormap:
1478  * @colormap:  a #GdkColormap.
1479  * 
1480  * Returns the X colormap belonging to a #GdkColormap.
1481  * 
1482  * Return value: an Xlib <type>Colormap</type>.
1483  **/
1484 Colormap
1485 gdk_x11_colormap_get_xcolormap (GdkColormap *colormap)
1486 {
1487   GdkColormapPrivateX11 *private;
1488
1489   g_return_val_if_fail (GDK_IS_COLORMAP (colormap), None);
1490
1491   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
1492
1493   if (private->screen->closed)
1494     return None;
1495   else
1496     return private->xcolormap;
1497 }
1498
1499 /**
1500  * gdk_colormap_get_screen:
1501  * @cmap: a #GdkColormap
1502  * 
1503  * Gets the screen for which this colormap was created.
1504  * 
1505  * Return value: the screen for which this colormap was created.
1506  *
1507  * Since: 2.2
1508  **/
1509 GdkScreen *
1510 gdk_colormap_get_screen (GdkColormap *cmap)
1511 {
1512   g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
1513
1514   return  GDK_COLORMAP_PRIVATE_DATA (cmap)->screen;
1515 }