]> Pileus Git - ~andy/gtk/blobdiff - gdk/linux-fb/gdkcolor-fb.c
Take thickness into account in the size allocation of the child widgets in
[~andy/gtk] / gdk / linux-fb / gdkcolor-fb.c
index e5e0330988a333b17816abe3f3985128aa5adc94..c2bbb10b2ad7af43748ebc48bd8db2fa317fe62d 100644 (file)
@@ -2,28 +2,29 @@
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 /*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
 #include <time.h>
 #include <sys/ioctl.h>
 #include <string.h>
 #include "gdkcolor.h"
 #include "gdkprivate-fb.h"
 
+#define GDK_COLORMAP_PRIVATE_DATA(cmap) ((GdkColormapPrivateFB *) GDK_COLORMAP (cmap)->windowing_data)
+
 static gint  gdk_colormap_match_color (GdkColormap *cmap,
                                       GdkColor    *color,
                                       const gchar *available);
+static void  gdk_fb_color_round_to_hw (GdkColor *color);
 
 static gpointer parent_class;
 
 static void
 gdk_colormap_finalize (GObject *object)
 {
-  GdkColormap *colormap = GDK_COLORMAP(object);
-  GdkColormapPrivateFB *private = (GdkColormapPrivateFB*) colormap;
+  GdkColormap *colormap = GDK_COLORMAP (object);
+  GdkColormapPrivateFB *private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
   if (private->hash)
     g_hash_table_destroy (private->hash);
   
   g_free (private->info);
   g_free (colormap->colors);
+  g_free (private);
 
-  G_OBJECT_CLASS(parent_class)->finalize(object);
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static void
 gdk_colormap_init (GdkColormap *colormap)
 {
-  colormap->windowing_data = NULL;
+  GdkColormapPrivateFB *private;
+
+  private = g_new (GdkColormapPrivateFB, 1);
+
+  colormap->windowing_data = private;
   
   colormap->size = 0;
   colormap->colors = NULL;
@@ -81,40 +90,42 @@ gdk_colormap_get_type (void)
     {
       static const GTypeInfo object_info =
       {
-        sizeof (GdkColormapFBClass),
+        sizeof (GdkColormapClass),
         (GBaseInitFunc) NULL,
         (GBaseFinalizeFunc) NULL,
         (GClassInitFunc) gdk_colormap_class_init,
         NULL,           /* class_finalize */
         NULL,           /* class_data */
-        sizeof (GdkColormapPrivateFB),
+        sizeof (GdkColormap),
         0,              /* n_preallocs */
         (GInstanceInitFunc) gdk_colormap_init,
       };
       
       object_type = g_type_register_static (G_TYPE_OBJECT,
                                             "GdkColormap",
-                                            &object_info);
+                                            &object_info,
+                                           0);
     }
   
   return object_type;
 }
 
