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