]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkcolor.c
Change GDK_WINDOWING_WIN32 usage to #ifdef also here.
[~andy/gtk] / gdk / win32 / gdkcolor.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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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 "config.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33
34 #include "gdkcolor.h"
35 #include "gdkprivate.h"
36
37 static gint  gdk_colormap_match_color (GdkColormap *cmap,
38                                        GdkColor    *color,
39                                        const gchar *available);
40 static void  gdk_colormap_add         (GdkColormap *cmap);
41 static void  gdk_colormap_remove      (GdkColormap *cmap);
42 static guint gdk_colormap_hash        (Colormap    *cmap);
43 static gint  gdk_colormap_cmp         (Colormap    *a,
44                                        Colormap    *b);
45 static void gdk_colormap_real_destroy (GdkColormap *colormap);
46
47 static GHashTable *colormap_hash = NULL;
48
49 static Status
50 alloc_color_cells(Colormap      colormap,
51                   gboolean      contig,
52                   unsigned long plane_masks_return[],
53                   unsigned int  nplanes,
54                   unsigned long pixels_return[],
55                   unsigned int  npixels)
56 {
57   unsigned int i, nfree, iret;
58
59   nfree = 0;
60   for (i = 0; i < colormap->size && nfree < npixels; i++)
61     if (!colormap->in_use[i])
62       nfree++;
63
64   if (colormap->size + npixels - nfree > colormap->sizepalette)
65     {
66       g_warning ("alloc_color_cells: too large palette: %d",
67                  colormap->size + npixels);
68       return FALSE;
69     }
70
71   iret = 0;
72   for (i = 0; i < colormap->size && iret < npixels; i++)
73     if (!colormap->in_use[i])
74       {
75         colormap->in_use[i] = TRUE;
76         pixels_return[iret] = i;
77         iret++;
78       }
79
80   if (nfree < npixels)
81     {
82       int nmore = npixels - nfree;
83
84       /* I don't understand why, if the code below in #if 0 is
85          enabled, gdkrgb fails miserably. The palette doesn't get
86          realized correctly. There doesn't seem to be any harm done by
87          keeping this code out, either.  */
88 #ifdef SOME_STRANGE_BUG
89       if (!ResizePalette (colormap->palette, colormap->size + nmore))
90         {
91           g_warning ("alloc_color_cells: ResizePalette to %d failed",
92                      colormap->size + nmore);
93           return FALSE;
94         }
95       g_print("alloc_color_cells: %#x to %d\n",
96               colormap->palette, colormap->size + nmore);
97 #endif
98       for (i = colormap->size; i < colormap->size + nmore; i++)
99         {
100           pixels_return[iret] = i;
101           iret++;
102           colormap->in_use[i] = TRUE;
103         }
104 #ifdef SOME_STRANGE_BUG
105       colormap->size += nmore;
106 #endif
107     }
108   return TRUE;
109 }
110
111 /* The following functions are from Tk8.0, but heavily modified.
112    Here are tk's licensing terms. I hope these terms don't conflict
113    with the GNU Library General Public License? They shouldn't, as
114    they are looser that the GLPL, yes? */
115
116 /*
117 This software is copyrighted by the Regents of the University of
118 California, Sun Microsystems, Inc., and other parties.  The following
119 terms apply to all files associated with the software unless explicitly
120 disclaimed in individual files.
121
122 The authors hereby grant permission to use, copy, modify, distribute,
123 and license this software and its documentation for any purpose, provided
124 that existing copyright notices are retained in all copies and that this
125 notice is included verbatim in any distributions. No written agreement,
126 license, or royalty fee is required for any of the authorized uses.
127 Modifications to this software may be copyrighted by their authors
128 and need not follow the licensing terms described here, provided that
129 the new terms are clearly indicated on the first page of each file where
130 they apply.
131
132 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
133 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
134 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
135 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
136 POSSIBILITY OF SUCH DAMAGE.
137
138 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
139 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
140 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
141 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
142 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
143 MODIFICATIONS.
144
145 GOVERNMENT USE: If you are acquiring this software on behalf of the
146 U.S. government, the Government shall have only "Restricted Rights"
147 in the software and related documentation as defined in the Federal 
148 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
149 are acquiring the software on behalf of the Department of Defense, the
150 software shall be classified as "Commercial Computer Software" and the
151 Government shall have only "Restricted Rights" as defined in Clause
152 252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
153 authors grant the U.S. Government and others acting in its behalf
154 permission to use and distribute the software in accordance with the
155 terms specified in this license.
156 */
157 /*
158  *----------------------------------------------------------------------
159  *
160  * XAllocColor --
161  *
162  *      Find the closest available color to the specified XColor.
163  *
164  * Results:
165  *      Updates the color argument and returns 1 on success.  Otherwise
166  *      returns 0.
167  *
168  * Side effects:
169  *      Allocates a new color in the palette.
170  *
171  *----------------------------------------------------------------------
172  */
173
174 static int
175 alloc_color(Colormap  colormap,
176             XColor   *color,
177             gulong   *pixelp)
178 {
179   PALETTEENTRY entry, closeEntry;
180   HDC hdc;
181   unsigned int i;
182     
183   entry = *color;
184   entry.peFlags = 0;
185
186   if (colormap->rc_palette)
187     {
188       COLORREF newPixel, closePixel;
189       UINT index;
190
191       /*
192        * Find the nearest existing palette entry.
193        */
194         
195       newPixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
196       index = GetNearestPaletteIndex (colormap->palette, newPixel);
197       GetPaletteEntries (colormap->palette, index, 1, &closeEntry);
198       closePixel = RGB (closeEntry.peRed, closeEntry.peGreen,
199                         closeEntry.peBlue);
200
201       if (newPixel != closePixel)
202         {
203           /* Not a perfect match. */
204           if (!colormap->in_use[index])
205             {
206               /* It was a free'd entry anyway, so we can use it, and
207                  set it to the correct color. */
208               if (SetPaletteEntries (colormap->palette, index, 1, &entry) == 0)
209                 g_warning ("alloc_color: SetPaletteEntries #1 failed");
210             }
211           else
212             {
213               /* The close entry found is in use, so search for a
214                  unused slot. */
215                  
216               for (i = 0; i < colormap->size; i++)
217                 if (!colormap->in_use[i])
218                   {
219                     /* A free slot, use it. */
220                     if (SetPaletteEntries (colormap->palette,
221                                            index, 1, &entry) == 0)
222                       g_warning ("alloc_color: SetPaletteEntries #2 failed");
223                     index = i;
224                     break;
225                   }
226               if (i == colormap->size)
227                 {
228                   /* No free slots found. If the palette isn't maximal
229                      yet, grow it. */
230                   if (colormap->size == colormap->sizepalette)
231                     {
232                       /* The palette is maximal, and no free slots available,
233                          so use the close entry, then, dammit. */
234                       *color = closeEntry;
235                     }
236                   else
237                     {
238                       /* There is room to grow the palette. */
239                       index = colormap->size;
240                       colormap->size++;
241                       if (!ResizePalette (colormap->palette, colormap->size))
242                         g_warning ("alloc_color: ResizePalette to %d failed",
243                                    colormap->size);
244                       if (SetPaletteEntries (colormap->palette, index, 1, &entry) == 0)
245                         g_warning ("alloc_color: SetPaletteEntries #3 failed");
246                     }
247                 }
248             }
249           colormap->stale = TRUE;
250         }
251       else
252         {
253           /* We got a match, so use it. */
254         }
255
256       *pixelp = index;
257       colormap->in_use[index] = TRUE;
258 #if 0
259       g_print("alloc_color from %#x: index %d for %02x %02x %02x\n",
260               colormap->palette, index,
261               entry.peRed, entry.peGreen, entry.peBlue);
262 #endif
263     }
264   else
265     {
266       /*
267        * Determine what color will actually be used on non-colormap systems.
268        */
269       *pixelp = GetNearestColor (gdk_DC, RGB(entry.peRed, entry.peGreen, entry.peBlue));
270       
271       color->peRed = GetRValue (*pixelp);
272       color->peGreen = GetGValue (*pixelp);
273       color->peBlue = GetBValue (*pixelp);
274     }
275   
276   return 1;
277 }
278
279 /*
280  *----------------------------------------------------------------------
281  *
282  * XFreeColors --
283  *
284  *      Deallocate a block of colors.
285  *
286  * Results:
287  *      None.
288  *
289  * Side effects:
290  *      Removes entries for the current palette and compacts the
291  *      remaining set.
292  *
293  *----------------------------------------------------------------------
294  */
295
296 static void
297 XFreeColors(Colormap colormap,
298             gulong  *pixels,
299             gint     npixels,
300             gulong   planes)
301 {
302   gint i;
303   PALETTEENTRY entries[256];
304
305   /*
306    * We don't have to do anything for non-palette devices.
307    */
308   
309   if (colormap->rc_palette)
310     {
311       int npal;
312       int lowestpixel = 256;
313       int highestpixel = -1;
314
315       npal = GetPaletteEntries (colormap->palette, 0, 256, entries);
316       for (i = 0; i < npixels; i++)
317         {
318           int pixel = pixels[i];
319
320           if (pixel < lowestpixel)
321             lowestpixel = pixel;
322           if (pixel > highestpixel)
323             highestpixel = pixel;
324
325           colormap->in_use[pixel] = FALSE;
326
327           entries[pixel] = entries[0];
328         }
329 #if 0
330       if (SetPaletteEntries (colormap->palette, lowestpixel,
331                              highestpixel - lowestpixel + 1,
332                              entries + lowestpixel) == 0)
333         g_warning ("XFreeColors: SetPaletteEntries failed");
334 #endif
335       colormap->stale = TRUE;
336 #if 0
337       g_print("XFreeColors %#x lowestpixel = %d, highestpixel = %d\n",
338               colormap->palette, lowestpixel, highestpixel);
339 #endif
340     }
341 }
342
343 /*
344  *----------------------------------------------------------------------
345  *
346  * XCreateColormap --
347  *
348  *      Allocate a new colormap.
349  *
350  * Results:
351  *      Returns a newly allocated colormap.
352  *
353  * Side effects:
354  *      Allocates an empty palette and color list.
355  *
356  *----------------------------------------------------------------------
357  */
358
359 static Colormap
360 create_colormap (HWND     w,
361                  Visual  *visual,
362                  int      alloc)
363 {
364   char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
365   LOGPALETTE *logPalettePtr;
366   PALETTEENTRY *entryPtr;
367   Colormap colormap;
368   guint i;
369   HPALETTE sysPal;
370   HDC hdc;
371
372   /* Should the alloc parameter do something? */
373
374
375   /* Allocate a starting palette with all of the reserved colors. */
376   
377   logPalettePtr = (LOGPALETTE *) logPalBuf;
378   logPalettePtr->palVersion = 0x300;
379   sysPal = (HPALETTE) GetStockObject (DEFAULT_PALETTE);
380   logPalettePtr->palNumEntries =
381     GetPaletteEntries (sysPal, 0, 256, logPalettePtr->palPalEntry);
382   
383   colormap = (Colormap) g_new (ColormapStruct, 1);
384   colormap->size = logPalettePtr->palNumEntries;
385   colormap->stale = TRUE;
386   colormap->palette = CreatePalette (logPalettePtr);
387   hdc = GetDC (NULL);
388   colormap->rc_palette = ((GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) != 0);
389   if (colormap->rc_palette)
390     {
391       colormap->sizepalette = GetDeviceCaps (hdc, SIZEPALETTE);
392       colormap->in_use = g_new (gboolean, colormap->sizepalette);
393       /* Mark static colors in use. */
394       for (i = 0; i < logPalettePtr->palNumEntries; i++)
395         colormap->in_use[i] = TRUE;
396       /* Mark rest not in use */
397       for (i = logPalettePtr->palNumEntries; i < colormap->sizepalette; i++)
398         colormap->in_use[i] = FALSE;
399     }
400   ReleaseDC (NULL, hdc);
401
402   return colormap;
403 }
404
405 /*
406  *----------------------------------------------------------------------
407  *
408  * XFreeColormap --
409  *
410  *      Frees the resources associated with the given colormap.
411  *
412  * Results:
413  *      None.
414  *
415  * Side effects:
416  *      Deletes the palette associated with the colormap.  Note that
417  *      the palette must not be selected into a device context when
418  *      this occurs.
419  *
420  *----------------------------------------------------------------------
421  */
422
423 static void
424 XFreeColormap(Colormap  colormap)
425  
426 {
427   if (!DeleteObject (colormap->palette))
428     {
429       g_error ("Unable to free colormap, palette is still selected.");
430     }
431   g_free (colormap);
432 }
433
434 typedef struct {
435     char *name;
436     unsigned char red;
437     unsigned char green;
438     unsigned char blue;
439 } XColorEntry;
440
441 static XColorEntry xColors[] = {
442     { "alice blue", 240, 248, 255 },
443     { "AliceBlue", 240, 248, 255 },
444     { "antique white", 250, 235, 215 },
445     { "AntiqueWhite", 250, 235, 215 },
446     { "AntiqueWhite1", 255, 239, 219 },
447     { "AntiqueWhite2", 238, 223, 204 },
448     { "AntiqueWhite3", 205, 192, 176 },
449     { "AntiqueWhite4", 139, 131, 120 },
450     { "aquamarine", 127, 255, 212 },
451     { "aquamarine1", 127, 255, 212 },
452     { "aquamarine2", 118, 238, 198 },
453     { "aquamarine3", 102, 205, 170 },
454     { "aquamarine4", 69, 139, 116 },
455     { "azure", 240, 255, 255 },
456     { "azure1", 240, 255, 255 },
457     { "azure2", 224, 238, 238 },
458     { "azure3", 193, 205, 205 },
459     { "azure4", 131, 139, 139 },
460     { "beige", 245, 245, 220 },
461     { "bisque", 255, 228, 196 },
462     { "bisque1", 255, 228, 196 },
463     { "bisque2", 238, 213, 183 },
464     { "bisque3", 205, 183, 158 },
465     { "bisque4", 139, 125, 107 },
466     { "black", 0, 0, 0 },
467     { "blanched almond", 255, 235, 205 },
468     { "BlanchedAlmond", 255, 235, 205 },
469     { "blue", 0, 0, 255 },
470     { "blue violet", 138, 43, 226 },
471     { "blue1", 0, 0, 255 },
472     { "blue2", 0, 0, 238 },
473     { "blue3", 0, 0, 205 },
474     { "blue4", 0, 0, 139 },
475     { "BlueViolet", 138, 43, 226 },
476     { "brown", 165, 42, 42 },
477     { "brown1", 255, 64, 64 },
478     { "brown2", 238, 59, 59 },
479     { "brown3", 205, 51, 51 },
480     { "brown4", 139, 35, 35 },
481     { "burlywood", 222, 184, 135 },
482     { "burlywood1", 255, 211, 155 },
483     { "burlywood2", 238, 197, 145 },
484     { "burlywood3", 205, 170, 125 },
485     { "burlywood4", 139, 115, 85 },
486     { "cadet blue", 95, 158, 160 },
487     { "CadetBlue", 95, 158, 160 },
488     { "CadetBlue1", 152, 245, 255 },
489     { "CadetBlue2", 142, 229, 238 },
490     { "CadetBlue3", 122, 197, 205 },
491     { "CadetBlue4", 83, 134, 139 },
492     { "chartreuse", 127, 255, 0 },
493     { "chartreuse1", 127, 255, 0 },
494     { "chartreuse2", 118, 238, 0 },
495     { "chartreuse3", 102, 205, 0 },
496     { "chartreuse4", 69, 139, 0 },
497     { "chocolate", 210, 105, 30 },
498     { "chocolate1", 255, 127, 36 },
499     { "chocolate2", 238, 118, 33 },
500     { "chocolate3", 205, 102, 29 },
501     { "chocolate4", 139, 69, 19 },
502     { "coral", 255, 127, 80 },
503     { "coral1", 255, 114, 86 },
504     { "coral2", 238, 106, 80 },
505     { "coral3", 205, 91, 69 },
506     { "coral4", 139, 62, 47 },
507     { "cornflower blue", 100, 149, 237 },
508     { "CornflowerBlue", 100, 149, 237 },
509     { "cornsilk", 255, 248, 220 },
510     { "cornsilk1", 255, 248, 220 },
511     { "cornsilk2", 238, 232, 205 },
512     { "cornsilk3", 205, 200, 177 },
513     { "cornsilk4", 139, 136, 120 },
514     { "cyan", 0, 255, 255 },
515     { "cyan1", 0, 255, 255 },
516     { "cyan2", 0, 238, 238 },
517     { "cyan3", 0, 205, 205 },
518     { "cyan4", 0, 139, 139 },
519     { "dark blue", 0, 0, 139 },
520     { "dark cyan", 0, 139, 139 },
521     { "dark goldenrod", 184, 134, 11 },
522     { "dark gray", 169, 169, 169 },
523     { "dark green", 0, 100, 0 },
524     { "dark grey", 169, 169, 169 },
525     { "dark khaki", 189, 183, 107 },
526     { "dark magenta", 139, 0, 139 },
527     { "dark olive green", 85, 107, 47 },
528     { "dark orange", 255, 140, 0 },
529     { "dark orchid", 153, 50, 204 },
530     { "dark red", 139, 0, 0 },
531     { "dark salmon", 233, 150, 122 },
532     { "dark sea green", 143, 188, 143 },
533     { "dark slate blue", 72, 61, 139 },
534     { "dark slate gray", 47, 79, 79 },
535     { "dark slate grey", 47, 79, 79 },
536     { "dark turquoise", 0, 206, 209 },
537     { "dark violet", 148, 0, 211 },
538     { "DarkBlue", 0, 0, 139 },
539     { "DarkCyan", 0, 139, 139 },
540     { "DarkGoldenrod", 184, 134, 11 },
541     { "DarkGoldenrod1", 255, 185, 15 },
542     { "DarkGoldenrod2", 238, 173, 14 },
543     { "DarkGoldenrod3", 205, 149, 12 },
544     { "DarkGoldenrod4", 139, 101, 8 },
545     { "DarkGray", 169, 169, 169 },
546     { "DarkGreen", 0, 100, 0 },
547     { "DarkGrey", 169, 169, 169 },
548     { "DarkKhaki", 189, 183, 107 },
549     { "DarkMagenta", 139, 0, 139 },
550     { "DarkOliveGreen", 85, 107, 47 },
551     { "DarkOliveGreen1", 202, 255, 112 },
552     { "DarkOliveGreen2", 188, 238, 104 },
553     { "DarkOliveGreen3", 162, 205, 90 },
554     { "DarkOliveGreen4", 110, 139, 61 },
555     { "DarkOrange", 255, 140, 0 },
556     { "DarkOrange1", 255, 127, 0 },
557     { "DarkOrange2", 238, 118, 0 },
558     { "DarkOrange3", 205, 102, 0 },
559     { "DarkOrange4", 139, 69, 0 },
560     { "DarkOrchid", 153, 50, 204 },
561     { "DarkOrchid1", 191, 62, 255 },
562     { "DarkOrchid2", 178, 58, 238 },
563     { "DarkOrchid3", 154, 50, 205 },
564     { "DarkOrchid4", 104, 34, 139 },
565     { "DarkRed", 139, 0, 0 },
566     { "DarkSalmon", 233, 150, 122 },
567     { "DarkSeaGreen", 143, 188, 143 },
568     { "DarkSeaGreen1", 193, 255, 193 },
569     { "DarkSeaGreen2", 180, 238, 180 },
570     { "DarkSeaGreen3", 155, 205, 155 },
571     { "DarkSeaGreen4", 105, 139, 105 },
572     { "DarkSlateBlue", 72, 61, 139 },
573     { "DarkSlateGray", 47, 79, 79 },
574     { "DarkSlateGray1", 151, 255, 255 },
575     { "DarkSlateGray2", 141, 238, 238 },
576     { "DarkSlateGray3", 121, 205, 205 },
577     { "DarkSlateGray4", 82, 139, 139 },
578     { "DarkSlateGrey", 47, 79, 79 },
579     { "DarkTurquoise", 0, 206, 209 },
580     { "DarkViolet", 148, 0, 211 },
581     { "deep pink", 255, 20, 147 },
582     { "deep sky blue", 0, 191, 255 },
583     { "DeepPink", 255, 20, 147 },
584     { "DeepPink1", 255, 20, 147 },
585     { "DeepPink2", 238, 18, 137 },
586     { "DeepPink3", 205, 16, 118 },
587     { "DeepPink4", 139, 10, 80 },
588     { "DeepSkyBlue", 0, 191, 255 },
589     { "DeepSkyBlue1", 0, 191, 255 },
590     { "DeepSkyBlue2", 0, 178, 238 },
591     { "DeepSkyBlue3", 0, 154, 205 },
592     { "DeepSkyBlue4", 0, 104, 139 },
593     { "dim gray", 105, 105, 105 },
594     { "dim grey", 105, 105, 105 },
595     { "DimGray", 105, 105, 105 },
596     { "DimGrey", 105, 105, 105 },
597     { "dodger blue", 30, 144, 255 },
598     { "DodgerBlue", 30, 144, 255 },
599     { "DodgerBlue1", 30, 144, 255 },
600     { "DodgerBlue2", 28, 134, 238 },
601     { "DodgerBlue3", 24, 116, 205 },
602     { "DodgerBlue4", 16, 78, 139 },
603     { "firebrick", 178, 34, 34 },
604     { "firebrick1", 255, 48, 48 },
605     { "firebrick2", 238, 44, 44 },
606     { "firebrick3", 205, 38, 38 },
607     { "firebrick4", 139, 26, 26 },
608     { "floral white", 255, 250, 240 },
609     { "FloralWhite", 255, 250, 240 },
610     { "forest green", 34, 139, 34 },
611     { "ForestGreen", 34, 139, 34 },
612     { "gainsboro", 220, 220, 220 },
613     { "ghost white", 248, 248, 255 },
614     { "GhostWhite", 248, 248, 255 },
615     { "gold", 255, 215, 0 },
616     { "gold1", 255, 215, 0 },
617     { "gold2", 238, 201, 0 },
618     { "gold3", 205, 173, 0 },
619     { "gold4", 139, 117, 0 },
620     { "goldenrod", 218, 165, 32 },
621     { "goldenrod1", 255, 193, 37 },
622     { "goldenrod2", 238, 180, 34 },
623     { "goldenrod3", 205, 155, 29 },
624     { "goldenrod4", 139, 105, 20 },
625     { "gray", 190, 190, 190 },
626     { "gray0", 0, 0, 0 },
627     { "gray1", 3, 3, 3 },
628     { "gray10", 26, 26, 26 },
629     { "gray100", 255, 255, 255 },
630     { "gray11", 28, 28, 28 },
631     { "gray12", 31, 31, 31 },
632     { "gray13", 33, 33, 33 },
633     { "gray14", 36, 36, 36 },
634     { "gray15", 38, 38, 38 },
635     { "gray16", 41, 41, 41 },
636     { "gray17", 43, 43, 43 },
637     { "gray18", 46, 46, 46 },
638     { "gray19", 48, 48, 48 },
639     { "gray2", 5, 5, 5 },
640     { "gray20", 51, 51, 51 },
641     { "gray21", 54, 54, 54 },
642     { "gray22", 56, 56, 56 },
643     { "gray23", 59, 59, 59 },
644     { "gray24", 61, 61, 61 },
645     { "gray25", 64, 64, 64 },
646     { "gray26", 66, 66, 66 },
647     { "gray27", 69, 69, 69 },
648     { "gray28", 71, 71, 71 },
649     { "gray29", 74, 74, 74 },
650     { "gray3", 8, 8, 8 },
651     { "gray30", 77, 77, 77 },
652     { "gray31", 79, 79, 79 },
653     { "gray32", 82, 82, 82 },
654     { "gray33", 84, 84, 84 },
655     { "gray34", 87, 87, 87 },
656     { "gray35", 89, 89, 89 },
657     { "gray36", 92, 92, 92 },
658     { "gray37", 94, 94, 94 },
659     { "gray38", 97, 97, 97 },
660     { "gray39", 99, 99, 99 },
661     { "gray4", 10, 10, 10 },
662     { "gray40", 102, 102, 102 },
663     { "gray41", 105, 105, 105 },
664     { "gray42", 107, 107, 107 },
665     { "gray43", 110, 110, 110 },
666     { "gray44", 112, 112, 112 },
667     { "gray45", 115, 115, 115 },
668     { "gray46", 117, 117, 117 },
669     { "gray47", 120, 120, 120 },
670     { "gray48", 122, 122, 122 },
671     { "gray49", 125, 125, 125 },
672     { "gray5", 13, 13, 13 },
673     { "gray50", 127, 127, 127 },
674     { "gray51", 130, 130, 130 },
675     { "gray52", 133, 133, 133 },
676     { "gray53", 135, 135, 135 },
677     { "gray54", 138, 138, 138 },
678     { "gray55", 140, 140, 140 },
679     { "gray56", 143, 143, 143 },
680     { "gray57", 145, 145, 145 },
681     { "gray58", 148, 148, 148 },
682     { "gray59", 150, 150, 150 },
683     { "gray6", 15, 15, 15 },
684     { "gray60", 153, 153, 153 },
685     { "gray61", 156, 156, 156 },
686     { "gray62", 158, 158, 158 },
687     { "gray63", 161, 161, 161 },
688     { "gray64", 163, 163, 163 },
689     { "gray65", 166, 166, 166 },
690     { "gray66", 168, 168, 168 },
691     { "gray67", 171, 171, 171 },
692     { "gray68", 173, 173, 173 },
693     { "gray69", 176, 176, 176 },
694     { "gray7", 18, 18, 18 },
695     { "gray70", 179, 179, 179 },
696     { "gray71", 181, 181, 181 },
697     { "gray72", 184, 184, 184 },
698     { "gray73", 186, 186, 186 },
699     { "gray74", 189, 189, 189 },
700     { "gray75", 191, 191, 191 },
701     { "gray76", 194, 194, 194 },
702     { "gray77", 196, 196, 196 },
703     { "gray78", 199, 199, 199 },
704     { "gray79", 201, 201, 201 },
705     { "gray8", 20, 20, 20 },
706     { "gray80", 204, 204, 204 },
707     { "gray81", 207, 207, 207 },
708     { "gray82", 209, 209, 209 },
709     { "gray83", 212, 212, 212 },
710     { "gray84", 214, 214, 214 },
711     { "gray85", 217, 217, 217 },
712     { "gray86", 219, 219, 219 },
713     { "gray87", 222, 222, 222 },
714     { "gray88", 224, 224, 224 },
715     { "gray89", 227, 227, 227 },
716     { "gray9", 23, 23, 23 },
717     { "gray90", 229, 229, 229 },
718     { "gray91", 232, 232, 232 },
719     { "gray92", 235, 235, 235 },
720     { "gray93", 237, 237, 237 },
721     { "gray94", 240, 240, 240 },
722     { "gray95", 242, 242, 242 },
723     { "gray96", 245, 245, 245 },
724     { "gray97", 247, 247, 247 },
725     { "gray98", 250, 250, 250 },
726     { "gray99", 252, 252, 252 },
727     { "green", 0, 255, 0 },
728     { "green yellow", 173, 255, 47 },
729     { "green1", 0, 255, 0 },
730     { "green2", 0, 238, 0 },
731     { "green3", 0, 205, 0 },
732     { "green4", 0, 139, 0 },
733     { "GreenYellow", 173, 255, 47 },
734     { "grey", 190, 190, 190 },
735     { "grey0", 0, 0, 0 },
736     { "grey1", 3, 3, 3 },
737     { "grey10", 26, 26, 26 },
738     { "grey100", 255, 255, 255 },
739     { "grey11", 28, 28, 28 },
740     { "grey12", 31, 31, 31 },
741     { "grey13", 33, 33, 33 },
742     { "grey14", 36, 36, 36 },
743     { "grey15", 38, 38, 38 },
744     { "grey16", 41, 41, 41 },
745     { "grey17", 43, 43, 43 },
746     { "grey18", 46, 46, 46 },
747     { "grey19", 48, 48, 48 },
748     { "grey2", 5, 5, 5 },
749     { "grey20", 51, 51, 51 },
750     { "grey21", 54, 54, 54 },
751     { "grey22", 56, 56, 56 },
752     { "grey23", 59, 59, 59 },
753     { "grey24", 61, 61, 61 },
754     { "grey25", 64, 64, 64 },
755     { "grey26", 66, 66, 66 },
756     { "grey27", 69, 69, 69 },
757     { "grey28", 71, 71, 71 },
758     { "grey29", 74, 74, 74 },
759     { "grey3", 8, 8, 8 },
760     { "grey30", 77, 77, 77 },
761     { "grey31", 79, 79, 79 },
762     { "grey32", 82, 82, 82 },
763     { "grey33", 84, 84, 84 },
764     { "grey34", 87, 87, 87 },
765     { "grey35", 89, 89, 89 },
766     { "grey36", 92, 92, 92 },
767     { "grey37", 94, 94, 94 },
768     { "grey38", 97, 97, 97 },
769     { "grey39", 99, 99, 99 },
770     { "grey4", 10, 10, 10 },
771     { "grey40", 102, 102, 102 },
772     { "grey41", 105, 105, 105 },
773     { "grey42", 107, 107, 107 },
774     { "grey43", 110, 110, 110 },
775     { "grey44", 112, 112, 112 },
776     { "grey45", 115, 115, 115 },
777     { "grey46", 117, 117, 117 },
778     { "grey47", 120, 120, 120 },
779     { "grey48", 122, 122, 122 },
780     { "grey49", 125, 125, 125 },
781     { "grey5", 13, 13, 13 },
782     { "grey50", 127, 127, 127 },
783     { "grey51", 130, 130, 130 },
784     { "grey52", 133, 133, 133 },
785     { "grey53", 135, 135, 135 },
786     { "grey54", 138, 138, 138 },
787     { "grey55", 140, 140, 140 },
788     { "grey56", 143, 143, 143 },
789     { "grey57", 145, 145, 145 },
790     { "grey58", 148, 148, 148 },
791     { "grey59", 150, 150, 150 },
792     { "grey6", 15, 15, 15 },
793     { "grey60", 153, 153, 153 },
794     { "grey61", 156, 156, 156 },
795     { "grey62", 158, 158, 158 },
796     { "grey63", 161, 161, 161 },
797     { "grey64", 163, 163, 163 },
798     { "grey65", 166, 166, 166 },
799     { "grey66", 168, 168, 168 },
800     { "grey67", 171, 171, 171 },
801     { "grey68", 173, 173, 173 },
802     { "grey69", 176, 176, 176 },
803     { "grey7", 18, 18, 18 },
804     { "grey70", 179, 179, 179 },
805     { "grey71", 181, 181, 181 },
806     { "grey72", 184, 184, 184 },
807     { "grey73", 186, 186, 186 },
808     { "grey74", 189, 189, 189 },
809     { "grey75", 191, 191, 191 },
810     { "grey76", 194, 194, 194 },
811     { "grey77", 196, 196, 196 },
812     { "grey78", 199, 199, 199 },
813     { "grey79", 201, 201, 201 },
814     { "grey8", 20, 20, 20 },
815     { "grey80", 204, 204, 204 },
816     { "grey81", 207, 207, 207 },
817     { "grey82", 209, 209, 209 },
818     { "grey83", 212, 212, 212 },
819     { "grey84", 214, 214, 214 },
820     { "grey85", 217, 217, 217 },
821     { "grey86", 219, 219, 219 },
822     { "grey87", 222, 222, 222 },
823     { "grey88", 224, 224, 224 },
824     { "grey89", 227, 227, 227 },
825     { "grey9", 23, 23, 23 },
826     { "grey90", 229, 229, 229 },
827     { "grey91", 232, 232, 232 },
828     { "grey92", 235, 235, 235 },
829     { "grey93", 237, 237, 237 },
830     { "grey94", 240, 240, 240 },
831     { "grey95", 242, 242, 242 },
832     { "grey96", 245, 245, 245 },
833     { "grey97", 247, 247, 247 },
834     { "grey98", 250, 250, 250 },
835     { "grey99", 252, 252, 252 },
836     { "honeydew", 240, 255, 240 },
837     { "honeydew1", 240, 255, 240 },
838     { "honeydew2", 224, 238, 224 },
839     { "honeydew3", 193, 205, 193 },
840     { "honeydew4", 131, 139, 131 },
841     { "hot pink", 255, 105, 180 },
842     { "HotPink", 255, 105, 180 },
843     { "HotPink1", 255, 110, 180 },
844     { "HotPink2", 238, 106, 167 },
845     { "HotPink3", 205, 96, 144 },
846     { "HotPink4", 139, 58, 98 },
847     { "indian red", 205, 92, 92 },
848     { "IndianRed", 205, 92, 92 },
849     { "IndianRed1", 255, 106, 106 },
850     { "IndianRed2", 238, 99, 99 },
851     { "IndianRed3", 205, 85, 85 },
852     { "IndianRed4", 139, 58, 58 },
853     { "ivory", 255, 255, 240 },
854     { "ivory1", 255, 255, 240 },
855     { "ivory2", 238, 238, 224 },
856     { "ivory3", 205, 205, 193 },
857     { "ivory4", 139, 139, 131 },
858     { "khaki", 240, 230, 140 },
859     { "khaki1", 255, 246, 143 },
860     { "khaki2", 238, 230, 133 },
861     { "khaki3", 205, 198, 115 },
862     { "khaki4", 139, 134, 78 },
863     { "lavender", 230, 230, 250 },
864     { "lavender blush", 255, 240, 245 },
865     { "LavenderBlush", 255, 240, 245 },
866     { "LavenderBlush1", 255, 240, 245 },
867     { "LavenderBlush2", 238, 224, 229 },
868     { "LavenderBlush3", 205, 193, 197 },
869     { "LavenderBlush4", 139, 131, 134 },
870     { "lawn green", 124, 252, 0 },
871     { "LawnGreen", 124, 252, 0 },
872     { "lemon chiffon", 255, 250, 205 },
873     { "LemonChiffon", 255, 250, 205 },
874     { "LemonChiffon1", 255, 250, 205 },
875     { "LemonChiffon2", 238, 233, 191 },
876     { "LemonChiffon3", 205, 201, 165 },
877     { "LemonChiffon4", 139, 137, 112 },
878     { "light blue", 173, 216, 230 },
879     { "light coral", 240, 128, 128 },
880     { "light cyan", 224, 255, 255 },
881     { "light goldenrod", 238, 221, 130 },
882     { "light goldenrod yellow", 250, 250, 210 },
883     { "light gray", 211, 211, 211 },
884     { "light green", 144, 238, 144 },
885     { "light grey", 211, 211, 211 },
886     { "light pink", 255, 182, 193 },
887     { "light salmon", 255, 160, 122 },
888     { "light sea green", 32, 178, 170 },
889     { "light sky blue", 135, 206, 250 },
890     { "light slate blue", 132, 112, 255 },
891     { "light slate gray", 119, 136, 153 },
892     { "light slate grey", 119, 136, 153 },
893     { "light steel blue", 176, 196, 222 },
894     { "light yellow", 255, 255, 224 },
895     { "LightBlue", 173, 216, 230 },
896     { "LightBlue1", 191, 239, 255 },
897     { "LightBlue2", 178, 223, 238 },
898     { "LightBlue3", 154, 192, 205 },
899     { "LightBlue4", 104, 131, 139 },
900     { "LightCoral", 240, 128, 128 },
901     { "LightCyan", 224, 255, 255 },
902     { "LightCyan1", 224, 255, 255 },
903     { "LightCyan2", 209, 238, 238 },
904     { "LightCyan3", 180, 205, 205 },
905     { "LightCyan4", 122, 139, 139 },
906     { "LightGoldenrod", 238, 221, 130 },
907     { "LightGoldenrod1", 255, 236, 139 },
908     { "LightGoldenrod2", 238, 220, 130 },
909     { "LightGoldenrod3", 205, 190, 112 },
910     { "LightGoldenrod4", 139, 129, 76 },
911     { "LightGoldenrodYellow", 250, 250, 210 },
912     { "LightGray", 211, 211, 211 },
913     { "LightGreen", 144, 238, 144 },
914     { "LightGrey", 211, 211, 211 },
915     { "LightPink", 255, 182, 193 },
916     { "LightPink1", 255, 174, 185 },
917     { "LightPink2", 238, 162, 173 },
918     { "LightPink3", 205, 140, 149 },
919     { "LightPink4", 139, 95, 101 },
920     { "LightSalmon", 255, 160, 122 },
921     { "LightSalmon1", 255, 160, 122 },
922     { "LightSalmon2", 238, 149, 114 },
923     { "LightSalmon3", 205, 129, 98 },
924     { "LightSalmon4", 139, 87, 66 },
925     { "LightSeaGreen", 32, 178, 170 },
926     { "LightSkyBlue", 135, 206, 250 },
927     { "LightSkyBlue1", 176, 226, 255 },
928     { "LightSkyBlue2", 164, 211, 238 },
929     { "LightSkyBlue3", 141, 182, 205 },
930     { "LightSkyBlue4", 96, 123, 139 },
931     { "LightSlateBlue", 132, 112, 255 },
932     { "LightSlateGray", 119, 136, 153 },
933     { "LightSlateGrey", 119, 136, 153 },
934     { "LightSteelBlue", 176, 196, 222 },
935     { "LightSteelBlue1", 202, 225, 255 },
936     { "LightSteelBlue2", 188, 210, 238 },
937     { "LightSteelBlue3", 162, 181, 205 },
938     { "LightSteelBlue4", 110, 123, 139 },
939     { "LightYellow", 255, 255, 224 },
940     { "LightYellow1", 255, 255, 224 },
941     { "LightYellow2", 238, 238, 209 },
942     { "LightYellow3", 205, 205, 180 },
943     { "LightYellow4", 139, 139, 122 },
944     { "lime green", 50, 205, 50 },
945     { "LimeGreen", 50, 205, 50 },
946     { "linen", 250, 240, 230 },
947     { "magenta", 255, 0, 255 },
948     { "magenta1", 255, 0, 255 },
949     { "magenta2", 238, 0, 238 },
950     { "magenta3", 205, 0, 205 },
951     { "magenta4", 139, 0, 139 },
952     { "maroon", 176, 48, 96 },
953     { "maroon1", 255, 52, 179 },
954     { "maroon2", 238, 48, 167 },
955     { "maroon3", 205, 41, 144 },
956     { "maroon4", 139, 28, 98 },
957     { "medium aquamarine", 102, 205, 170 },
958     { "medium blue", 0, 0, 205 },
959     { "medium orchid", 186, 85, 211 },
960     { "medium purple", 147, 112, 219 },
961     { "medium sea green", 60, 179, 113 },
962     { "medium slate blue", 123, 104, 238 },
963     { "medium spring green", 0, 250, 154 },
964     { "medium turquoise", 72, 209, 204 },
965     { "medium violet red", 199, 21, 133 },
966     { "MediumAquamarine", 102, 205, 170 },
967     { "MediumBlue", 0, 0, 205 },
968     { "MediumOrchid", 186, 85, 211 },
969     { "MediumOrchid1", 224, 102, 255 },
970     { "MediumOrchid2", 209, 95, 238 },
971     { "MediumOrchid3", 180, 82, 205 },
972     { "MediumOrchid4", 122, 55, 139 },
973     { "MediumPurple", 147, 112, 219 },
974     { "MediumPurple1", 171, 130, 255 },
975     { "MediumPurple2", 159, 121, 238 },
976     { "MediumPurple3", 137, 104, 205 },
977     { "MediumPurple4", 93, 71, 139 },
978     { "MediumSeaGreen", 60, 179, 113 },
979     { "MediumSlateBlue", 123, 104, 238 },
980     { "MediumSpringGreen", 0, 250, 154 },
981     { "MediumTurquoise", 72, 209, 204 },
982     { "MediumVioletRed", 199, 21, 133 },
983     { "midnight blue", 25, 25, 112 },
984     { "MidnightBlue", 25, 25, 112 },
985     { "mint cream", 245, 255, 250 },
986     { "MintCream", 245, 255, 250 },
987     { "misty rose", 255, 228, 225 },
988     { "MistyRose", 255, 228, 225 },
989     { "MistyRose1", 255, 228, 225 },
990     { "MistyRose2", 238, 213, 210 },
991     { "MistyRose3", 205, 183, 181 },
992     { "MistyRose4", 139, 125, 123 },
993     { "moccasin", 255, 228, 181 },
994     { "navajo white", 255, 222, 173 },
995     { "NavajoWhite", 255, 222, 173 },
996     { "NavajoWhite1", 255, 222, 173 },
997     { "NavajoWhite2", 238, 207, 161 },
998     { "NavajoWhite3", 205, 179, 139 },
999     { "NavajoWhite4", 139, 121, 94 },
1000     { "navy", 0, 0, 128 },
1001     { "navy blue", 0, 0, 128 },
1002     { "NavyBlue", 0, 0, 128 },
1003     { "old lace", 253, 245, 230 },
1004     { "OldLace", 253, 245, 230 },
1005     { "olive drab", 107, 142, 35 },
1006     { "OliveDrab", 107, 142, 35 },
1007     { "OliveDrab1", 192, 255, 62 },
1008     { "OliveDrab2", 179, 238, 58 },
1009     { "OliveDrab3", 154, 205, 50 },
1010     { "OliveDrab4", 105, 139, 34 },
1011     { "orange", 255, 165, 0 },
1012     { "orange red", 255, 69, 0 },
1013     { "orange1", 255, 165, 0 },
1014     { "orange2", 238, 154, 0 },
1015     { "orange3", 205, 133, 0 },
1016     { "orange4", 139, 90, 0 },
1017     { "OrangeRed", 255, 69, 0 },
1018     { "OrangeRed1", 255, 69, 0 },
1019     { "OrangeRed2", 238, 64, 0 },
1020     { "OrangeRed3", 205, 55, 0 },
1021     { "OrangeRed4", 139, 37, 0 },
1022     { "orchid", 218, 112, 214 },
1023     { "orchid1", 255, 131, 250 },
1024     { "orchid2", 238, 122, 233 },
1025     { "orchid3", 205, 105, 201 },
1026     { "orchid4", 139, 71, 137 },
1027     { "pale goldenrod", 238, 232, 170 },
1028     { "pale green", 152, 251, 152 },
1029     { "pale turquoise", 175, 238, 238 },
1030     { "pale violet red", 219, 112, 147 },
1031     { "PaleGoldenrod", 238, 232, 170 },
1032     { "PaleGreen", 152, 251, 152 },
1033     { "PaleGreen1", 154, 255, 154 },
1034     { "PaleGreen2", 144, 238, 144 },
1035     { "PaleGreen3", 124, 205, 124 },
1036     { "PaleGreen4", 84, 139, 84 },
1037     { "PaleTurquoise", 175, 238, 238 },
1038     { "PaleTurquoise1", 187, 255, 255 },
1039     { "PaleTurquoise2", 174, 238, 238 },
1040     { "PaleTurquoise3", 150, 205, 205 },
1041     { "PaleTurquoise4", 102, 139, 139 },
1042     { "PaleVioletRed", 219, 112, 147 },
1043     { "PaleVioletRed1", 255, 130, 171 },
1044     { "PaleVioletRed2", 238, 121, 159 },
1045     { "PaleVioletRed3", 205, 104, 137 },
1046     { "PaleVioletRed4", 139, 71, 93 },
1047     { "papaya whip", 255, 239, 213 },
1048     { "PapayaWhip", 255, 239, 213 },
1049     { "peach puff", 255, 218, 185 },
1050     { "PeachPuff", 255, 218, 185 },
1051     { "PeachPuff1", 255, 218, 185 },
1052     { "PeachPuff2", 238, 203, 173 },
1053     { "PeachPuff3", 205, 175, 149 },
1054     { "PeachPuff4", 139, 119, 101 },
1055     { "peru", 205, 133, 63 },
1056     { "pink", 255, 192, 203 },
1057     { "pink1", 255, 181, 197 },
1058     { "pink2", 238, 169, 184 },
1059     { "pink3", 205, 145, 158 },
1060     { "pink4", 139, 99, 108 },
1061     { "plum", 221, 160, 221 },
1062     { "plum1", 255, 187, 255 },
1063     { "plum2", 238, 174, 238 },
1064     { "plum3", 205, 150, 205 },
1065     { "plum4", 139, 102, 139 },
1066     { "powder blue", 176, 224, 230 },
1067     { "PowderBlue", 176, 224, 230 },
1068     { "purple", 160, 32, 240 },
1069     { "purple1", 155, 48, 255 },
1070     { "purple2", 145, 44, 238 },
1071     { "purple3", 125, 38, 205 },
1072     { "purple4", 85, 26, 139 },
1073     { "red", 255, 0, 0 },
1074     { "red1", 255, 0, 0 },
1075     { "red2", 238, 0, 0 },
1076     { "red3", 205, 0, 0 },
1077     { "red4", 139, 0, 0 },
1078     { "rosy brown", 188, 143, 143 },
1079     { "RosyBrown", 188, 143, 143 },
1080     { "RosyBrown1", 255, 193, 193 },
1081     { "RosyBrown2", 238, 180, 180 },
1082     { "RosyBrown3", 205, 155, 155 },
1083     { "RosyBrown4", 139, 105, 105 },
1084     { "royal blue", 65, 105, 225 },
1085     { "RoyalBlue", 65, 105, 225 },
1086     { "RoyalBlue1", 72, 118, 255 },
1087     { "RoyalBlue2", 67, 110, 238 },
1088     { "RoyalBlue3", 58, 95, 205 },
1089     { "RoyalBlue4", 39, 64, 139 },
1090     { "saddle brown", 139, 69, 19 },
1091     { "SaddleBrown", 139, 69, 19 },
1092     { "salmon", 250, 128, 114 },
1093     { "salmon1", 255, 140, 105 },
1094     { "salmon2", 238, 130, 98 },
1095     { "salmon3", 205, 112, 84 },
1096     { "salmon4", 139, 76, 57 },
1097     { "sandy brown", 244, 164, 96 },
1098     { "SandyBrown", 244, 164, 96 },
1099     { "sea green", 46, 139, 87 },
1100     { "SeaGreen", 46, 139, 87 },
1101     { "SeaGreen1", 84, 255, 159 },
1102     { "SeaGreen2", 78, 238, 148 },
1103     { "SeaGreen3", 67, 205, 128 },
1104     { "SeaGreen4", 46, 139, 87 },
1105     { "seashell", 255, 245, 238 },
1106     { "seashell1", 255, 245, 238 },
1107     { "seashell2", 238, 229, 222 },
1108     { "seashell3", 205, 197, 191 },
1109     { "seashell4", 139, 134, 130 },
1110     { "sienna", 160, 82, 45 },
1111     { "sienna1", 255, 130, 71 },
1112     { "sienna2", 238, 121, 66 },
1113     { "sienna3", 205, 104, 57 },
1114     { "sienna4", 139, 71, 38 },
1115     { "sky blue", 135, 206, 235 },
1116     { "SkyBlue", 135, 206, 235 },
1117     { "SkyBlue1", 135, 206, 255 },
1118     { "SkyBlue2", 126, 192, 238 },
1119     { "SkyBlue3", 108, 166, 205 },
1120     { "SkyBlue4", 74, 112, 139 },
1121     { "slate blue", 106, 90, 205 },
1122     { "slate gray", 112, 128, 144 },
1123     { "slate grey", 112, 128, 144 },
1124     { "SlateBlue", 106, 90, 205 },
1125     { "SlateBlue1", 131, 111, 255 },
1126     { "SlateBlue2", 122, 103, 238 },
1127     { "SlateBlue3", 105, 89, 205 },
1128     { "SlateBlue4", 71, 60, 139 },
1129     { "SlateGray", 112, 128, 144 },
1130     { "SlateGray1", 198, 226, 255 },
1131     { "SlateGray2", 185, 211, 238 },
1132     { "SlateGray3", 159, 182, 205 },
1133     { "SlateGray4", 108, 123, 139 },
1134     { "SlateGrey", 112, 128, 144 },
1135     { "snow", 255, 250, 250 },
1136     { "snow1", 255, 250, 250 },
1137     { "snow2", 238, 233, 233 },
1138     { "snow3", 205, 201, 201 },
1139     { "snow4", 139, 137, 137 },
1140     { "spring green", 0, 255, 127 },
1141     { "SpringGreen", 0, 255, 127 },
1142     { "SpringGreen1", 0, 255, 127 },
1143     { "SpringGreen2", 0, 238, 118 },
1144     { "SpringGreen3", 0, 205, 102 },
1145     { "SpringGreen4", 0, 139, 69 },
1146     { "steel blue", 70, 130, 180 },
1147     { "SteelBlue", 70, 130, 180 },
1148     { "SteelBlue1", 99, 184, 255 },
1149     { "SteelBlue2", 92, 172, 238 },
1150     { "SteelBlue3", 79, 148, 205 },
1151     { "SteelBlue4", 54, 100, 139 },
1152     { "tan", 210, 180, 140 },
1153     { "tan1", 255, 165, 79 },
1154     { "tan2", 238, 154, 73 },
1155     { "tan3", 205, 133, 63 },
1156     { "tan4", 139, 90, 43 },
1157     { "thistle", 216, 191, 216 },
1158     { "thistle1", 255, 225, 255 },
1159     { "thistle2", 238, 210, 238 },
1160     { "thistle3", 205, 181, 205 },
1161     { "thistle4", 139, 123, 139 },
1162     { "tomato", 255, 99, 71 },
1163     { "tomato1", 255, 99, 71 },
1164     { "tomato2", 238, 92, 66 },
1165     { "tomato3", 205, 79, 57 },
1166     { "tomato4", 139, 54, 38 },
1167     { "turquoise", 64, 224, 208 },
1168     { "turquoise1", 0, 245, 255 },
1169     { "turquoise2", 0, 229, 238 },
1170     { "turquoise3", 0, 197, 205 },
1171     { "turquoise4", 0, 134, 139 },
1172     { "violet", 238, 130, 238 },
1173     { "violet red", 208, 32, 144 },
1174     { "VioletRed", 208, 32, 144 },
1175     { "VioletRed1", 255, 62, 150 },
1176     { "VioletRed2", 238, 58, 140 },
1177     { "VioletRed3", 205, 50, 120 },
1178     { "VioletRed4", 139, 34, 82 },
1179     { "wheat", 245, 222, 179 },
1180     { "wheat1", 255, 231, 186 },
1181     { "wheat2", 238, 216, 174 },
1182     { "wheat3", 205, 186, 150 },
1183     { "wheat4", 139, 126, 102 },
1184     { "white", 255, 255, 255 },
1185     { "white smoke", 245, 245, 245 },
1186     { "WhiteSmoke", 245, 245, 245 },
1187     { "yellow", 255, 255, 0 },
1188     { "yellow green", 154, 205, 50 },
1189     { "yellow1", 255, 255, 0 },
1190     { "yellow2", 238, 238, 0 },
1191     { "yellow3", 205, 205, 0 },
1192     { "yellow4", 139, 139, 0 },
1193     { "YellowGreen", 154, 205, 50 }
1194 };
1195  
1196 #define numXColors (sizeof (xColors) / sizeof (*xColors))
1197  
1198 /*
1199  *----------------------------------------------------------------------
1200  *
1201  * FindColor --
1202  *
1203  *      This routine finds the color entry that corresponds to the
1204  *      specified color.
1205  *
1206  * Results:
1207  *      Returns non-zero on success.  The RGB values of the XColor
1208  *      will be initialized to the proper values on success.
1209  *
1210  * Side effects:
1211  *      None.
1212  *
1213  *----------------------------------------------------------------------
1214  */
1215
1216 static int
1217 compare_xcolor_entries (const void *a, const void *b)
1218 {
1219   return strcasecmp ((const char *) a, ((const XColorEntry *) b)->name);
1220 }
1221
1222 static int
1223 FindColor(const char *name,
1224           GdkColor   *colorPtr)
1225 {
1226   XColorEntry *found;
1227
1228   found = bsearch (name, xColors, numXColors, sizeof (XColorEntry),
1229                    compare_xcolor_entries);
1230   if (found == NULL)
1231     return 0;
1232   
1233   colorPtr->red = (found->red * 65535) / 255;
1234   colorPtr->green = (found->green * 65535) / 255;
1235   colorPtr->blue = (found->blue * 65535) / 255;
1236   return 1;
1237 }
1238
1239 /*
1240  *----------------------------------------------------------------------
1241  *
1242  * parse_color --
1243  *
1244  *      Partial implementation of X color name parsing interface.
1245  *
1246  * Results:
1247  *      Returns non-zero on success.
1248  *
1249  * Side effects:
1250  *      None.
1251  *
1252  *----------------------------------------------------------------------
1253  */
1254
1255 gboolean
1256 parse_color(Colormap    map,
1257             const char *spec,
1258             GdkColor   *colorPtr)
1259 {
1260     if (spec[0] == '#') {
1261         char fmt[16];
1262         int i, red, green, blue;
1263
1264         if ((i = strlen(spec+1))%3) {
1265             return 0;
1266         }
1267         i /= 3;
1268
1269         sprintf(fmt, "%%%dx%%%dx%%%dx", i, i, i);
1270         if (sscanf(spec+1, fmt, &red, &green, &blue) != 3) {
1271             return 0;
1272         }
1273         if (i == 4)
1274           {
1275             colorPtr->red = red;
1276             colorPtr->green = green;
1277             colorPtr->blue = blue;
1278           }
1279         else if (i == 1)
1280           {
1281             colorPtr->red = (red * 65535) / 15;
1282             colorPtr->green = (green * 65535) / 15;
1283             colorPtr->blue = (blue * 65535) / 15;
1284           }
1285         else if (i == 2)
1286           {
1287             colorPtr->red = (red * 65535) / 255;
1288             colorPtr->green = (green * 65535) / 255;
1289             colorPtr->blue = (blue * 65535) / 255;
1290           }
1291         else /* if (i == 3) */
1292           {
1293             colorPtr->red = (red * 65535) / 4095;
1294             colorPtr->green = (green * 65535) / 4095;
1295             colorPtr->blue = (blue * 65535) / 4095;
1296           }
1297     } else {
1298         if (!FindColor(spec, colorPtr)) {
1299             return 0;
1300         }
1301     }
1302     return 1;
1303 }
1304
1305 /* End of code from Tk8.0 */
1306
1307 static Colormap
1308 DefaultColormap ()
1309 {
1310   static Colormap colormap;
1311   gint i;
1312
1313   if (colormap)
1314     return colormap;
1315
1316   colormap = create_colormap ( NULL, NULL, AllocNone);
1317   return colormap;
1318 }
1319
1320 \f
1321 GdkColormap*
1322 gdk_colormap_new (GdkVisual *visual,
1323                   gint       private_cmap)
1324 {
1325   GdkColormap *colormap;
1326   GdkColormapPrivate *private;
1327   Visual *xvisual;
1328   int size;
1329   unsigned int i;
1330
1331   g_return_val_if_fail (visual != NULL, NULL);
1332
1333   private = g_new (GdkColormapPrivate, 1);
1334   colormap = (GdkColormap*) private;
1335
1336   private->visual = visual;
1337   private->ref_count = 1;
1338
1339   private->hash = NULL;
1340   private->last_sync_time = 0;
1341   private->info = NULL;
1342   
1343   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
1344
1345   colormap->size = visual->colormap_size;
1346   colormap->colors = g_new (GdkColor, colormap->size);
1347
1348   switch (visual->type)
1349     {
1350     case GDK_VISUAL_GRAYSCALE:
1351     case GDK_VISUAL_PSEUDO_COLOR:
1352       private->info = g_new0 (GdkColorInfo, colormap->size);
1353       
1354       private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1355                                         (GCompareFunc) gdk_color_equal);
1356       
1357       private->private_val = private_cmap;
1358       private->xcolormap = create_colormap (gdk_root_window, xvisual,
1359                                             (private_cmap) ? (AllocAll) : (AllocNone));
1360
1361       if (private_cmap)
1362         {
1363           PALETTEENTRY pal[256];
1364           guint npal;
1365
1366           npal = GetPaletteEntries (private->xcolormap->palette, 0, colormap->size, pal);
1367           for (i = 0; i < colormap->size; i++)
1368             {
1369               colormap->colors[i].pixel = i;
1370               if (i >= npal)
1371                 {
1372                   colormap->colors[i].red =
1373                     colormap->colors[i].green =
1374                     colormap->colors[i].blue = 0;
1375                 }
1376               else
1377                 {
1378                   colormap->colors[i].red = (pal[i].peRed * 65535) / 255;
1379                   colormap->colors[i].green = (pal[i].peGreen * 65525) / 255;
1380                   colormap->colors[i].blue = (pal[i].peBlue * 65535) / 255;
1381                 }
1382             }
1383           gdk_colormap_change (colormap, colormap->size);
1384         }
1385       break;
1386
1387     case GDK_VISUAL_STATIC_GRAY:
1388     case GDK_VISUAL_STATIC_COLOR:
1389     case GDK_VISUAL_TRUE_COLOR:
1390       private->private_val = FALSE;
1391       private->xcolormap = create_colormap (gdk_root_window,
1392                                             xvisual, AllocNone);
1393       break;
1394     }
1395
1396   gdk_colormap_add (colormap);
1397
1398   return colormap;
1399 }
1400
1401 static void
1402 gdk_colormap_real_destroy (GdkColormap *colormap)
1403 {
1404   GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
1405
1406   g_return_if_fail (colormap != NULL);
1407   g_return_if_fail (private->ref_count == 0);
1408
1409   gdk_colormap_remove (colormap);
1410   XFreeColormap (private->xcolormap);
1411
1412   if (private->hash)
1413     g_hash_table_destroy (private->hash);
1414   
1415   g_free (private->info);
1416   g_free (colormap->colors);
1417   g_free (colormap);
1418 }
1419
1420 GdkColormap*
1421 gdk_colormap_ref (GdkColormap *cmap)
1422 {
1423   GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
1424
1425   g_return_val_if_fail (cmap != NULL, NULL);
1426
1427   private->ref_count += 1;
1428   return cmap;
1429 }
1430
1431 void
1432 gdk_colormap_unref (GdkColormap *cmap)
1433 {
1434   GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
1435
1436   g_return_if_fail (cmap != NULL);
1437   g_return_if_fail (private->ref_count > 0);
1438
1439   private->ref_count -= 1;
1440   if (private->ref_count == 0)
1441     gdk_colormap_real_destroy (cmap);
1442 }
1443
1444 #define MIN_SYNC_TIME 2
1445
1446 GdkVisual *
1447 gdk_colormap_get_visual (GdkColormap *colormap)
1448 {
1449   GdkColormapPrivate *private;
1450
1451   g_return_val_if_fail (colormap != NULL, NULL);
1452   
1453   private = (GdkColormapPrivate *)colormap;
1454
1455   return private->visual;
1456 }
1457      
1458 void
1459 gdk_colormap_sync (GdkColormap *colormap,
1460                    gboolean     force)
1461 {
1462   time_t current_time;
1463   GdkColormapPrivate *private = (GdkColormapPrivate *)colormap;
1464   XColor *xpalette;
1465   gint nlookup;
1466   gint i;
1467   
1468   g_return_if_fail (colormap != NULL);
1469
1470   current_time = time (NULL);
1471   if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME))
1472     return;
1473
1474   private->last_sync_time = current_time;
1475
1476   nlookup = 0;
1477   xpalette = g_new (XColor, colormap->size);
1478   
1479   nlookup = GetPaletteEntries (private->xcolormap->palette,
1480                                0, colormap->size, xpalette);
1481   
1482   for (i = 0; i < nlookup; i++)
1483     {
1484       colormap->colors[i].pixel = i;
1485       colormap->colors[i].red = (xpalette[i].peRed * 65535) / 255;
1486       colormap->colors[i].green = (xpalette[i].peGreen * 65535) / 255;
1487       colormap->colors[i].blue = (xpalette[i].peBlue * 65535) / 255;
1488     }
1489
1490   for (  ; i < colormap->size; i++)
1491     {
1492       colormap->colors[i].pixel = i;
1493       colormap->colors[i].red = 0;
1494       colormap->colors[i].green = 0;
1495       colormap->colors[i].blue = 0;
1496     }
1497
1498   g_free (xpalette);
1499 }
1500                    
1501
1502 GdkColormap*
1503 gdk_colormap_get_system (void)
1504 {
1505   static GdkColormap *colormap = NULL;
1506   GdkColormapPrivate *private;
1507   gint i;
1508
1509   if (!colormap)
1510     {
1511       private = g_new (GdkColormapPrivate, 1);
1512       colormap = (GdkColormap*) private;
1513
1514       private->xcolormap = DefaultColormap ();
1515       private->visual = gdk_visual_get_system ();
1516       private->private_val = FALSE;
1517       private->ref_count = 1;
1518
1519       private->hash = NULL;
1520       private->last_sync_time = 0;
1521       private->info = NULL;
1522
1523       colormap->colors = NULL;
1524       colormap->size = private->visual->colormap_size;
1525
1526       if ((private->visual->type == GDK_VISUAL_GRAYSCALE) ||
1527           (private->visual->type == GDK_VISUAL_PSEUDO_COLOR))
1528         {
1529           private->info = g_new0 (GdkColorInfo, colormap->size);
1530           colormap->colors = g_new (GdkColor, colormap->size);
1531           
1532           private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
1533                                             (GCompareFunc) gdk_color_equal);
1534
1535           gdk_colormap_sync (colormap, TRUE);
1536         }
1537       gdk_colormap_add (colormap);
1538     }
1539
1540   return colormap;
1541 }
1542
1543 gint
1544 gdk_colormap_get_system_size (void)
1545 {
1546   gint bitspixel;
1547   
1548   bitspixel = GetDeviceCaps (gdk_DC, BITSPIXEL);
1549
1550   if (bitspixel == 1)
1551     return 2;
1552   else if (bitspixel == 4)
1553     return 16;
1554   else if (bitspixel == 8)
1555     return 256;
1556   else if (bitspixel == 12)
1557     return 32;
1558   else if (bitspixel == 16)
1559     return 64;
1560   else /* if (bitspixel >= 24) */
1561     return 256;
1562 }
1563
1564 void
1565 gdk_colormap_change (GdkColormap *colormap,
1566                      gint         ncolors)
1567 {
1568   GdkColormapPrivate *private;
1569   GdkVisual *visual;
1570   XColor *palette;
1571   gint shift;
1572   int max_colors;
1573   int size;
1574   int i;
1575
1576   g_return_if_fail (colormap != NULL);
1577
1578   palette = g_new (XColor, ncolors);
1579
1580   private = (GdkColormapPrivate*) colormap;
1581   switch (private->visual->type)
1582     {
1583     case GDK_VISUAL_GRAYSCALE:
1584     case GDK_VISUAL_PSEUDO_COLOR:
1585       for (i = 0; i < ncolors; i++)
1586         {
1587           palette[i].peRed = (colormap->colors[i].red >> 8);
1588           palette[i].peGreen = (colormap->colors[i].green >> 8);
1589           palette[i].peBlue = (colormap->colors[i].blue >> 8);
1590           palette[i].peFlags = 0;
1591         }
1592
1593       if (SetPaletteEntries (private->xcolormap->palette,
1594                              0, ncolors, palette) == 0)
1595         g_warning ("gdk_colormap_change: SetPaletteEntries failed");
1596       private->xcolormap->stale = TRUE;
1597       break;
1598
1599     default:
1600       break;
1601     }
1602
1603   g_free (palette);
1604 }
1605
1606 void
1607 gdk_colors_store (GdkColormap   *colormap,
1608                   GdkColor      *colors,
1609                   gint           ncolors)
1610 {
1611   gint i;
1612
1613   for (i = 0; i < ncolors; i++)
1614     {
1615       colormap->colors[i].pixel = colors[i].pixel;
1616       colormap->colors[i].red = colors[i].red;
1617       colormap->colors[i].green = colors[i].green;
1618       colormap->colors[i].blue = colors[i].blue;
1619     }
1620
1621   gdk_colormap_change (colormap, ncolors);
1622 }
1623
1624 gboolean
1625 gdk_colors_alloc (GdkColormap   *colormap,
1626                   gint           contiguous,
1627                   gulong        *planes,
1628                   gint           nplanes,
1629                   gulong        *pixels,
1630                   gint           npixels)
1631 {
1632   GdkColormapPrivate *private;
1633   gint return_val;
1634   gint i;
1635
1636   g_return_val_if_fail (colormap != NULL, 0);
1637
1638   private = (GdkColormapPrivate*) colormap;
1639
1640   return_val = alloc_color_cells (private->xcolormap, contiguous,
1641                                   planes, nplanes, pixels, npixels);
1642
1643   if (return_val)
1644     {
1645       for (i=0; i<npixels; i++)
1646         {
1647           private->info[pixels[i]].ref_count++;
1648           private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
1649         }
1650     }
1651
1652   return return_val;
1653 }
1654
1655 /* This is almost identical to gdk_colormap_free_colors.
1656  * Keep them in sync!
1657  */
1658 void
1659 gdk_colors_free (GdkColormap *colormap,
1660                  gulong      *in_pixels,
1661                  gint         in_npixels,
1662                  gulong       planes)
1663 {
1664   GdkColormapPrivate *private;
1665   gulong *pixels;
1666   gint npixels = 0;
1667   gint i;
1668
1669   g_return_if_fail (colormap != NULL);
1670   g_return_if_fail (in_pixels != NULL);
1671
1672   private = (GdkColormapPrivate*) colormap;
1673
1674   if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
1675       (private->visual->type != GDK_VISUAL_GRAYSCALE))
1676     return;
1677   
1678   pixels = g_new (gulong, in_npixels);
1679
1680   for (i=0; i<in_npixels; i++)
1681     {
1682       gulong pixel = in_pixels[i];
1683       
1684       if (private->info[pixel].ref_count)
1685         {
1686           private->info[pixel].ref_count--;
1687
1688           if (private->info[pixel].ref_count == 0)
1689             {
1690               pixels[npixels++] = pixel;
1691               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
1692                 g_hash_table_remove (private->hash, &colormap->colors[in_pixels[i]]);
1693               private->info[pixel].flags = 0;
1694             }
1695         }
1696     }
1697
1698
1699   if (npixels)
1700     XFreeColors (private->xcolormap, pixels, npixels, planes);
1701
1702   g_free (pixels);
1703 }
1704
1705 /*
1706  *--------------------------------------------------------------
1707  * gdk_color_copy
1708  *
1709  *   Copy a color structure into new storage.
1710  *
1711  * Arguments:
1712  *   "color" is the color struct to copy.
1713  *
1714  * Results:
1715  *   A new color structure.  Free it with gdk_color_free.
1716  *
1717  *--------------------------------------------------------------
1718  */
1719
1720 static GMemChunk *color_chunk;
1721
1722 GdkColor*
1723 gdk_color_copy (GdkColor *color)
1724 {
1725   GdkColor *new_color;
1726   
1727   g_return_val_if_fail (color != NULL, NULL);
1728
1729   if (color_chunk == NULL)
1730     color_chunk = g_mem_chunk_new ("colors",
1731                                    sizeof (GdkColor),
1732                                    4096,
1733                                    G_ALLOC_AND_FREE);
1734
1735   new_color = g_chunk_new (GdkColor, color_chunk);
1736   *new_color = *color;
1737   return new_color;
1738 }
1739
1740 /*
1741  *--------------------------------------------------------------
1742  * gdk_color_free
1743  *
1744  *   Free a color structure obtained from gdk_color_copy.  Do not use
1745  *   with other color structures.
1746  *
1747  * Arguments:
1748  *   "color" is the color struct to free.
1749  *
1750  *-------------------------------------------------------------- */
1751
1752 void
1753 gdk_color_free (GdkColor *color)
1754 {
1755   g_assert (color_chunk != NULL);
1756   g_return_if_fail (color != NULL);
1757
1758   g_mem_chunk_free (color_chunk, color);
1759 }
1760
1761 gint
1762 gdk_color_white (GdkColormap *colormap,
1763                  GdkColor    *color)
1764 {
1765   gint return_val;
1766
1767   g_return_val_if_fail (colormap != NULL, FALSE);
1768
1769   if (color)
1770     {
1771       color->red = 65535;
1772       color->green = 65535;
1773       color->blue = 65535;
1774
1775       return_val = gdk_color_alloc (colormap, color);
1776     }
1777   else
1778     return_val = FALSE;
1779
1780   return return_val;
1781 }
1782
1783 gint
1784 gdk_color_black (GdkColormap *colormap,
1785                  GdkColor    *color)
1786 {
1787   gint return_val;
1788
1789   g_return_val_if_fail (colormap != NULL, FALSE);
1790
1791   if (color)
1792     {
1793       color->red = 0;
1794       color->green = 0;
1795       color->blue = 0;
1796
1797       return_val = gdk_color_alloc (colormap, color);
1798     }
1799   else
1800     return_val = FALSE;
1801
1802   return return_val;
1803 }
1804
1805 gboolean
1806 gdk_color_parse (const gchar *spec,
1807                  GdkColor *color)
1808 {
1809   Colormap xcolormap;
1810   XColor xcolor;
1811   gboolean return_val;
1812
1813   g_return_val_if_fail (spec != NULL, FALSE);
1814   g_return_val_if_fail (color != NULL, FALSE);
1815
1816   xcolormap = DefaultColormap ();
1817
1818   if (parse_color (xcolormap, spec, color))
1819     return_val = TRUE;
1820   else
1821     return_val = FALSE;
1822
1823   return return_val;
1824 }
1825
1826 /********************
1827  * Color allocation *
1828  ********************/
1829
1830 /* Try to allocate a single color using alloc_color. If it succeeds,
1831  * cache the result in our colormap, and store in ret.
1832  */
1833 static gboolean 
1834 gdk_colormap_alloc1 (GdkColormap *colormap,
1835                      GdkColor    *color,
1836                      GdkColor    *ret)
1837 {
1838   GdkColormapPrivate *private;
1839   XColor xcolor;
1840
1841   private = (GdkColormapPrivate*) colormap;
1842
1843   xcolor.peRed = color->red >> 8;
1844   xcolor.peGreen = color->green >> 8;
1845   xcolor.peBlue = color->blue >> 8;
1846
1847   if (alloc_color (private->xcolormap, &xcolor, &ret->pixel))
1848     {
1849       ret->red = (xcolor.peRed * 65535) / 255;
1850       ret->green = (xcolor.peGreen * 65535) / 255;;
1851       ret->blue = (xcolor.peBlue * 65535) / 255;
1852       
1853       if ((guint) ret->pixel < colormap->size)
1854         {
1855           if (private->info[ret->pixel].ref_count) /* got a duplicate */
1856             {
1857               /* XXX */
1858             }
1859           else
1860             {
1861               colormap->colors[ret->pixel] = *color;
1862               private->info[ret->pixel].ref_count = 1;
1863
1864               g_hash_table_insert (private->hash,
1865                                    &colormap->colors[ret->pixel],
1866                                    &colormap->colors[ret->pixel]);
1867             }
1868         }
1869       return TRUE;
1870     }
1871   else
1872     {
1873       return FALSE;
1874     }
1875 }
1876
1877 static gint
1878 gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
1879                                      GdkColor    *colors,
1880                                      gint         ncolors,
1881                                      gboolean     writeable,
1882                                      gboolean     best_match,
1883                                      gboolean    *success)
1884 {
1885   GdkColormapPrivate *private;
1886   gulong *pixels;
1887   Status status;
1888   gint i, index;
1889
1890   private = (GdkColormapPrivate*) colormap;
1891
1892   if (private->private_val)
1893     {
1894       index = 0;
1895       for (i=0; i<ncolors; i++)
1896         {
1897           while ((index < colormap->size) && (private->info[index].ref_count != 0))
1898             index++;
1899           
1900           if (index < colormap->size)
1901             {
1902               colors[i].pixel = index;
1903               success[i] = TRUE;
1904               private->info[index].ref_count++;
1905               private->info[i].flags |= GDK_COLOR_WRITEABLE;
1906             }
1907           else
1908             break;
1909         }
1910       return i;
1911     }
1912   else
1913     {
1914       pixels = g_new (gulong, ncolors);
1915
1916       /* Allocation of a writeable color cells */
1917       status =  alloc_color_cells (private->xcolormap, FALSE, NULL,
1918                                    0, pixels, ncolors);
1919       if (status)
1920         {
1921           for (i=0; i<ncolors; i++)
1922             {
1923               colors[i].pixel = pixels[i];
1924               private->info[pixels[i]].ref_count++;
1925               private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
1926             }
1927         }
1928       
1929       g_free (pixels);
1930
1931       return status ? ncolors : 0; 
1932     }
1933 }
1934
1935 static gint
1936 gdk_colormap_alloc_colors_private (GdkColormap *colormap,
1937                                    GdkColor    *colors,
1938                                    gint         ncolors,
1939                                    gboolean     writeable,
1940                                    gboolean     best_match,
1941                                    gboolean    *success)
1942 {
1943   GdkColormapPrivate *private;
1944   gint i, index;
1945   XColor *store = g_new (XColor, ncolors);
1946   gint nstore = 0;
1947   gint nremaining = 0;
1948   
1949   private = (GdkColormapPrivate*) colormap;
1950   index = -1;
1951
1952   /* First, store the colors we have room for */
1953
1954   index = 0;
1955   for (i=0; i<ncolors; i++)
1956     {
1957       if (!success[i])
1958         {
1959           while ((index < colormap->size) && (private->info[index].ref_count != 0))
1960             index++;
1961
1962           if (index < colormap->size)
1963             {
1964               store[nstore].peRed = colors[i].red >> 8;
1965               store[nstore].peBlue = colors[i].blue >> 8;
1966               store[nstore].peGreen = colors[i].green >> 8;
1967               nstore++;
1968
1969               success[i] = TRUE;
1970
1971               colors[i].pixel = index;
1972               private->info[index].ref_count++;
1973             }
1974           else
1975             nremaining++;
1976         }
1977     }
1978   
1979   if (SetPaletteEntries (private->xcolormap->palette,
1980                          0, nstore, store) == 0)
1981     g_warning ("gdk_colormap_alloc_colors_private: SetPaletteEntries failed");
1982   private->xcolormap->stale = TRUE;
1983
1984   g_free (store);
1985
1986   if (nremaining > 0 && best_match)
1987     {
1988       /* Get best matches for remaining colors */
1989
1990       gchar *available = g_new (gchar, colormap->size);
1991       for (i = 0; i < colormap->size; i++)
1992         available[i] = TRUE;
1993
1994       for (i=0; i<ncolors; i++)
1995         {
1996           if (!success[i])
1997             {
1998               index = gdk_colormap_match_color (colormap, 
1999                                                 &colors[i], 
2000                                                 available);
2001               if (index != -1)
2002                 {
2003                   colors[i] = colormap->colors[index];
2004                   private->info[index].ref_count++;
2005                   success[i] = TRUE;
2006                   nremaining--;
2007                 }
2008             }
2009         }
2010       g_free (available);
2011     }
2012
2013   return (ncolors - nremaining);
2014 }
2015
2016 static gint
2017 gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
2018                                   GdkColor    *colors,
2019                                   gint         ncolors,
2020                                   gboolean     writeable,
2021                                   gboolean     best_match,
2022                                   gboolean    *success)
2023 {
2024   GdkColormapPrivate *private;
2025   gint i, index;
2026   gint nremaining = 0;
2027   gint nfailed = 0;
2028
2029   private = (GdkColormapPrivate*) colormap;
2030   index = -1;
2031
2032   for (i=0; i<ncolors; i++)
2033     {
2034       if (!success[i])
2035         {
2036           if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
2037             success[i] = TRUE;
2038           else
2039             nremaining++;
2040         }
2041     }
2042
2043
2044   if (nremaining > 0 && best_match)
2045     {
2046       gchar *available = g_new (gchar, colormap->size);
2047       for (i = 0; i < colormap->size; i++)
2048         available[i] = ((private->info[i].ref_count == 0) ||
2049                         !(private->info[i].flags && GDK_COLOR_WRITEABLE));
2050       gdk_colormap_sync (colormap, FALSE);
2051       
2052       while (nremaining > 0)
2053         {
2054           for (i=0; i<ncolors; i++)
2055             {
2056               if (!success[i])
2057                 {
2058                   index = gdk_colormap_match_color (colormap, &colors[i], available);
2059                   if (index != -1)
2060                     {
2061                       if (private->info[index].ref_count)
2062                         {
2063                           private->info[index].ref_count++;
2064                           colors[i] = colormap->colors[index];
2065                           success[i] = TRUE;
2066                           nremaining--;
2067                         }
2068                       else
2069                         {
2070                           if (gdk_colormap_alloc1 (colormap, 
2071                                                    &colormap->colors[index],
2072                                                    &colors[i]))
2073                             {
2074                               success[i] = TRUE;
2075                               nremaining--;
2076                               break;
2077                             }
2078                           else
2079                             {
2080                               available[index] = FALSE;
2081                             }
2082                         }
2083                     }
2084                   else
2085                     {
2086                       nfailed++;
2087                       nremaining--;
2088                       success[i] = 2; /* flag as permanent failure */
2089                     }
2090                 }
2091             }
2092         }
2093       g_free (available);
2094     }
2095
2096   /* Change back the values we flagged as permanent failures */
2097   if (nfailed > 0)
2098     {
2099       for (i=0; i<ncolors; i++)
2100         if (success[i] == 2)
2101           success[i] = FALSE;
2102       nremaining = nfailed;
2103     }
2104   
2105   return (ncolors - nremaining);
2106 }
2107
2108 static gint
2109 gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
2110                                        GdkColor    *colors,
2111                                        gint         ncolors,
2112                                        gboolean     writeable,
2113                                        gboolean     best_match,
2114                                        gboolean    *success)
2115 {
2116   GdkColormapPrivate *private;
2117   GdkColor *lookup_color;
2118   gint i;
2119   gint nremaining = 0;
2120
2121   private = (GdkColormapPrivate*) colormap;
2122
2123   /* Check for an exact match among previously allocated colors */
2124
2125   for (i=0; i<ncolors; i++)
2126     {
2127       if (!success[i])
2128         {
2129           lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
2130           if (lookup_color)
2131             {
2132               private->info[lookup_color->pixel].ref_count++;
2133               colors[i].pixel = lookup_color->pixel;
2134               success[i] = TRUE;
2135             }
2136           else
2137             nremaining++;
2138         }
2139     }
2140
2141   /* If that failed, we try to allocate a new color, or approxmiate
2142    * with what we can get if best_match is TRUE.
2143    */
2144   if (nremaining > 0)
2145     {
2146       if (private->private_val)
2147         return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
2148       else
2149         return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
2150     }
2151   else
2152     return 0;
2153 }
2154
2155 gint
2156 gdk_colormap_alloc_colors (GdkColormap *colormap,
2157                            GdkColor    *colors,
2158                            gint         ncolors,
2159                            gboolean     writeable,
2160                            gboolean     best_match,
2161                            gboolean    *success)
2162 {
2163   GdkColormapPrivate *private;
2164   GdkVisual *visual;
2165   gint i;
2166   gint nremaining = 0;
2167   XColor xcolor;
2168
2169   g_return_val_if_fail (colormap != NULL, FALSE);
2170   g_return_val_if_fail (colors != NULL, FALSE);
2171
2172   private = (GdkColormapPrivate*) colormap;
2173
2174   for (i=0; i<ncolors; i++)
2175     {
2176       success[i] = FALSE;
2177     }
2178
2179   switch (private->visual->type)
2180     {
2181     case GDK_VISUAL_PSEUDO_COLOR:
2182     case GDK_VISUAL_GRAYSCALE:
2183       if (writeable)
2184         return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
2185                                                     writeable, best_match, success);
2186       else
2187         return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
2188                                                     writeable, best_match, success);
2189       break;
2190
2191     case GDK_VISUAL_TRUE_COLOR:
2192       visual = private->visual;
2193
2194       for (i=0; i<ncolors; i++)
2195         {
2196           colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
2197                              ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
2198                              ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
2199           success[i] = TRUE;
2200         }
2201       break;
2202
2203     case GDK_VISUAL_STATIC_GRAY:
2204     case GDK_VISUAL_STATIC_COLOR:
2205       for (i=0; i<ncolors; i++)
2206         {
2207           xcolor.peRed = colors[i].red >> 8;
2208           xcolor.peGreen = colors[i].green >> 8;
2209           xcolor.peBlue = colors[i].blue >> 8;
2210           if (alloc_color (private->xcolormap, &xcolor, &colors[i].pixel))
2211             success[i] = TRUE;
2212           else
2213             nremaining++;
2214         }
2215       break;
2216     }
2217   return nremaining;
2218 }
2219
2220 gboolean
2221 gdk_colormap_alloc_color (GdkColormap *colormap,
2222                           GdkColor    *color,
2223                           gboolean     writeable,
2224                           gboolean     best_match)
2225 {
2226   gboolean success;
2227
2228   GDK_NOTE (MISC, g_print ("gdk_colormap_alloc_color: (%.04x,%.04x,%.04x)",
2229                            color->red, color->green, color->blue));
2230
2231   gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match,
2232                              &success);
2233   GDK_NOTE (MISC, g_print (" -> %.08x\n", color->pixel));
2234
2235   return success;
2236 }
2237
2238 /* This is almost identical to gdk_colors_free.
2239  * Keep them in sync!
2240  */
2241 void
2242 gdk_colormap_free_colors (GdkColormap *colormap,
2243                           GdkColor    *colors,
2244                           gint         ncolors)
2245 {
2246   GdkColormapPrivate *private;
2247   gulong *pixels;
2248   gint npixels = 0;
2249   gint i;
2250
2251   g_return_if_fail (colormap != NULL);
2252   g_return_if_fail (colors != NULL);
2253
2254   private = (GdkColormapPrivate*) colormap;
2255
2256   if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
2257       (private->visual->type != GDK_VISUAL_GRAYSCALE))
2258     return;
2259
2260   pixels = g_new (gulong, ncolors);
2261
2262   for (i=0; i<ncolors; i++)
2263     {
2264       gulong pixel = colors[i].pixel;
2265       
2266       if (private->info[pixel].ref_count)
2267         {
2268           private->info[pixel].ref_count--;
2269
2270           if (private->info[pixel].ref_count == 0)
2271             {
2272               pixels[npixels++] = pixel;
2273               if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
2274                 g_hash_table_remove (private->hash, &colors[i]);
2275               private->info[pixel].flags = 0;
2276             }
2277         }
2278     }
2279   if (npixels)
2280     XFreeColors (private->xcolormap, pixels, npixels, 0);
2281   g_free (pixels);
2282 }
2283
2284 gboolean
2285 gdk_color_alloc (GdkColormap *colormap,
2286                  GdkColor    *color)
2287 {
2288   gboolean success;
2289
2290   GDK_NOTE (MISC, g_print ("gdk_color_alloc: (%.04x,%.04x,%.04x)",
2291                            color->red, color->green, color->blue));
2292
2293   gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success);
2294
2295   GDK_NOTE (MISC, g_print (" -> %.08x\n", color->pixel));
2296
2297   return success;
2298 }
2299
2300 gboolean
2301 gdk_color_change (GdkColormap *colormap,
2302                   GdkColor    *color)
2303 {
2304   GdkColormapPrivate *private;
2305   XColor xcolor;
2306
2307   g_return_val_if_fail (colormap != NULL, FALSE);
2308   g_return_val_if_fail (color != NULL, FALSE);
2309
2310   private = (GdkColormapPrivate*) colormap;
2311
2312   xcolor.peRed = color->red >> 8;
2313   xcolor.peGreen = color->green >> 8;
2314   xcolor.peBlue = color->blue >> 8;
2315
2316   if (SetPaletteEntries (private->xcolormap->palette,
2317                          color->pixel, 1, &xcolor) == 0)
2318     g_warning ("gdk_color_change: SetPaletteEntries failed");
2319   private->xcolormap->stale = TRUE;
2320
2321   return TRUE;
2322 }
2323
2324 guint
2325 gdk_color_hash (const GdkColor *colora)
2326 {
2327   return ((colora->red) +
2328           (colora->green << 11) +
2329           (colora->blue << 22) +
2330           (colora->blue >> 6));
2331 }
2332
2333 gint
2334 gdk_color_equal (const GdkColor *colora,
2335                  const GdkColor *colorb)
2336 {
2337   g_return_val_if_fail (colora != NULL, FALSE);
2338   g_return_val_if_fail (colorb != NULL, FALSE);
2339
2340   return ((colora->red == colorb->red) &&
2341           (colora->green == colorb->green) &&
2342           (colora->blue == colorb->blue));
2343 }
2344
2345 static gint
2346 gdk_colormap_match_color (GdkColormap *cmap,
2347                           GdkColor    *color,
2348                           const gchar *available)
2349 {
2350   GdkColor *colors;
2351   guint sum, max;
2352   gint rdiff, gdiff, bdiff;
2353   gint i, index;
2354
2355   g_return_val_if_fail (cmap != NULL, 0);
2356   g_return_val_if_fail (color != NULL, 0);
2357
2358   colors = cmap->colors;
2359   max = 3 * (65536);
2360   index = -1;
2361
2362   for (i = 0; i < cmap->size; i++)
2363     {
2364       if ((!available) || (available && available[i]))
2365         {
2366           rdiff = (color->red - colors[i].red);
2367           gdiff = (color->green - colors[i].green);
2368           bdiff = (color->blue - colors[i].blue);
2369
2370           sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
2371
2372           if (sum < max)
2373             {
2374               index = i;
2375               max = sum;
2376             }
2377         }
2378     }
2379
2380   return index;
2381 }
2382
2383 GdkColormap*
2384 gdk_colormap_lookup (Colormap xcolormap)
2385 {
2386   GdkColormap *cmap;
2387
2388   if (!colormap_hash)
2389     return NULL;
2390
2391   cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
2392   return cmap;
2393 }
2394
2395 static void
2396 gdk_colormap_add (GdkColormap *cmap)
2397 {
2398   GdkColormapPrivate *private;
2399
2400   if (!colormap_hash)
2401     colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
2402                                       (GCompareFunc) gdk_colormap_cmp);
2403
2404   private = (GdkColormapPrivate*) cmap;
2405
2406   g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
2407 }
2408
2409 static void
2410 gdk_colormap_remove (GdkColormap *cmap)
2411 {
2412   GdkColormapPrivate *private;
2413
2414   if (!colormap_hash)
2415     colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
2416                                       (GCompareFunc) gdk_colormap_cmp);
2417
2418   private = (GdkColormapPrivate*) cmap;
2419
2420   g_hash_table_remove (colormap_hash, &private->xcolormap);
2421 }
2422
2423 static guint
2424 gdk_colormap_hash (Colormap *cmap)
2425 {
2426   return (guint) *cmap;
2427 }
2428
2429 static gint
2430 gdk_colormap_cmp (Colormap *a,
2431                   Colormap *b)
2432 {
2433   return (*a == *b);
2434 }
2435
2436 char *
2437 gdk_color_to_string (GdkColor *color)
2438 {
2439   static char buf[100];
2440
2441   sprintf (buf, "(%.04x,%.04x,%.04x): %.06x",
2442            color->red, color->green, color->blue, color->pixel);
2443
2444   return buf;
2445 }