-GdkColormap*
+GdkColormap *
 gdk_colormap_new (GdkVisual *visual,
                  gint       private_cmap)
 {
   GdkColormap *colormap;
+  GdkColormap *system;
   GdkColormapPrivateFB *private;
   GdkFBDisplay *fbd;
   int i;
 
   g_return_val_if_fail (visual != NULL, NULL);
 
-  private = (GdkColormapPrivateFB *)g_type_create_instance(gdk_colormap_get_type());
-  colormap = (GdkColormap*) private;
+  colormap = g_object_new (gdk_colormap_get_type (), NULL);
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-  private->base.visual = visual;
+  colormap->visual = visual;
   fbd = gdk_display;
 
   private->hash = NULL;
@@ -132,7 +143,10 @@ gdk_colormap_new (GdkVisual *visual,
       colormap->colors = g_new (GdkColor, colormap->size);
       
       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
-                                       (GCompareFunc) gdk_color_equal);
+                                       (GEqualFunc) gdk_color_equal);
+
+      system = gdk_colormap_get_system ();
+      memcpy (colormap->colors, system->colors, colormap->size * sizeof (GdkColor));
       
       if (private_cmap)
        {
@@ -143,7 +157,7 @@ gdk_colormap_new (GdkVisual *visual,
          fbc.green = green;
          fbc.blue = blue;
 
-         if(ioctl(fbd->fd, FBIOGETCMAP, &fbc))
+         if (ioctl (fbd->fb_fd, FBIOGETCMAP, &fbc))
            g_error("ioctl(FBIOGETCMAP) failed");
 
          for (i = 0; i < colormap->size; i++)
@@ -159,7 +173,7 @@ gdk_colormap_new (GdkVisual *visual,
       break;
 
     case GDK_VISUAL_DIRECT_COLOR:
-      g_error("NYI");
+      g_warning ("gdk_colormap_new () on a direct color visual not implemented");
 #if 0
       colormap->colors = g_new (GdkColor, colormap->size);
 
@@ -180,7 +194,7 @@ gdk_colormap_new (GdkVisual *visual,
       break;
 
     default:
-      g_assert_not_reached();
+      g_assert_not_reached ();
 
     case GDK_VISUAL_TRUE_COLOR:
       break;
@@ -189,40 +203,51 @@ gdk_colormap_new (GdkVisual *visual,
   return colormap;
 }
 
-#define MIN_SYNC_TIME 2
-
-void
-gdk_colormap_sync (GdkColormap *colormap,
-                  gboolean     force)
-{
-  
-}                 
-
 GdkColormap*
-gdk_colormap_get_system (void)
+gdk_screen_get_system_colormap (GdkScreen *screen)
 {
   static GdkColormap *colormap = NULL;
 
   if (!colormap)
     {
-      guint16 red[256], green[256], blue[256];
-      struct fb_cmap fbc = {0, 256};
+      GdkColormapPrivateFB *private;
+      GdkVisual *visual = gdk_visual_get_system ();
       int i, r, g, b;
-      GdkVisual *visual = gdk_visual_get_system();
+      
+      colormap = g_object_new (gdk_colormap_get_type (), NULL);
+      private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-      if(visual->type == GDK_VISUAL_GRAYSCALE
-        || visual->type ==  GDK_VISUAL_PSEUDO_COLOR)
+      colormap->visual = visual;
+      private->hash = NULL;
+      
+      colormap->size = visual->colormap_size;
+      colormap->colors = NULL;
+      
+      switch (visual->type)
        {
-         fbc.red = red;
-         fbc.green = green;
-         fbc.blue = blue;
+       case GDK_VISUAL_STATIC_GRAY:
+       case GDK_VISUAL_STATIC_COLOR:
+       case GDK_VISUAL_GRAYSCALE:
+       case GDK_VISUAL_PSEUDO_COLOR:
+         private->info = g_new0 (GdkColorInfo, colormap->size);
+         colormap->colors = g_new (GdkColor, colormap->size);
+         
+         private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
+                                           (GEqualFunc) gdk_color_equal);
          switch(visual->type)
            {
            case GDK_VISUAL_GRAYSCALE:
-             for(i = 0; i < 256; i++)
-               red[i] = green[i] = blue[i] = i << 8;
+             for(i = 0; i < 256; i++) {
+               colormap->colors[i].red = 
+                 colormap->colors[i].green =
+                 colormap->colors[i].blue = i << 8;
+               gdk_fb_color_round_to_hw (&colormap->colors[i]);
+             }
              i--;
-             red[i] = green[i] = blue[i] = 65535; /* Make it a true white */
+             colormap->colors[i].red = 
+               colormap->colors[i].green =
+               colormap->colors[i].blue = 65535; /* Make it a true white */
+             gdk_fb_color_round_to_hw (&colormap->colors[i]);
              break;
            case GDK_VISUAL_PSEUDO_COLOR:
              /* Color cube stolen from gdkrgb upon advice from Owen */
@@ -230,30 +255,58 @@ gdk_colormap_get_system (void)
                for(g = 0; g < 6; g++)
                  for(b = 0; b < 6; b++)
                    {
-                     red[i] = r * 65535 / 5;
-                     green[i] = g * 65535 / 5;
-                     blue[i] = b * 65535 / 5;
+                     colormap->colors[i].red = r * 65535 / 5;
+                     colormap->colors[i].green = g * 65535 / 5;
+                     colormap->colors[i].blue = b * 65535 / 5;
+                     gdk_fb_color_round_to_hw (&colormap->colors[i]);
                      i++;
                    }
-             g_assert(i == 216);
-
-         /* Fill in remaining space with grays */
+             g_assert (i == 216);
+             /* Fill in remaining space with grays */
              for(i = 216; i < 256; i++)
                {
-                 red[i] = green[i] = blue[i] =
-                   (i - 216) * 40;
+                 colormap->colors[i].red = 
+                   colormap->colors[i].green =
+                   colormap->colors[i].blue = (i - 216) * 40;
+                 gdk_fb_color_round_to_hw (&colormap->colors[i]);
                }
              /* Real white */
-             red[255] = green[255] = blue[255] = 65535;
+             colormap->colors[255].red = 
+                 colormap->colors[255].green =
+                 colormap->colors[255].blue = 65535;
+             gdk_fb_color_round_to_hw (&colormap->colors[255]);
+
              break;
            default:
              break;
            }
-
-         ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
+         break;
+       case GDK_VISUAL_DIRECT_COLOR:
+         g_warning ("gdk_colormap_get_system() on a direct color visual is not implemented");
+         break;
+       default:
+         g_assert_not_reached ();
+       case GDK_VISUAL_TRUE_COLOR:
+         break;
        }
-
-      colormap = gdk_colormap_new(visual, TRUE);
+      
+      /* Lock all colors for the system colormap
+       * on pseudocolor visuals. The AA text rendering
+       * takes to many colors otherwise.
+       */
+      if ((visual->type == GDK_VISUAL_GRAYSCALE) ||
+         (visual->type == GDK_VISUAL_PSEUDO_COLOR))
+       {
+         for(i = 0; i < 256; i++)
+           {
+             colormap->colors[i].pixel = i;
+             private->info[i].ref_count = 1;
+             g_hash_table_insert (private->hash,
+                                  &colormap->colors[i],
+                                  &colormap->colors[i]);
+           }
+       }
+      gdk_colormap_change (colormap, colormap->size);
     }
 
   return colormap;
@@ -280,8 +333,8 @@ gdk_colormap_change (GdkColormap *colormap,
   fbc.green = green;
   fbc.blue = blue;
 
-  private = (GdkColormapPrivateFB*) colormap;
-  switch (private->base.visual->type)
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
+  switch (colormap->visual->type)
     {
     case GDK_VISUAL_GRAYSCALE:
       for(i = 0; i < ncolors; i++)
@@ -291,7 +344,7 @@ gdk_colormap_change (GdkColormap *colormap,
             colormap->colors[i].green +
             colormap->colors[i].blue)/3;
        }
-      ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
+      ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
       break;
 
     case GDK_VISUAL_PSEUDO_COLOR:
@@ -301,7 +354,7 @@ gdk_colormap_change (GdkColormap *colormap,
          green[i] = colormap->colors[i].green;
          blue[i] = colormap->colors[i].blue;
        }
-      ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
+      ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
       break;
 
     default:
@@ -309,94 +362,6 @@ gdk_colormap_change (GdkColormap *colormap,
     }
 }
 
-gboolean
-gdk_color_parse (const gchar *spec,
-                GdkColor *color)
-{
-  char aline[512];
-  FILE *fh;
-
-  g_return_val_if_fail(spec, FALSE);
-  g_return_val_if_fail(color, FALSE);
-
-  if(spec[0] == '#')
-    {
-      if(strlen(spec) == 7)
-       {
-         guint num;
-
-         sscanf(spec + 1, "%x", &num);
-         color->red = (num & 0xFF0000) >> 8;
-         color->green = (num & 0xFF00);
-         color->blue = (num & 0xFF) << 8;
-       }
-      else if(strlen(spec) == 13)
-       {
-         char s1[5], s2[5], s3[5];
-         g_snprintf(s1, sizeof(s1), spec + 1);
-         g_snprintf(s2, sizeof(s2), spec + 5);
-         g_snprintf(s3, sizeof(s3), spec + 9);
-
-         if(!sscanf(s1, "%hx", &color->red))
-           g_error("sscanf failed");
-         if(!sscanf(s2, "%hx", &color->green))
-           g_error("sscanf failed");
-         if(!sscanf(s3, "%hx", &color->blue))
-           g_error("sscanf failed");
-       }
-      else
-       {
-         g_warning("Couldn't parse color specifier `%s'", spec);
-         return FALSE;
-       }
-
-      return TRUE;
-    }
-  else
-    {
-      fh = fopen("/usr/lib/X11/rgb.txt", "r");
-      if(!fh)
-       return FALSE;
-
-      while(fgets(aline, sizeof(aline), fh))
-       {
-         int red, green, blue;
-         char *ctmp;
-
-         g_strstrip(aline);
-         if(!aline[0] || aline[0] == '#' || aline[0] == '!')
-           continue;
-
-         ctmp = strtok(aline, " \t");
-         if(!ctmp)
-           continue;
-         red = atoi(ctmp);
-
-         ctmp = strtok(NULL, " \t");
-         if(!ctmp)
-           continue;
-         green = atoi(ctmp);
-
-         ctmp = strtok(NULL, " \t");
-         if(!ctmp)
-           continue;
-         blue = atoi(ctmp);
-
-         ctmp = strtok(NULL, " \t");
-         if(!ctmp || strcmp(ctmp, spec))
-           continue;
-
-         color->red = red << 8;
-         color->green = green << 8;
-         color->blue = blue << 8;
-         return TRUE;
-       }
-      fclose(fh);
-    }
-
-  return FALSE;
-}
-
 void
 gdk_colormap_free_colors (GdkColormap *colormap,
                          GdkColor    *colors,
@@ -408,13 +373,13 @@ gdk_colormap_free_colors (GdkColormap *colormap,
   g_return_if_fail (colormap != NULL);
   g_return_if_fail (colors != NULL);
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-  if ((private->base.visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
-      (private->base.visual->type != GDK_VISUAL_GRAYSCALE))
+  if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
     return;
 
-  for (i=0; i<ncolors; i++)
+  for (i = 0; i < ncolors; i++)
     {
       gulong pixel = colors[i].pixel;
       
@@ -436,6 +401,23 @@ gdk_colormap_free_colors (GdkColormap *colormap,
  * Color allocation *
  ********************/
 
+static void
+gdk_fb_color_round_to_hw (GdkColor *color)
+{
+  guint rmask, gmask, bmask, len;
+
+  len = gdk_display->modeinfo.red.length;
+  rmask = ((1 << len) - 1) << (16-len);
+  len = gdk_display->modeinfo.green.length;
+  gmask = ((1 << len) - 1) << (16-len);
+  len = gdk_display->modeinfo.blue.length;
+  bmask = ((1 << len) - 1) << (16-len);
+  
+  color->red &=rmask;
+  color->green &=gmask;
+  color->blue &=bmask;
+}
+
 /* Try to allocate a single color using XAllocColor. If it succeeds,
  * cache the result in our colormap, and store in ret.
  */
@@ -447,40 +429,48 @@ gdk_colormap_alloc1 (GdkColormap *colormap,
   GdkColormapPrivateFB *private;
   int i;
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-  if(private->base.visual->type != GDK_VISUAL_GRAYSCALE
-     && private->base.visual->type != GDK_VISUAL_PSEUDO_COLOR)
+  if (colormap->visual->type != GDK_VISUAL_GRAYSCALE
+      && colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR)
     return FALSE;
 
   *ret = *color;
-  if(!color->red && !color->green && !color->blue) /* black */
-    {
-      ret->pixel = 0;
-      private->info[ret->pixel].ref_count++;
-      return TRUE;
-    }
+  
+  gdk_fb_color_round_to_hw (ret);
 
-  if(color->red == 65535 && color->green == 65535 && color->blue == 65535) /* white */
+  for (i = 0; i<colormap->size; i++)
     {
-      ret->pixel = 255;
-      private->info[ret->pixel].ref_count++;
-      return TRUE;
+      if (!(private->info[i].flags & GDK_COLOR_WRITEABLE) &&
+         (ret->red == colormap->colors[i].red) &&
+         (ret->green == colormap->colors[i].green) &&
+         (ret->blue == colormap->colors[i].blue))
+       {
+         ret->pixel = i;
+         colormap->colors[i].pixel = i;
+         if (private->info[i].ref_count == 0)
+           g_hash_table_insert (private->hash,
+                                &colormap->colors[ret->pixel],
+                                &colormap->colors[ret->pixel]);
+         private->info[i].ref_count++;
+         return TRUE;
+       }
     }
 
-  for(i = 1; i < (colormap->size - 1); i++)
+  for (i = 0; i<colormap->size; i++)
     {
-      if(!private->info[i].ref_count)
+      if (private->info[i].ref_count==0)
        {
          guint16 red = color->red, green = color->green, blue = color->blue;
          struct fb_cmap fbc;
+         
          fbc.len = 1;
          fbc.start = i;
          fbc.red = &red;
          fbc.green = &green;
          fbc.blue = &blue;
 
-         ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
+         ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
 
          ret->pixel = i;
          colormap->colors[ret->pixel] = *ret;
@@ -491,7 +481,7 @@ gdk_colormap_alloc1 (GdkColormap *colormap,
          return TRUE;
        }
     }
-
+      
   return FALSE;
 }
 
@@ -508,10 +498,10 @@ gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
   gint nremaining = 0;
   gint nfailed = 0;
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
   index = -1;
 
-  for (i=0; i<ncolors; i++)
+  for (i = 0; i < ncolors; i++)
     {
       if (!success[i])
        {
@@ -529,11 +519,11 @@ gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
 
       for (i = 0; i < colormap->size; i++)
        available[i] = ((private->info[i].ref_count == 0) ||
-                       !(private->info[i].flags && GDK_COLOR_WRITEABLE));
+                       !(private->info[i].flags & GDK_COLOR_WRITEABLE));
       
       while (nremaining > 0)
        {
-         for (i=0; i<ncolors; i++)
+         for (i = 0; i < ncolors; i++)
            {
              if (!success[i])
                {
@@ -578,7 +568,7 @@ gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
   /* Change back the values we flagged as permanent failures */
   if (nfailed > 0)
     {
-      for (i=0; i<ncolors; i++)
+      for (i = 0; i < ncolors; i++)
        if (success[i] == 2)
          success[i] = FALSE;
       nremaining = nfailed;
@@ -600,11 +590,11 @@ gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
   gint i;
   gint nremaining = 0;
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
   /* Check for an exact match among previously allocated colors */
 
-  for (i=0; i<ncolors; i++)
+  for (i = 0; i < ncolors; i++)
     {
       if (!success[i])
        {
@@ -645,12 +635,13 @@ gdk_colormap_alloc_colors (GdkColormap *colormap,
   g_return_val_if_fail (colormap != NULL, FALSE);
   g_return_val_if_fail (colors != NULL, FALSE);
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-  for (i=0; i<ncolors; i++)
+  for (i = 0; i < ncolors; i++)
     success[i] = FALSE;
 
-  switch (private->base.visual->type)
+  visual = colormap->visual;
+  switch (visual->type)
     {
     case GDK_VISUAL_PSEUDO_COLOR:
     case GDK_VISUAL_GRAYSCALE:
@@ -662,9 +653,7 @@ gdk_colormap_alloc_colors (GdkColormap *colormap,
 
     case GDK_VISUAL_DIRECT_COLOR:
     case GDK_VISUAL_TRUE_COLOR:
-      visual = private->base.visual;
-
-      for (i=0; i<ncolors; i++)
+      for (i = 0; i < ncolors; i++)
        {
          colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
                             ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
@@ -686,19 +675,22 @@ gdk_color_change (GdkColormap *colormap,
   g_return_val_if_fail (colormap != NULL, FALSE);
   g_return_val_if_fail (color != NULL, FALSE);
 
-  private = (GdkColormapPrivateFB*) colormap;
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
 
-  switch(private->base.visual->type)
+  switch(colormap->visual->type)
     {
     case GDK_VISUAL_GRAYSCALE:
       color->red = color->green = color->blue = (color->red + color->green + color->blue)/3;
 
+      /* Fall through */
     case GDK_VISUAL_PSEUDO_COLOR:
+      colormap->colors[color->pixel] = *color;
+      
       fbc.start = color->pixel;
       fbc.red = &color->red;
       fbc.green = &color->green;
       fbc.blue = &color->blue;
-      ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
+      ioctl (gdk_display->fb_fd, FBIOPUTCMAP, &fbc);
       break;
 
     default:
@@ -746,65 +738,129 @@ gdk_colormap_match_color (GdkColormap *cmap,
   return index;
 }
 
-gint gdk_colors_alloc   (GdkColormap   *colormap,
-                         gboolean       contiguous,
-                         gulong        *planes,
-                         gint           nplanes,
-                         gulong        *pixels,
-                         gint           npixels)
-{
-  return 0;
-}
-
-void
-gdk_colors_free         (GdkColormap   *colormap,
+gboolean
+gdk_colors_alloc (GdkColormap  *colormap,
+                 gboolean       contiguous,
+                 gulong        *planes,
+                 gint           nplanes,
                  gulong        *pixels,
-                 gint           npixels,
-                 gulong         planes)
+                 gint           npixels)
 {
-}
+  GdkColormapPrivateFB *private;
+  gint found, i, col;
 
-gulong
-gdk_color_context_get_pixel(GdkColorContext *cc,
-                           gushort         red,
-                           gushort         green,
-                           gushort         blue,
-                           gint           *failed)
-{
-  g_error("NYI");
+  g_return_val_if_fail (colormap != NULL, FALSE);
 
-  return 0;
-}
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
+  
+  if (nplanes > 0)
+    return FALSE;
 
-GdkColorContext *
-gdk_color_context_new(GdkVisual   *visual,
-                     GdkColormap *colormap)
-{
-  g_error("NYI");
+  found = 0;
+  for (i = 1; i < colormap->size; i++)
+    {
+      if (private->info[i].ref_count == 0)
+       {
+         found++;
+         if (found >= npixels)
+           break;
+       }
+    }
+
+  if (found < npixels)
+    return FALSE;
 
-  return NULL;
+  col = 0;
+  for (i = 1; i < colormap->size; i++)
+    {
+      if (private->info[i].ref_count == 0)
+       {
+         pixels[col++] = i;
+         private->info[i].ref_count++;
+         private->info[i].flags |= GDK_COLOR_WRITEABLE;
+         if (col == npixels)
+           return TRUE;
+       }
+    }
+
+  g_assert_not_reached ();
+  return FALSE;
 }
 
-GdkColorContext *
-gdk_color_context_new_mono(GdkVisual   *visual,
-                          GdkColormap *colormap)
+void
+gdk_colors_free        (GdkColormap    *colormap,
+                gulong         *pixels,
+                gint            npixels,
+                gulong          planes)
 {
-  g_error("NYI");
+  GdkColormapPrivateFB *private;
+  gint i, pixel;
+
+  g_return_if_fail (colormap != NULL);
+
+  if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
+      (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
+    return;
+  
+  private = GDK_COLORMAP_PRIVATE_DATA (colormap);
+  
+  for (i = 0; i < npixels; i++)
+    {
+      pixel = pixels[i];
+      
+      if (private->info[pixel].ref_count)
+       {
+         private->info[pixel].ref_count--;
 
-  return NULL;
+         if (private->info[pixel].ref_count == 0)
+           {
+             if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
+               g_hash_table_remove (private->hash, &colormap->colors[pixel]);
+             private->info[pixel].flags = 0;
+           }
+       }
+    }
 }
 
+
 void
-gdk_color_context_free(GdkColorContext *cc)
+gdk_colormap_query_color (GdkColormap *colormap,
+                         gulong       pixel,
+                         GdkColor    *result)
 {
-  g_error("NYI");
+  GdkVisual *visual;
+
+  g_return_if_fail (GDK_IS_COLORMAP (colormap));
+  
+  visual = gdk_colormap_get_visual (colormap);
+
+  switch (visual->type)
+    {
+    case GDK_VISUAL_DIRECT_COLOR:
+    case GDK_VISUAL_TRUE_COLOR:
+      result->red = 65535. * (gdouble) ((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
+      result->green = 65535. * (gdouble) ((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
+      result->blue = 65535. * (gdouble) ((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
+      break;
+    case GDK_VISUAL_STATIC_GRAY:
+    case GDK_VISUAL_GRAYSCALE:
+      result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
+      break;
+    case GDK_VISUAL_PSEUDO_COLOR:
+      result->red = colormap->colors[pixel].red;
+      result->green = colormap->colors[pixel].green;
+      result->blue = colormap->colors[pixel].blue;
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
 }
 
-gint
-gdk_color_context_query_color(GdkColorContext *cc,
-                             GdkColor     *color)
+GdkScreen*
+gdk_colormap_get_screen (GdkColormap *cmap)
 {
-  g_error("NYI");
+  g_return_val_if_fail (cmap != NULL, NULL);
 
-  return 0;
+  return gdk_screen_get_default ();
 }