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