]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkcolor-fb.c
Patch from Eric Warmonhoven to get linux-fb compiling with multihead
[~andy/gtk] / gdk / linux-fb / gdkcolor-fb.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 #include <sys/ioctl.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "gdkcolor.h"
33 #include "gdkprivate-fb.h"
34
35 #define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateFB *) GDK_COLORMAP (cmap)->windowing_data)
36
37 static gint  gdk_colormap_match_color (GdkColormap *cmap,
38                                        GdkColor    *color,
39                                        const gchar *available);
40 static void  gdk_fb_color_round_to_hw (GdkColor *color);
41
42 static gpointer parent_class;
43
44 static void
45 gdk_colormap_finalize (GObject *object)
46 {
47   GdkColormap *colormap = GDK_COLORMAP (object);
48   GdkColormapPrivateFB *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
49
50   if (private->hash)
51     g_hash_table_destroy (private->hash);
52   
53   g_free (private->info);
54   g_free (colormap->colors);
55
56   G_OBJECT_CLASS (parent_class)->finalize (object);
57 }
58
59 static void
60 gdk_colormap_init (GdkColormap *colormap)
61 {
62   GdkColormapPrivateFB *private;
63
64   private = g_new (GdkColormapPrivateFB, 1);
65
66   colormap->windowing_data = private;
67   
68   colormap->size = 0;
69   colormap->colors = NULL;
70 }
71
72 static void
73 gdk_colormap_class_init (GdkColormapClass *klass)
74 {
75   GObjectClass *object_class = G_OBJECT_CLASS (klass);
76
77   parent_class = g_type_class_peek_parent (klass);
78
79   object_class->finalize = gdk_colormap_finalize;
80 }
81
82 GType
83 gdk_colormap_get_type (void)
84 {
85   static GType object_type = 0;
86
87   if (!object_type)
88     {
89       static const GTypeInfo object_info =
90       {
91         sizeof (GdkColormapClass),
92         (GBaseInitFunc) NULL,
93         (GBaseFinalizeFunc) NULL,
94         (GClassInitFunc) gdk_colormap_class_init,
95         NULL,           /* class_finalize */
96         NULL,           /* class_data */
97         sizeof (GdkColormap),
98         0,              /* n_preallocs */
99         (GInstanceInitFunc) gdk_colormap_init,
100       };
101       
102       object_type = g_type_register_static (G_TYPE_OBJECT,
103                                             "GdkColormap",
104                                             &object_info,
105                                             0);
106     }
107   
108   return object_type;
109 }
110
111 GdkColormap *
112 gdk_colormap_new (GdkVisual *visual,
113                   gint       private_cmap)
114 {
115   GdkColormap *colormap;
116   GdkColormap *system;
117   GdkColormapPrivateFB *private;
118   GdkFBDisplay *fbd;
119   int i;
120
121   g_return_val_if_fail (visual != NULL, NULL);
122
123   colormap = g_object_new (gdk_colormap_get_type (), NULL);
124   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
125
126   colormap->visual = visual;
127   fbd = gdk_display;
128
129   private->hash = NULL;
130   
131   colormap->size = visual->colormap_size;
132   colormap->colors = NULL;
133
134   switch (visual->type)
135     {
136     case GDK_VISUAL_STATIC_GRAY:
137     case GDK_VISUAL_STATIC_COLOR:
138     case GDK_VISUAL_GRAYSCALE:
139     case GDK_VISUAL_PSEUDO_COLOR:
140       private->info = g_new0 (GdkColorInfo, colormap->size);
141       colormap->colors = g_new (GdkColor, colormap->size);
142       
143       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
144                                         (GEqualFunc) gdk_color_equal);
145
146       system = gdk_colormap_get_system ();
147       memcpy (colormap->colors, system->colors, colormap->size * sizeof (GdkColor));
148       
149       if (private_cmap)
150         {
151           guint16 red[256], green[256], blue[256];
152           struct fb_cmap fbc = {0, 256};
153
154           fbc.red = red;
155           fbc.green = green;
156           fbc.blue = blue;
157
158           if (ioctl (fbd->fb_fd, FBIOGETCMAP, &fbc))
159             g_error("ioctl(FBIOGETCMAP) failed");
160
161           for (i = 0; i < colormap->size; i++)
162             {
163               colormap->colors[i].pixel = i;
164               colormap->colors[i].red = red[i];
165               colormap->colors[i].green = green[i];
166               colormap->colors[i].blue = blue[i];
167             }
168
169           gdk_colormap_change (colormap, colormap->size);
170         }
171       break;
172
173     case GDK_VISUAL_DIRECT_COLOR:
174       g_warning ("gdk_colormap_new () on a direct color visual not implemented");
175 #if 0
176       colormap->colors = g_new (GdkColor, colormap->size);
177
178       size = 1 << visual->red_prec;
179       for (i = 0; i < size; i++)
180         colormap->colors[i].red = i * 65535 / (size - 1);
181
182       size = 1 << visual->green_prec;
183       for (i = 0; i < size; i++)
184         colormap->colors[i].green = i * 65535 / (size - 1);
185
186       size = 1 << visual->blue_prec;
187       for (i = 0; i < size; i++)
188         colormap->colors[i].blue = i * 65535 / (size - 1);
189
190       gdk_colormap_change (colormap, colormap->size);
191 #endif
192       break;
193
194     default:
195       g_assert_not_reached ();
196
197     case GDK_VISUAL_TRUE_COLOR:
198       break;
199     }
200
201   return colormap;
202 }
203
204 GdkColormap*
205 gdk_screen_get_system_colormap (GdkScreen *screen)
206 {
207   static GdkColormap *colormap = NULL;
208
209   if (!colormap)
210     {
211       GdkColormapPrivateFB *private;
212       GdkVisual *visual = gdk_visual_get_system ();
213       int i, r, g, b;
214       
215       colormap = g_object_new (gdk_colormap_get_type (), NULL);
216       private = GDK_COLORMAP_PRIVATE_DATA (colormap);
217
218       colormap->visual = visual;
219       private->hash = NULL;
220       
221       colormap->size = visual->colormap_size;
222       colormap->colors = NULL;
223       
224       switch (visual->type)
225         {
226         case GDK_VISUAL_STATIC_GRAY:
227         case GDK_VISUAL_STATIC_COLOR:
228         case GDK_VISUAL_GRAYSCALE:
229         case GDK_VISUAL_PSEUDO_COLOR:
230           private->info = g_new0 (GdkColorInfo, colormap->size);
231           colormap->colors = g_new (GdkColor, colormap->size);
232           
233           private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
234                                             (GEqualFunc) gdk_color_equal);
235           switch(visual->type)
236             {
237             case GDK_VISUAL_GRAYSCALE:
238               for(i = 0; i < 256; i++) {
239                 colormap->colors[i].red = 
240                   colormap->colors[i].green =
241                   colormap->colors[i].blue = i << 8;
242                 gdk_fb_color_round_to_hw (&colormap->colors[i]);
243               }
244               i--;
245               colormap->colors[i].red = 
246                 colormap->colors[i].green =
247                 colormap->colors[i].blue = 65535; /* Make it a true white */
248               gdk_fb_color_round_to_hw (&colormap->colors[i]);
249               break;
250             case GDK_VISUAL_PSEUDO_COLOR:
251               /* Color cube stolen from gdkrgb upon advice from Owen */
252               for(i = r = 0; r < 6; r++)
253                 for(g = 0; g < 6; g++)
254                   for(b = 0; b < 6; b++)
255                     {
256                       colormap->colors[i].red = r * 65535 / 5;
257                       colormap->colors[i].green = g * 65535 / 5;
258                       colormap->colors[i].blue = b * 65535 / 5;
259                       gdk_fb_color_round_to_hw (&colormap->colors[i]);
260                       i++;
261                     }
262               g_assert (i == 216);
263               /* Fill in remaining space with grays */
264               for(i = 216; i < 256; i++)
265                 {
266                   colormap->colors[i].red = 
267                     colormap->colors[i].green =
268                     colormap->colors[i].blue = (i - 216) * 40;
269                   gdk_fb_color_round_to_hw (&colormap->colors[i]);
270                 }
271               /* Real white */
272               colormap->colors[255].red = 
273                   colormap->colors[255].green =
274                   colormap->colors[255].blue = 65535;
275               gdk_fb_color_round_to_hw (&colormap->colors[255]);
276
277               break;
278             default:
279               break;
280             }
281           break;
282         case GDK_VISUAL_DIRECT_COLOR:
283           g_warning ("gdk_colormap_get_system() on a direct color visual is not implemented");
284           break;
285         default:
286           g_assert_not_reached ();
287         case GDK_VISUAL_TRUE_COLOR:
288           break;
289         }
290       
291       /* Lock all colors for the system colormap
292        * on pseudocolor visuals. The AA text rendering
293        * takes to many colors otherwise.
294        */
295       if ((visual->type == GDK_VISUAL_GRAYSCALE) ||
296           (visual->type == GDK_VISUAL_PSEUDO_COLOR))
297         {
298           for(i = 0; i < 256; i++)
299             {
300               colormap->colors[i].pixel = i;
301               private->info[i].ref_count = 1;
302               g_hash_table_insert (private->hash,
303                                    &colormap->colors[i],
304                                    &colormap->colors[i]);
305             }
306         }
307       gdk_colormap_change (colormap, colormap->size);
308     }
309
310   return colormap;
311 }
312
313 gint
314 gdk_colormap_get_system_size (void)
315 {
316   return 1 << (gdk_display->modeinfo.bits_per_pixel);
317 }
318
319 void
320 gdk_colormap_change (GdkColormap *colormap,
321                      gint         ncolors)
322 {
323   guint16 red[256], green[256], blue[256];
324   struct fb_cmap fbc = {0,256};
325   GdkColormapPrivateFB *private;
326   int i;
327
328   g_return_if_fail (colormap != NULL);
329
330   fbc.red = red;
331   fbc.green = green;
332   fbc.blue = blue;
333
334   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
335   switch (colormap->visual->type)
336     {
337     case GDK_VISUAL_GRAYSCALE:
338       for(i = 0; i < ncolors; i++)
339         {
340           red[i] = green[i] = blue[i] =
341             (colormap->colors[i].red +
342              colormap->colors[i].green +
343              colormap->colors[i].blue)/3;
344         }
345       ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
346       break;
347
348     case GDK_VISUAL_PSEUDO_COLOR:
349       for (i = 0; i < ncolors; i++)
350         {
351           red[i] = colormap->colors[i].red;
352           green[i] = colormap->colors[i].green;
353           blue[i] = colormap->colors[i].blue;
354         }
355       ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
356       break;
357
358     default:
359       break;
360     }
361 }
362
363 void
364 gdk_colormap_free_colors (GdkColormap *colormap,
365                           GdkColor    *colors,
366                           gint         ncolors)
367 {
368   GdkColormapPrivateFB *private;
369   gint i;
370
371   g_return_if_fail (colormap != NULL);
372   g_return_if_fail (colors != NULL);
373
374   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
375
376   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
377       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
378     return;
379
380   for (i = 0; i < ncolors; i++)
381     {
382       gulong pixel = colors[i].pixel;
383       
384       if (private->info[pixel].ref_count)
385         {
386           private->info[pixel].ref_count--;
387
388           if (private->info[pixel].ref_count == 0)
389             {
390               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
391                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
392               private->info[pixel].flags = 0;
393             }
394         }
395     }
396 }
397
398 /********************
399  * Color allocation *
400  ********************/
401
402 static void
403 gdk_fb_color_round_to_hw (GdkColor *color)
404 {
405   guint rmask, gmask, bmask, len;
406
407   len = gdk_display->modeinfo.red.length;
408   rmask = ((1 << len) - 1) << (16-len);
409   len = gdk_display->modeinfo.green.length;
410   gmask = ((1 << len) - 1) << (16-len);
411   len = gdk_display->modeinfo.blue.length;
412   bmask = ((1 << len) - 1) << (16-len);
413   
414   color->red &=rmask;
415   color->green &=gmask;
416   color->blue &=bmask;
417 }
418
419 /* Try to allocate a single color using XAllocColor. If it succeeds,
420  * cache the result in our colormap, and store in ret.
421  */
422 static gboolean 
423 gdk_colormap_alloc1 (GdkColormap *colormap,
424                      GdkColor    *color,
425                      GdkColor    *ret)
426 {
427   GdkColormapPrivateFB *private;
428   int i;
429
430   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
431
432   if (colormap->visual->type != GDK_VISUAL_GRAYSCALE
433       && colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR)
434     return FALSE;
435
436   *ret = *color;
437   
438   gdk_fb_color_round_to_hw (ret);
439
440   for (i = 0; i<colormap->size; i++)
441     {
442       if (!(private->info[i].flags & GDK_COLOR_WRITEABLE) &&
443           (ret->red == colormap->colors[i].red) &&
444           (ret->green == colormap->colors[i].green) &&
445           (ret->blue == colormap->colors[i].blue))
446         {
447           ret->pixel = i;
448           colormap->colors[i].pixel = i;
449           if (private->info[i].ref_count == 0)
450             g_hash_table_insert (private->hash,
451                                  &colormap->colors[ret->pixel],
452                                  &colormap->colors[ret->pixel]);
453           private->info[i].ref_count++;
454           return TRUE;
455         }
456     }
457
458   for (i = 0; i<colormap->size; i++)
459     {
460       if (private->info[i].ref_count==0)
461         {
462           guint16 red = color->red, green = color->green, blue = color->blue;
463           struct fb_cmap fbc;
464           
465           fbc.len = 1;
466           fbc.start = i;
467           fbc.red = &red;
468           fbc.green = &green;
469           fbc.blue = &blue;
470
471           ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
472
473           ret->pixel = i;
474           colormap->colors[ret->pixel] = *ret;
475           private->info[ret->pixel].ref_count = 1;
476           g_hash_table_insert (private->hash,
477                                &colormap->colors[ret->pixel],
478                                &colormap->colors[ret->pixel]);
479           return TRUE;
480         }
481     }
482       
483   return FALSE;
484 }
485
486 static gint
487 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
488                                   GdkColor    *colors,
489                                   gint         ncolors,
490                                   gboolean     writeable,
491                                   gboolean     best_match,
492                                   gboolean    *success)
493 {
494   GdkColormapPrivateFB *private;
495   gint i, index;
496   gint nremaining = 0;
497   gint nfailed = 0;
498
499   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
500   index = -1;
501
502   for (i = 0; i < ncolors; i++)
503     {
504       if (!success[i])
505         {
506           if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
507             success[i] = TRUE;
508           else
509             nremaining++;
510         }
511     }
512
513
514   if (nremaining > 0 && best_match)
515     {
516       gchar *available = g_new (gchar, colormap->size);
517
518       for (i = 0; i < colormap->size; i++)
519         available[i] = ((private->info[i].ref_count == 0) ||
520                         !(private->info[i].flags & GDK_COLOR_WRITEABLE));
521       
522       while (nremaining > 0)
523         {
524           for (i = 0; i < ncolors; i++)
525             {
526               if (!success[i])
527                 {
528                   index = gdk_colormap_match_color (colormap, &colors[i], available);
529                   if (index != -1)
530                     {
531                       if (private->info[index].ref_count)
532                         {
533                           private->info[index].ref_count++;
534                           colors[i] = colormap->colors[index];
535                           success[i] = TRUE;
536                           nremaining--;
537                         }
538                       else
539                         {
540                           if (gdk_colormap_alloc1 (colormap, 
541                                                    &colormap->colors[index],
542                                                    &colors[i]))
543                             {
544                               success[i] = TRUE;
545                               nremaining--;
546                               break;
547                             }
548                           else
549                             {
550                               available[index] = FALSE;
551                             }
552                         }
553                     }
554                   else
555                     {
556                       nfailed++;
557                       nremaining--;
558                       success[i] = 2; /* flag as permanent failure */
559                     }
560                 }
561             }
562         }
563       g_free (available);
564     }
565
566   /* Change back the values we flagged as permanent failures */
567   if (nfailed > 0)
568     {
569       for (i = 0; i < ncolors; i++)
570         if (success[i] == 2)
571           success[i] = FALSE;
572       nremaining = nfailed;
573     }
574   
575   return (ncolors - nremaining);
576 }
577
578 static gint
579 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
580                                        GdkColor    *colors,
581                                        gint         ncolors,
582                                        gboolean     writeable,
583                                        gboolean     best_match,
584                                        gboolean    *success)
585 {
586   GdkColormapPrivateFB *private;
587   GdkColor *lookup_color;
588   gint i;
589   gint nremaining = 0;
590
591   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
592
593   /* Check for an exact match among previously allocated colors */
594
595   for (i = 0; i < ncolors; i++)
596     {
597       if (!success[i])
598         {
599           lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
600           if (lookup_color)
601             {
602               private->info[lookup_color->pixel].ref_count++;
603               colors[i].pixel = lookup_color->pixel;
604               success[i] = TRUE;
605             }
606           else
607             nremaining++;
608         }
609     }
610
611   /* If that failed, we try to allocate a new color, or approxmiate
612    * with what we can get if best_match is TRUE.
613    */
614   if (nremaining > 0)
615     return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
616   else
617     return 0;
618 }
619
620 gint
621 gdk_colormap_alloc_colors (GdkColormap *colormap,
622                            GdkColor    *colors,
623                            gint         ncolors,
624                            gboolean     writeable,
625                            gboolean     best_match,
626                            gboolean    *success)
627 {
628   GdkColormapPrivateFB *private;
629   GdkVisual *visual;
630   gint i;
631   gint nremaining = 0;
632
633   g_return_val_if_fail (colormap != NULL, FALSE);
634   g_return_val_if_fail (colors != NULL, FALSE);
635
636   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
637
638   for (i = 0; i < ncolors; i++)
639     success[i] = FALSE;
640
641   visual = colormap->visual;
642   switch (visual->type)
643     {
644     case GDK_VISUAL_PSEUDO_COLOR:
645     case GDK_VISUAL_GRAYSCALE:
646     case GDK_VISUAL_STATIC_GRAY:
647     case GDK_VISUAL_STATIC_COLOR:
648       return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
649                                                     writeable, best_match, success);
650       break;
651
652     case GDK_VISUAL_DIRECT_COLOR:
653     case GDK_VISUAL_TRUE_COLOR:
654       for (i = 0; i < ncolors; i++)
655         {
656           colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
657                              ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
658                              ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
659           success[i] = TRUE;
660         }
661       break;
662     }
663   return nremaining;
664 }
665
666 gboolean
667 gdk_color_change (GdkColormap *colormap,
668                   GdkColor    *color)
669 {
670   GdkColormapPrivateFB *private;
671   struct fb_cmap fbc = {0, 1};
672
673   g_return_val_if_fail (colormap != NULL, FALSE);
674   g_return_val_if_fail (color != NULL, FALSE);
675
676   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
677
678   switch(colormap->visual->type)
679     {
680     case GDK_VISUAL_GRAYSCALE:
681       color->red = color->green = color->blue = (color->red + color->green + color->blue)/3;
682
683       /* Fall through */
684     case GDK_VISUAL_PSEUDO_COLOR:
685       colormap->colors[color->pixel] = *color;
686       
687       fbc.start = color->pixel;
688       fbc.red = &color->red;
689       fbc.green = &color->green;
690       fbc.blue = &color->blue;
691       ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
692       break;
693
694     default:
695       break;
696     }
697
698   return TRUE;
699 }
700
701 static gint
702 gdk_colormap_match_color (GdkColormap *cmap,
703                           GdkColor    *color,
704                           const gchar *available)
705 {
706   GdkColor *colors;
707   guint sum, max;
708   gint rdiff, gdiff, bdiff;
709   gint i, index;
710
711   g_return_val_if_fail (cmap != NULL, 0);
712   g_return_val_if_fail (color != NULL, 0);
713
714   colors = cmap->colors;
715   max = 3 * (65536);
716   index = -1;
717
718   for (i = 0; i < cmap->size; i++)
719     {
720       if ((!available) || (available && available[i]))
721         {
722           rdiff = (color->red - colors[i].red);
723           gdiff = (color->green - colors[i].green);
724           bdiff = (color->blue - colors[i].blue);
725
726           sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
727
728           if (sum < max)
729             {
730               index = i;
731               max = sum;
732             }
733         }
734     }
735
736   return index;
737 }
738
739 gboolean
740 gdk_colors_alloc (GdkColormap   *colormap,
741                   gboolean       contiguous,
742                   gulong        *planes,
743                   gint           nplanes,
744                   gulong        *pixels,
745                   gint           npixels)
746 {
747   GdkColormapPrivateFB *private;
748   gint found, i, col;
749
750   g_return_val_if_fail (colormap != NULL, FALSE);
751
752   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
753   
754   if (nplanes > 0)
755     return 0;
756
757   found = 0;
758   for (i = 1; i < colormap->size; i++)
759     {
760       if (private->info[i].ref_count == 0)
761         {
762           found++;
763           if (found >= npixels)
764             break;
765         }
766     }
767
768   if (found < npixels)
769     return FALSE;
770
771   col = 0;
772   for (i = 1; i < colormap->size; i++)
773     {
774       if (private->info[i].ref_count == 0)
775         {
776           pixels[col++] = i;
777           private->info[i].ref_count++;
778           private->info[i].flags |= GDK_COLOR_WRITEABLE;
779           if (col == npixels)
780             return TRUE;
781         }
782     }
783
784   g_assert_not_reached ();
785   return FALSE;
786 }
787
788 void
789 gdk_colors_free (GdkColormap    *colormap,
790                  gulong         *pixels,
791                  gint            npixels,
792                  gulong          planes)
793 {
794   GdkColormapPrivateFB *private;
795   gint i, pixel;
796
797   g_return_if_fail (colormap != NULL);
798
799   if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
800       (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
801     return;
802   
803   private = GDK_COLORMAP_PRIVATE_DATA (colormap);
804   
805   for (i = 0; i < npixels; i++)
806     {
807       pixel = pixels[i];
808       
809       if (private->info[pixel].ref_count)
810         {
811           private->info[pixel].ref_count--;
812
813           if (private->info[pixel].ref_count == 0)
814             {
815               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
816                 g_hash_table_remove (private->hash, &colormap->colors[pixel]);
817               private->info[pixel].flags = 0;
818             }
819         }
820     }
821 }
822
823
824 void
825 gdk_colormap_query_color (GdkColormap *colormap,
826                           gulong       pixel,
827                           GdkColor    *result)
828 {
829   GdkVisual *visual;
830
831   g_return_if_fail (GDK_IS_COLORMAP (colormap));
832   
833   visual = gdk_colormap_get_visual (colormap);
834
835   switch (visual->type)
836     {
837     case GDK_VISUAL_DIRECT_COLOR:
838     case GDK_VISUAL_TRUE_COLOR:
839       result->red = 65535. * (gdouble) ((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
840       result->green = 65535. * (gdouble) ((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
841       result->blue = 65535. * (gdouble) ((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
842       break;
843     case GDK_VISUAL_STATIC_GRAY:
844     case GDK_VISUAL_GRAYSCALE:
845       result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
846       break;
847     case GDK_VISUAL_PSEUDO_COLOR:
848       result->red = colormap->colors[pixel].red;
849       result->green = colormap->colors[pixel].green;
850       result->blue = colormap->colors[pixel].blue;
851       break;
852     default:
853       g_assert_not_reached ();
854       break;
855     }
856 }
857
858 GdkScreen*
859 gdk_colormap_get_screen (GdkColormap *cmap)
860 {
861   g_return_val_if_fail (cmap != NULL, NULL);
862
863   return gdk_screen_get_default ();
864 }