xref: /openbsd/usr.bin/tmux/colour.c (revision c7510e3d)
1 /* $OpenBSD: colour.c,v 1.28 2024/09/29 20:05:42 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
5  * Copyright (c) 2016 Avi Halachmi <avihpit@yahoo.com>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 
27 #include "tmux.h"
28 
29 static int
colour_dist_sq(int R,int G,int B,int r,int g,int b)30 colour_dist_sq(int R, int G, int B, int r, int g, int b)
31 {
32 	return ((R - r) * (R - r) + (G - g) * (G - g) + (B - b) * (B - b));
33 }
34 
35 static int
colour_to_6cube(int v)36 colour_to_6cube(int v)
37 {
38 	if (v < 48)
39 		return (0);
40 	if (v < 114)
41 		return (1);
42 	return ((v - 35) / 40);
43 }
44 
45 /*
46  * Convert an RGB triplet to the xterm(1) 256 colour palette.
47  *
48  * xterm provides a 6x6x6 colour cube (16 - 231) and 24 greys (232 - 255). We
49  * map our RGB colour to the closest in the cube, also work out the closest
50  * grey, and use the nearest of the two.
51  *
52  * Note that the xterm has much lower resolution for darker colours (they are
53  * not evenly spread out), so our 6 levels are not evenly spread: 0x0, 0x5f
54  * (95), 0x87 (135), 0xaf (175), 0xd7 (215) and 0xff (255). Greys are more
55  * evenly spread (8, 18, 28 ... 238).
56  */
57 int
colour_find_rgb(u_char r,u_char g,u_char b)58 colour_find_rgb(u_char r, u_char g, u_char b)
59 {
60 	static const int	q2c[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
61 	int			qr, qg, qb, cr, cg, cb, d, idx;
62 	int			grey_avg, grey_idx, grey;
63 
64 	/* Map RGB to 6x6x6 cube. */
65 	qr = colour_to_6cube(r); cr = q2c[qr];
66 	qg = colour_to_6cube(g); cg = q2c[qg];
67 	qb = colour_to_6cube(b); cb = q2c[qb];
68 
69 	/* If we have hit the colour exactly, return early. */
70 	if (cr == r && cg == g && cb == b)
71 		return ((16 + (36 * qr) + (6 * qg) + qb) | COLOUR_FLAG_256);
72 
73 	/* Work out the closest grey (average of RGB). */
74 	grey_avg = (r + g + b) / 3;
75 	if (grey_avg > 238)
76 		grey_idx = 23;
77 	else
78 		grey_idx = (grey_avg - 3) / 10;
79 	grey = 8 + (10 * grey_idx);
80 
81 	/* Is grey or 6x6x6 colour closest? */
82 	d = colour_dist_sq(cr, cg, cb, r, g, b);
83 	if (colour_dist_sq(grey, grey, grey, r, g, b) < d)
84 		idx = 232 + grey_idx;
85 	else
86 		idx = 16 + (36 * qr) + (6 * qg) + qb;
87 	return (idx | COLOUR_FLAG_256);
88 }
89 
90 /* Join RGB into a colour. */
91 int
colour_join_rgb(u_char r,u_char g,u_char b)92 colour_join_rgb(u_char r, u_char g, u_char b)
93 {
94 	return ((((int)((r) & 0xff)) << 16) |
95 	    (((int)((g) & 0xff)) << 8) |
96 	    (((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
97 }
98 
99 /* Split colour into RGB. */
100 void
colour_split_rgb(int c,u_char * r,u_char * g,u_char * b)101 colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
102 {
103 	*r = (c >> 16) & 0xff;
104 	*g = (c >> 8) & 0xff;
105 	*b = c & 0xff;
106 }
107 
108 /* Force colour to RGB if not already. */
109 int
colour_force_rgb(int c)110 colour_force_rgb(int c)
111 {
112 	if (c & COLOUR_FLAG_RGB)
113 		return (c);
114 	if (c & COLOUR_FLAG_256)
115 		return (colour_256toRGB(c));
116 	if (c >= 0 && c <= 7)
117 		return (colour_256toRGB(c));
118 	if (c >= 90 && c <= 97)
119 		return (colour_256toRGB(8 + c - 90));
120 	return (-1);
121 }
122 
123 /* Convert colour to a string. */
124 const char *
colour_tostring(int c)125 colour_tostring(int c)
126 {
127 	static char	s[32];
128 	u_char		r, g, b;
129 
130 	if (c == -1)
131 		return ("none");
132 
133 	if (c & COLOUR_FLAG_RGB) {
134 		colour_split_rgb(c, &r, &g, &b);
135 		xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
136 		return (s);
137 	}
138 
139 	if (c & COLOUR_FLAG_256) {
140 		xsnprintf(s, sizeof s, "colour%u", c & 0xff);
141 		return (s);
142 	}
143 
144 	switch (c) {
145 	case 0:
146 		return ("black");
147 	case 1:
148 		return ("red");
149 	case 2:
150 		return ("green");
151 	case 3:
152 		return ("yellow");
153 	case 4:
154 		return ("blue");
155 	case 5:
156 		return ("magenta");
157 	case 6:
158 		return ("cyan");
159 	case 7:
160 		return ("white");
161 	case 8:
162 		return ("default");
163 	case 9:
164 		return ("terminal");
165 	case 90:
166 		return ("brightblack");
167 	case 91:
168 		return ("brightred");
169 	case 92:
170 		return ("brightgreen");
171 	case 93:
172 		return ("brightyellow");
173 	case 94:
174 		return ("brightblue");
175 	case 95:
176 		return ("brightmagenta");
177 	case 96:
178 		return ("brightcyan");
179 	case 97:
180 		return ("brightwhite");
181 	}
182 	return ("invalid");
183 }
184 
185 /* Convert colour from string. */
186 int
colour_fromstring(const char * s)187 colour_fromstring(const char *s)
188 {
189 	const char	*errstr;
190 	const char	*cp;
191 	int		 n;
192 	u_char		 r, g, b;
193 
194 	if (*s == '#' && strlen(s) == 7) {
195 		for (cp = s + 1; isxdigit((u_char) *cp); cp++)
196 			;
197 		if (*cp != '\0')
198 			return (-1);
199 		n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
200 		if (n != 3)
201 			return (-1);
202 		return (colour_join_rgb(r, g, b));
203 	}
204 
205 	if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
206 		n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
207 		if (errstr != NULL)
208 			return (-1);
209 		return (n | COLOUR_FLAG_256);
210 	}
211 	if (strncasecmp(s, "color", (sizeof "color") - 1) == 0) {
212 		n = strtonum(s + (sizeof "color") - 1, 0, 255, &errstr);
213 		if (errstr != NULL)
214 			return (-1);
215 		return (n | COLOUR_FLAG_256);
216 	}
217 
218 	if (strcasecmp(s, "default") == 0)
219 		return (8);
220 	if (strcasecmp(s, "terminal") == 0)
221 		return (9);
222 
223 	if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
224 		return (0);
225 	if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
226 		return (1);
227 	if (strcasecmp(s, "green") == 0 || strcmp(s, "2") == 0)
228 		return (2);
229 	if (strcasecmp(s, "yellow") == 0 || strcmp(s, "3") == 0)
230 		return (3);
231 	if (strcasecmp(s, "blue") == 0 || strcmp(s, "4") == 0)
232 		return (4);
233 	if (strcasecmp(s, "magenta") == 0 || strcmp(s, "5") == 0)
234 		return (5);
235 	if (strcasecmp(s, "cyan") == 0 || strcmp(s, "6") == 0)
236 		return (6);
237 	if (strcasecmp(s, "white") == 0 || strcmp(s, "7") == 0)
238 		return (7);
239 	if (strcasecmp(s, "brightblack") == 0 || strcmp(s, "90") == 0)
240 		return (90);
241 	if (strcasecmp(s, "brightred") == 0 || strcmp(s, "91") == 0)
242 		return (91);
243 	if (strcasecmp(s, "brightgreen") == 0 || strcmp(s, "92") == 0)
244 		return (92);
245 	if (strcasecmp(s, "brightyellow") == 0 || strcmp(s, "93") == 0)
246 		return (93);
247 	if (strcasecmp(s, "brightblue") == 0 || strcmp(s, "94") == 0)
248 		return (94);
249 	if (strcasecmp(s, "brightmagenta") == 0 || strcmp(s, "95") == 0)
250 		return (95);
251 	if (strcasecmp(s, "brightcyan") == 0 || strcmp(s, "96") == 0)
252 		return (96);
253 	if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
254 		return (97);
255 	return (colour_byname(s));
256 }
257 
258 /* Convert 256 colour to RGB colour. */
259 int
colour_256toRGB(int c)260 colour_256toRGB(int c)
261 {
262 	static const int table[256] = {
263 		0x000000, 0x800000, 0x008000, 0x808000,
264 		0x000080, 0x800080, 0x008080, 0xc0c0c0,
265 		0x808080, 0xff0000, 0x00ff00, 0xffff00,
266 		0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
267 		0x000000, 0x00005f, 0x000087, 0x0000af,
268 		0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
269 		0x005f87, 0x005faf, 0x005fd7, 0x005fff,
270 		0x008700, 0x00875f, 0x008787, 0x0087af,
271 		0x0087d7, 0x0087ff, 0x00af00, 0x00af5f,
272 		0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
273 		0x00d700, 0x00d75f, 0x00d787, 0x00d7af,
274 		0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
275 		0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff,
276 		0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
277 		0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f,
278 		0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
279 		0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af,
280 		0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
281 		0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff,
282 		0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
283 		0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f,
284 		0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
285 		0x870000, 0x87005f, 0x870087, 0x8700af,
286 		0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
287 		0x875f87, 0x875faf, 0x875fd7, 0x875fff,
288 		0x878700, 0x87875f, 0x878787, 0x8787af,
289 		0x8787d7, 0x8787ff, 0x87af00, 0x87af5f,
290 		0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
291 		0x87d700, 0x87d75f, 0x87d787, 0x87d7af,
292 		0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
293 		0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff,
294 		0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
295 		0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f,
296 		0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
297 		0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af,
298 		0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
299 		0xafaf87, 0xafafaf, 0xafafd7, 0xafafff,
300 		0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
301 		0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f,
302 		0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
303 		0xd70000, 0xd7005f, 0xd70087, 0xd700af,
304 		0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
305 		0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff,
306 		0xd78700, 0xd7875f, 0xd78787, 0xd787af,
307 		0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f,
308 		0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
309 		0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af,
310 		0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
311 		0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff,
312 		0xff0000, 0xff005f, 0xff0087, 0xff00af,
313 		0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f,
314 		0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
315 		0xff8700, 0xff875f, 0xff8787, 0xff87af,
316 		0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
317 		0xffaf87, 0xffafaf, 0xffafd7, 0xffafff,
318 		0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
319 		0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f,
320 		0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
321 		0x080808, 0x121212, 0x1c1c1c, 0x262626,
322 		0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
323 		0x585858, 0x626262, 0x6c6c6c, 0x767676,
324 		0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
325 		0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6,
326 		0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
327 	};
328 
329 	return (table[c & 0xff] | COLOUR_FLAG_RGB);
330 }
331 
332 /* Convert 256 colour to 16 colour. */
333 int
colour_256to16(int c)334 colour_256to16(int c)
335 {
336 	static const char table[256] = {
337 		 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
338 		 0,  4,  4,  4, 12, 12,  2,  6,  4,  4, 12, 12,  2,  2,  6,  4,
339 		12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
340 		10, 10, 10, 14,  1,  5,  4,  4, 12, 12,  3,  8,  4,  4, 12, 12,
341 		 2,  2,  6,  4, 12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10,
342 		14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  5,  4, 12, 12,  1,  1,
343 		 5,  4, 12, 12,  3,  3,  8,  4, 12, 12,  2,  2,  2,  6, 12, 12,
344 		10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  1,  5,
345 		12, 12,  1,  1,  1,  5, 12, 12,  1,  1,  1,  5, 12, 12,  3,  3,
346 		 3,  7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
347 		 9,  9,  9,  9, 13, 12,  9,  9,  9,  9, 13, 12,  9,  9,  9,  9,
348 		13, 12,  9,  9,  9,  9, 13, 12, 11, 11, 11, 11,  7, 12, 10, 10,
349 		10, 10, 10, 14,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,
350 		 9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,
351 		 9, 13, 11, 11, 11, 11, 11, 15,  0,  0,  0,  0,  0,  0,  8,  8,
352 		 8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15
353 	};
354 
355 	return (table[c & 0xff]);
356 }
357 
358 /* Get colour by X11 colour name. */
359 int
colour_byname(const char * name)360 colour_byname(const char *name)
361 {
362 	static const struct {
363 		const char	*name;
364 		int		 c;
365 	} colours[] = {
366 		{ "AliceBlue", 0xf0f8ff },
367 		{ "AntiqueWhite", 0xfaebd7 },
368 		{ "AntiqueWhite1", 0xffefdb },
369 		{ "AntiqueWhite2", 0xeedfcc },
370 		{ "AntiqueWhite3", 0xcdc0b0 },
371 		{ "AntiqueWhite4", 0x8b8378 },
372 		{ "BlanchedAlmond", 0xffebcd },
373 		{ "BlueViolet", 0x8a2be2 },
374 		{ "CadetBlue", 0x5f9ea0 },
375 		{ "CadetBlue1", 0x98f5ff },
376 		{ "CadetBlue2", 0x8ee5ee },
377 		{ "CadetBlue3", 0x7ac5cd },
378 		{ "CadetBlue4", 0x53868b },
379 		{ "CornflowerBlue", 0x6495ed },
380 		{ "DarkBlue", 0x00008b },
381 		{ "DarkCyan", 0x008b8b },
382 		{ "DarkGoldenrod", 0xb8860b },
383 		{ "DarkGoldenrod1", 0xffb90f },
384 		{ "DarkGoldenrod2", 0xeead0e },
385 		{ "DarkGoldenrod3", 0xcd950c },
386 		{ "DarkGoldenrod4", 0x8b6508 },
387 		{ "DarkGray", 0xa9a9a9 },
388 		{ "DarkGreen", 0x006400 },
389 		{ "DarkGrey", 0xa9a9a9 },
390 		{ "DarkKhaki", 0xbdb76b },
391 		{ "DarkMagenta", 0x8b008b },
392 		{ "DarkOliveGreen", 0x556b2f },
393 		{ "DarkOliveGreen1", 0xcaff70 },
394 		{ "DarkOliveGreen2", 0xbcee68 },
395 		{ "DarkOliveGreen3", 0xa2cd5a },
396 		{ "DarkOliveGreen4", 0x6e8b3d },
397 		{ "DarkOrange", 0xff8c00 },
398 		{ "DarkOrange1", 0xff7f00 },
399 		{ "DarkOrange2", 0xee7600 },
400 		{ "DarkOrange3", 0xcd6600 },
401 		{ "DarkOrange4", 0x8b4500 },
402 		{ "DarkOrchid", 0x9932cc },
403 		{ "DarkOrchid1", 0xbf3eff },
404 		{ "DarkOrchid2", 0xb23aee },
405 		{ "DarkOrchid3", 0x9a32cd },
406 		{ "DarkOrchid4", 0x68228b },
407 		{ "DarkRed", 0x8b0000 },
408 		{ "DarkSalmon", 0xe9967a },
409 		{ "DarkSeaGreen", 0x8fbc8f },
410 		{ "DarkSeaGreen1", 0xc1ffc1 },
411 		{ "DarkSeaGreen2", 0xb4eeb4 },
412 		{ "DarkSeaGreen3", 0x9bcd9b },
413 		{ "DarkSeaGreen4", 0x698b69 },
414 		{ "DarkSlateBlue", 0x483d8b },
415 		{ "DarkSlateGray", 0x2f4f4f },
416 		{ "DarkSlateGray1", 0x97ffff },
417 		{ "DarkSlateGray2", 0x8deeee },
418 		{ "DarkSlateGray3", 0x79cdcd },
419 		{ "DarkSlateGray4", 0x528b8b },
420 		{ "DarkSlateGrey", 0x2f4f4f },
421 		{ "DarkTurquoise", 0x00ced1 },
422 		{ "DarkViolet", 0x9400d3 },
423 		{ "DeepPink", 0xff1493 },
424 		{ "DeepPink1", 0xff1493 },
425 		{ "DeepPink2", 0xee1289 },
426 		{ "DeepPink3", 0xcd1076 },
427 		{ "DeepPink4", 0x8b0a50 },
428 		{ "DeepSkyBlue", 0x00bfff },
429 		{ "DeepSkyBlue1", 0x00bfff },
430 		{ "DeepSkyBlue2", 0x00b2ee },
431 		{ "DeepSkyBlue3", 0x009acd },
432 		{ "DeepSkyBlue4", 0x00688b },
433 		{ "DimGray", 0x696969 },
434 		{ "DimGrey", 0x696969 },
435 		{ "DodgerBlue", 0x1e90ff },
436 		{ "DodgerBlue1", 0x1e90ff },
437 		{ "DodgerBlue2", 0x1c86ee },
438 		{ "DodgerBlue3", 0x1874cd },
439 		{ "DodgerBlue4", 0x104e8b },
440 		{ "FloralWhite", 0xfffaf0 },
441 		{ "ForestGreen", 0x228b22 },
442 		{ "GhostWhite", 0xf8f8ff },
443 		{ "GreenYellow", 0xadff2f },
444 		{ "HotPink", 0xff69b4 },
445 		{ "HotPink1", 0xff6eb4 },
446 		{ "HotPink2", 0xee6aa7 },
447 		{ "HotPink3", 0xcd6090 },
448 		{ "HotPink4", 0x8b3a62 },
449 		{ "IndianRed", 0xcd5c5c },
450 		{ "IndianRed1", 0xff6a6a },
451 		{ "IndianRed2", 0xee6363 },
452 		{ "IndianRed3", 0xcd5555 },
453 		{ "IndianRed4", 0x8b3a3a },
454 		{ "LavenderBlush", 0xfff0f5 },
455 		{ "LavenderBlush1", 0xfff0f5 },
456 		{ "LavenderBlush2", 0xeee0e5 },
457 		{ "LavenderBlush3", 0xcdc1c5 },
458 		{ "LavenderBlush4", 0x8b8386 },
459 		{ "LawnGreen", 0x7cfc00 },
460 		{ "LemonChiffon", 0xfffacd },
461 		{ "LemonChiffon1", 0xfffacd },
462 		{ "LemonChiffon2", 0xeee9bf },
463 		{ "LemonChiffon3", 0xcdc9a5 },
464 		{ "LemonChiffon4", 0x8b8970 },
465 		{ "LightBlue", 0xadd8e6 },
466 		{ "LightBlue1", 0xbfefff },
467 		{ "LightBlue2", 0xb2dfee },
468 		{ "LightBlue3", 0x9ac0cd },
469 		{ "LightBlue4", 0x68838b },
470 		{ "LightCoral", 0xf08080 },
471 		{ "LightCyan", 0xe0ffff },
472 		{ "LightCyan1", 0xe0ffff },
473 		{ "LightCyan2", 0xd1eeee },
474 		{ "LightCyan3", 0xb4cdcd },
475 		{ "LightCyan4", 0x7a8b8b },
476 		{ "LightGoldenrod", 0xeedd82 },
477 		{ "LightGoldenrod1", 0xffec8b },
478 		{ "LightGoldenrod2", 0xeedc82 },
479 		{ "LightGoldenrod3", 0xcdbe70 },
480 		{ "LightGoldenrod4", 0x8b814c },
481 		{ "LightGoldenrodYellow", 0xfafad2 },
482 		{ "LightGray", 0xd3d3d3 },
483 		{ "LightGreen", 0x90ee90 },
484 		{ "LightGrey", 0xd3d3d3 },
485 		{ "LightPink", 0xffb6c1 },
486 		{ "LightPink1", 0xffaeb9 },
487 		{ "LightPink2", 0xeea2ad },
488 		{ "LightPink3", 0xcd8c95 },
489 		{ "LightPink4", 0x8b5f65 },
490 		{ "LightSalmon", 0xffa07a },
491 		{ "LightSalmon1", 0xffa07a },
492 		{ "LightSalmon2", 0xee9572 },
493 		{ "LightSalmon3", 0xcd8162 },
494 		{ "LightSalmon4", 0x8b5742 },
495 		{ "LightSeaGreen", 0x20b2aa },
496 		{ "LightSkyBlue", 0x87cefa },
497 		{ "LightSkyBlue1", 0xb0e2ff },
498 		{ "LightSkyBlue2", 0xa4d3ee },
499 		{ "LightSkyBlue3", 0x8db6cd },
500 		{ "LightSkyBlue4", 0x607b8b },
501 		{ "LightSlateBlue", 0x8470ff },
502 		{ "LightSlateGray", 0x778899 },
503 		{ "LightSlateGrey", 0x778899 },
504 		{ "LightSteelBlue", 0xb0c4de },
505 		{ "LightSteelBlue1", 0xcae1ff },
506 		{ "LightSteelBlue2", 0xbcd2ee },
507 		{ "LightSteelBlue3", 0xa2b5cd },
508 		{ "LightSteelBlue4", 0x6e7b8b },
509 		{ "LightYellow", 0xffffe0 },
510 		{ "LightYellow1", 0xffffe0 },
511 		{ "LightYellow2", 0xeeeed1 },
512 		{ "LightYellow3", 0xcdcdb4 },
513 		{ "LightYellow4", 0x8b8b7a },
514 		{ "LimeGreen", 0x32cd32 },
515 		{ "MediumAquamarine", 0x66cdaa },
516 		{ "MediumBlue", 0x0000cd },
517 		{ "MediumOrchid", 0xba55d3 },
518 		{ "MediumOrchid1", 0xe066ff },
519 		{ "MediumOrchid2", 0xd15fee },
520 		{ "MediumOrchid3", 0xb452cd },
521 		{ "MediumOrchid4", 0x7a378b },
522 		{ "MediumPurple", 0x9370db },
523 		{ "MediumPurple1", 0xab82ff },
524 		{ "MediumPurple2", 0x9f79ee },
525 		{ "MediumPurple3", 0x8968cd },
526 		{ "MediumPurple4", 0x5d478b },
527 		{ "MediumSeaGreen", 0x3cb371 },
528 		{ "MediumSlateBlue", 0x7b68ee },
529 		{ "MediumSpringGreen", 0x00fa9a },
530 		{ "MediumTurquoise", 0x48d1cc },
531 		{ "MediumVioletRed", 0xc71585 },
532 		{ "MidnightBlue", 0x191970 },
533 		{ "MintCream", 0xf5fffa },
534 		{ "MistyRose", 0xffe4e1 },
535 		{ "MistyRose1", 0xffe4e1 },
536 		{ "MistyRose2", 0xeed5d2 },
537 		{ "MistyRose3", 0xcdb7b5 },
538 		{ "MistyRose4", 0x8b7d7b },
539 		{ "NavajoWhite", 0xffdead },
540 		{ "NavajoWhite1", 0xffdead },
541 		{ "NavajoWhite2", 0xeecfa1 },
542 		{ "NavajoWhite3", 0xcdb38b },
543 		{ "NavajoWhite4", 0x8b795e },
544 		{ "NavyBlue", 0x000080 },
545 		{ "OldLace", 0xfdf5e6 },
546 		{ "OliveDrab", 0x6b8e23 },
547 		{ "OliveDrab1", 0xc0ff3e },
548 		{ "OliveDrab2", 0xb3ee3a },
549 		{ "OliveDrab3", 0x9acd32 },
550 		{ "OliveDrab4", 0x698b22 },
551 		{ "OrangeRed", 0xff4500 },
552 		{ "OrangeRed1", 0xff4500 },
553 		{ "OrangeRed2", 0xee4000 },
554 		{ "OrangeRed3", 0xcd3700 },
555 		{ "OrangeRed4", 0x8b2500 },
556 		{ "PaleGoldenrod", 0xeee8aa },
557 		{ "PaleGreen", 0x98fb98 },
558 		{ "PaleGreen1", 0x9aff9a },
559 		{ "PaleGreen2", 0x90ee90 },
560 		{ "PaleGreen3", 0x7ccd7c },
561 		{ "PaleGreen4", 0x548b54 },
562 		{ "PaleTurquoise", 0xafeeee },
563 		{ "PaleTurquoise1", 0xbbffff },
564 		{ "PaleTurquoise2", 0xaeeeee },
565 		{ "PaleTurquoise3", 0x96cdcd },
566 		{ "PaleTurquoise4", 0x668b8b },
567 		{ "PaleVioletRed", 0xdb7093 },
568 		{ "PaleVioletRed1", 0xff82ab },
569 		{ "PaleVioletRed2", 0xee799f },
570 		{ "PaleVioletRed3", 0xcd6889 },
571 		{ "PaleVioletRed4", 0x8b475d },
572 		{ "PapayaWhip", 0xffefd5 },
573 		{ "PeachPuff", 0xffdab9 },
574 		{ "PeachPuff1", 0xffdab9 },
575 		{ "PeachPuff2", 0xeecbad },
576 		{ "PeachPuff3", 0xcdaf95 },
577 		{ "PeachPuff4", 0x8b7765 },
578 		{ "PowderBlue", 0xb0e0e6 },
579 		{ "RebeccaPurple", 0x663399 },
580 		{ "RosyBrown", 0xbc8f8f },
581 		{ "RosyBrown1", 0xffc1c1 },
582 		{ "RosyBrown2", 0xeeb4b4 },
583 		{ "RosyBrown3", 0xcd9b9b },
584 		{ "RosyBrown4", 0x8b6969 },
585 		{ "RoyalBlue", 0x4169e1 },
586 		{ "RoyalBlue1", 0x4876ff },
587 		{ "RoyalBlue2", 0x436eee },
588 		{ "RoyalBlue3", 0x3a5fcd },
589 		{ "RoyalBlue4", 0x27408b },
590 		{ "SaddleBrown", 0x8b4513 },
591 		{ "SandyBrown", 0xf4a460 },
592 		{ "SeaGreen", 0x2e8b57 },
593 		{ "SeaGreen1", 0x54ff9f },
594 		{ "SeaGreen2", 0x4eee94 },
595 		{ "SeaGreen3", 0x43cd80 },
596 		{ "SeaGreen4", 0x2e8b57 },
597 		{ "SkyBlue", 0x87ceeb },
598 		{ "SkyBlue1", 0x87ceff },
599 		{ "SkyBlue2", 0x7ec0ee },
600 		{ "SkyBlue3", 0x6ca6cd },
601 		{ "SkyBlue4", 0x4a708b },
602 		{ "SlateBlue", 0x6a5acd },
603 		{ "SlateBlue1", 0x836fff },
604 		{ "SlateBlue2", 0x7a67ee },
605 		{ "SlateBlue3", 0x6959cd },
606 		{ "SlateBlue4", 0x473c8b },
607 		{ "SlateGray", 0x708090 },
608 		{ "SlateGray1", 0xc6e2ff },
609 		{ "SlateGray2", 0xb9d3ee },
610 		{ "SlateGray3", 0x9fb6cd },
611 		{ "SlateGray4", 0x6c7b8b },
612 		{ "SlateGrey", 0x708090 },
613 		{ "SpringGreen", 0x00ff7f },
614 		{ "SpringGreen1", 0x00ff7f },
615 		{ "SpringGreen2", 0x00ee76 },
616 		{ "SpringGreen3", 0x00cd66 },
617 		{ "SpringGreen4", 0x008b45 },
618 		{ "SteelBlue", 0x4682b4 },
619 		{ "SteelBlue1", 0x63b8ff },
620 		{ "SteelBlue2", 0x5cacee },
621 		{ "SteelBlue3", 0x4f94cd },
622 		{ "SteelBlue4", 0x36648b },
623 		{ "VioletRed", 0xd02090 },
624 		{ "VioletRed1", 0xff3e96 },
625 		{ "VioletRed2", 0xee3a8c },
626 		{ "VioletRed3", 0xcd3278 },
627 		{ "VioletRed4", 0x8b2252 },
628 		{ "WebGray", 0x808080 },
629 		{ "WebGreen", 0x008000 },
630 		{ "WebGrey", 0x808080 },
631 		{ "WebMaroon", 0x800000 },
632 		{ "WebPurple", 0x800080 },
633 		{ "WhiteSmoke", 0xf5f5f5 },
634 		{ "X11Gray", 0xbebebe },
635 		{ "X11Green", 0x00ff00 },
636 		{ "X11Grey", 0xbebebe },
637 		{ "X11Maroon", 0xb03060 },
638 		{ "X11Purple", 0xa020f0 },
639 		{ "YellowGreen", 0x9acd32 },
640 		{ "alice blue", 0xf0f8ff },
641 		{ "antique white", 0xfaebd7 },
642 		{ "aqua", 0x00ffff },
643 		{ "aquamarine", 0x7fffd4 },
644 		{ "aquamarine1", 0x7fffd4 },
645 		{ "aquamarine2", 0x76eec6 },
646 		{ "aquamarine3", 0x66cdaa },
647 		{ "aquamarine4", 0x458b74 },
648 		{ "azure", 0xf0ffff },
649 		{ "azure1", 0xf0ffff },
650 		{ "azure2", 0xe0eeee },
651 		{ "azure3", 0xc1cdcd },
652 		{ "azure4", 0x838b8b },
653 		{ "beige", 0xf5f5dc },
654 		{ "bisque", 0xffe4c4 },
655 		{ "bisque1", 0xffe4c4 },
656 		{ "bisque2", 0xeed5b7 },
657 		{ "bisque3", 0xcdb79e },
658 		{ "bisque4", 0x8b7d6b },
659 		{ "black", 0x000000 },
660 		{ "blanched almond", 0xffebcd },
661 		{ "blue violet", 0x8a2be2 },
662 		{ "blue", 0x0000ff },
663 		{ "blue1", 0x0000ff },
664 		{ "blue2", 0x0000ee },
665 		{ "blue3", 0x0000cd },
666 		{ "blue4", 0x00008b },
667 		{ "brown", 0xa52a2a },
668 		{ "brown1", 0xff4040 },
669 		{ "brown2", 0xee3b3b },
670 		{ "brown3", 0xcd3333 },
671 		{ "brown4", 0x8b2323 },
672 		{ "burlywood", 0xdeb887 },
673 		{ "burlywood1", 0xffd39b },
674 		{ "burlywood2", 0xeec591 },
675 		{ "burlywood3", 0xcdaa7d },
676 		{ "burlywood4", 0x8b7355 },
677 		{ "cadet blue", 0x5f9ea0 },
678 		{ "chartreuse", 0x7fff00 },
679 		{ "chartreuse1", 0x7fff00 },
680 		{ "chartreuse2", 0x76ee00 },
681 		{ "chartreuse3", 0x66cd00 },
682 		{ "chartreuse4", 0x458b00 },
683 		{ "chocolate", 0xd2691e },
684 		{ "chocolate1", 0xff7f24 },
685 		{ "chocolate2", 0xee7621 },
686 		{ "chocolate3", 0xcd661d },
687 		{ "chocolate4", 0x8b4513 },
688 		{ "coral", 0xff7f50 },
689 		{ "coral1", 0xff7256 },
690 		{ "coral2", 0xee6a50 },
691 		{ "coral3", 0xcd5b45 },
692 		{ "coral4", 0x8b3e2f },
693 		{ "cornflower blue", 0x6495ed },
694 		{ "cornsilk", 0xfff8dc },
695 		{ "cornsilk1", 0xfff8dc },
696 		{ "cornsilk2", 0xeee8cd },
697 		{ "cornsilk3", 0xcdc8b1 },
698 		{ "cornsilk4", 0x8b8878 },
699 		{ "crimson", 0xdc143c },
700 		{ "cyan", 0x00ffff },
701 		{ "cyan1", 0x00ffff },
702 		{ "cyan2", 0x00eeee },
703 		{ "cyan3", 0x00cdcd },
704 		{ "cyan4", 0x008b8b },
705 		{ "dark blue", 0x00008b },
706 		{ "dark cyan", 0x008b8b },
707 		{ "dark goldenrod", 0xb8860b },
708 		{ "dark gray", 0xa9a9a9 },
709 		{ "dark green", 0x006400 },
710 		{ "dark grey", 0xa9a9a9 },
711 		{ "dark khaki", 0xbdb76b },
712 		{ "dark magenta", 0x8b008b },
713 		{ "dark olive green", 0x556b2f },
714 		{ "dark orange", 0xff8c00 },
715 		{ "dark orchid", 0x9932cc },
716 		{ "dark red", 0x8b0000 },
717 		{ "dark salmon", 0xe9967a },
718 		{ "dark sea green", 0x8fbc8f },
719 		{ "dark slate blue", 0x483d8b },
720 		{ "dark slate gray", 0x2f4f4f },
721 		{ "dark slate grey", 0x2f4f4f },
722 		{ "dark turquoise", 0x00ced1 },
723 		{ "dark violet", 0x9400d3 },
724 		{ "deep pink", 0xff1493 },
725 		{ "deep sky blue", 0x00bfff },
726 		{ "dim gray", 0x696969 },
727 		{ "dim grey", 0x696969 },
728 		{ "dodger blue", 0x1e90ff },
729 		{ "firebrick", 0xb22222 },
730 		{ "firebrick1", 0xff3030 },
731 		{ "firebrick2", 0xee2c2c },
732 		{ "firebrick3", 0xcd2626 },
733 		{ "firebrick4", 0x8b1a1a },
734 		{ "floral white", 0xfffaf0 },
735 		{ "forest green", 0x228b22 },
736 		{ "fuchsia", 0xff00ff },
737 		{ "gainsboro", 0xdcdcdc },
738 		{ "ghost white", 0xf8f8ff },
739 		{ "gold", 0xffd700 },
740 		{ "gold1", 0xffd700 },
741 		{ "gold2", 0xeec900 },
742 		{ "gold3", 0xcdad00 },
743 		{ "gold4", 0x8b7500 },
744 		{ "goldenrod", 0xdaa520 },
745 		{ "goldenrod1", 0xffc125 },
746 		{ "goldenrod2", 0xeeb422 },
747 		{ "goldenrod3", 0xcd9b1d },
748 		{ "goldenrod4", 0x8b6914 },
749 		{ "green yellow", 0xadff2f },
750 		{ "green", 0x00ff00 },
751 		{ "green1", 0x00ff00 },
752 		{ "green2", 0x00ee00 },
753 		{ "green3", 0x00cd00 },
754 		{ "green4", 0x008b00 },
755 		{ "honeydew", 0xf0fff0 },
756 		{ "honeydew1", 0xf0fff0 },
757 		{ "honeydew2", 0xe0eee0 },
758 		{ "honeydew3", 0xc1cdc1 },
759 		{ "honeydew4", 0x838b83 },
760 		{ "hot pink", 0xff69b4 },
761 		{ "indian red", 0xcd5c5c },
762 		{ "indigo", 0x4b0082 },
763 		{ "ivory", 0xfffff0 },
764 		{ "ivory1", 0xfffff0 },
765 		{ "ivory2", 0xeeeee0 },
766 		{ "ivory3", 0xcdcdc1 },
767 		{ "ivory4", 0x8b8b83 },
768 		{ "khaki", 0xf0e68c },
769 		{ "khaki1", 0xfff68f },
770 		{ "khaki2", 0xeee685 },
771 		{ "khaki3", 0xcdc673 },
772 		{ "khaki4", 0x8b864e },
773 		{ "lavender blush", 0xfff0f5 },
774 		{ "lavender", 0xe6e6fa },
775 		{ "lawn green", 0x7cfc00 },
776 		{ "lemon chiffon", 0xfffacd },
777 		{ "light blue", 0xadd8e6 },
778 		{ "light coral", 0xf08080 },
779 		{ "light cyan", 0xe0ffff },
780 		{ "light goldenrod yellow", 0xfafad2 },
781 		{ "light goldenrod", 0xeedd82 },
782 		{ "light gray", 0xd3d3d3 },
783 		{ "light green", 0x90ee90 },
784 		{ "light grey", 0xd3d3d3 },
785 		{ "light pink", 0xffb6c1 },
786 		{ "light salmon", 0xffa07a },
787 		{ "light sea green", 0x20b2aa },
788 		{ "light sky blue", 0x87cefa },
789 		{ "light slate blue", 0x8470ff },
790 		{ "light slate gray", 0x778899 },
791 		{ "light slate grey", 0x778899 },
792 		{ "light steel blue", 0xb0c4de },
793 		{ "light yellow", 0xffffe0 },
794 		{ "lime green", 0x32cd32 },
795 		{ "lime", 0x00ff00 },
796 		{ "linen", 0xfaf0e6 },
797 		{ "magenta", 0xff00ff },
798 		{ "magenta1", 0xff00ff },
799 		{ "magenta2", 0xee00ee },
800 		{ "magenta3", 0xcd00cd },
801 		{ "magenta4", 0x8b008b },
802 		{ "maroon", 0xb03060 },
803 		{ "maroon1", 0xff34b3 },
804 		{ "maroon2", 0xee30a7 },
805 		{ "maroon3", 0xcd2990 },
806 		{ "maroon4", 0x8b1c62 },
807 		{ "medium aquamarine", 0x66cdaa },
808 		{ "medium blue", 0x0000cd },
809 		{ "medium orchid", 0xba55d3 },
810 		{ "medium purple", 0x9370db },
811 		{ "medium sea green", 0x3cb371 },
812 		{ "medium slate blue", 0x7b68ee },
813 		{ "medium spring green", 0x00fa9a },
814 		{ "medium turquoise", 0x48d1cc },
815 		{ "medium violet red", 0xc71585 },
816 		{ "midnight blue", 0x191970 },
817 		{ "mint cream", 0xf5fffa },
818 		{ "misty rose", 0xffe4e1 },
819 		{ "moccasin", 0xffe4b5 },
820 		{ "navajo white", 0xffdead },
821 		{ "navy blue", 0x000080 },
822 		{ "navy", 0x000080 },
823 		{ "old lace", 0xfdf5e6 },
824 		{ "olive drab", 0x6b8e23 },
825 		{ "olive", 0x808000 },
826 		{ "orange red", 0xff4500 },
827 		{ "orange", 0xffa500 },
828 		{ "orange1", 0xffa500 },
829 		{ "orange2", 0xee9a00 },
830 		{ "orange3", 0xcd8500 },
831 		{ "orange4", 0x8b5a00 },
832 		{ "orchid", 0xda70d6 },
833 		{ "orchid1", 0xff83fa },
834 		{ "orchid2", 0xee7ae9 },
835 		{ "orchid3", 0xcd69c9 },
836 		{ "orchid4", 0x8b4789 },
837 		{ "pale goldenrod", 0xeee8aa },
838 		{ "pale green", 0x98fb98 },
839 		{ "pale turquoise", 0xafeeee },
840 		{ "pale violet red", 0xdb7093 },
841 		{ "papaya whip", 0xffefd5 },
842 		{ "peach puff", 0xffdab9 },
843 		{ "peru", 0xcd853f },
844 		{ "pink", 0xffc0cb },
845 		{ "pink1", 0xffb5c5 },
846 		{ "pink2", 0xeea9b8 },
847 		{ "pink3", 0xcd919e },
848 		{ "pink4", 0x8b636c },
849 		{ "plum", 0xdda0dd },
850 		{ "plum1", 0xffbbff },
851 		{ "plum2", 0xeeaeee },
852 		{ "plum3", 0xcd96cd },
853 		{ "plum4", 0x8b668b },
854 		{ "powder blue", 0xb0e0e6 },
855 		{ "purple", 0xa020f0 },
856 		{ "purple1", 0x9b30ff },
857 		{ "purple2", 0x912cee },
858 		{ "purple3", 0x7d26cd },
859 		{ "purple4", 0x551a8b },
860 		{ "rebecca purple", 0x663399 },
861 		{ "red", 0xff0000 },
862 		{ "red1", 0xff0000 },
863 		{ "red2", 0xee0000 },
864 		{ "red3", 0xcd0000 },
865 		{ "red4", 0x8b0000 },
866 		{ "rosy brown", 0xbc8f8f },
867 		{ "royal blue", 0x4169e1 },
868 		{ "saddle brown", 0x8b4513 },
869 		{ "salmon", 0xfa8072 },
870 		{ "salmon1", 0xff8c69 },
871 		{ "salmon2", 0xee8262 },
872 		{ "salmon3", 0xcd7054 },
873 		{ "salmon4", 0x8b4c39 },
874 		{ "sandy brown", 0xf4a460 },
875 		{ "sea green", 0x2e8b57 },
876 		{ "seashell", 0xfff5ee },
877 		{ "seashell1", 0xfff5ee },
878 		{ "seashell2", 0xeee5de },
879 		{ "seashell3", 0xcdc5bf },
880 		{ "seashell4", 0x8b8682 },
881 		{ "sienna", 0xa0522d },
882 		{ "sienna1", 0xff8247 },
883 		{ "sienna2", 0xee7942 },
884 		{ "sienna3", 0xcd6839 },
885 		{ "sienna4", 0x8b4726 },
886 		{ "silver", 0xc0c0c0 },
887 		{ "sky blue", 0x87ceeb },
888 		{ "slate blue", 0x6a5acd },
889 		{ "slate gray", 0x708090 },
890 		{ "slate grey", 0x708090 },
891 		{ "snow", 0xfffafa },
892 		{ "snow1", 0xfffafa },
893 		{ "snow2", 0xeee9e9 },
894 		{ "snow3", 0xcdc9c9 },
895 		{ "snow4", 0x8b8989 },
896 		{ "spring green", 0x00ff7f },
897 		{ "steel blue", 0x4682b4 },
898 		{ "tan", 0xd2b48c },
899 		{ "tan1", 0xffa54f },
900 		{ "tan2", 0xee9a49 },
901 		{ "tan3", 0xcd853f },
902 		{ "tan4", 0x8b5a2b },
903 		{ "teal", 0x008080 },
904 		{ "thistle", 0xd8bfd8 },
905 		{ "thistle1", 0xffe1ff },
906 		{ "thistle2", 0xeed2ee },
907 		{ "thistle3", 0xcdb5cd },
908 		{ "thistle4", 0x8b7b8b },
909 		{ "tomato", 0xff6347 },
910 		{ "tomato1", 0xff6347 },
911 		{ "tomato2", 0xee5c42 },
912 		{ "tomato3", 0xcd4f39 },
913 		{ "tomato4", 0x8b3626 },
914 		{ "turquoise", 0x40e0d0 },
915 		{ "turquoise1", 0x00f5ff },
916 		{ "turquoise2", 0x00e5ee },
917 		{ "turquoise3", 0x00c5cd },
918 		{ "turquoise4", 0x00868b },
919 		{ "violet red", 0xd02090 },
920 		{ "violet", 0xee82ee },
921 		{ "web gray", 0x808080 },
922 		{ "web green", 0x008000 },
923 		{ "web grey", 0x808080 },
924 		{ "web maroon", 0x800000 },
925 		{ "web purple", 0x800080 },
926 		{ "wheat", 0xf5deb3 },
927 		{ "wheat1", 0xffe7ba },
928 		{ "wheat2", 0xeed8ae },
929 		{ "wheat3", 0xcdba96 },
930 		{ "wheat4", 0x8b7e66 },
931 		{ "white smoke", 0xf5f5f5 },
932 		{ "white", 0xffffff },
933 		{ "x11 gray", 0xbebebe },
934 		{ "x11 green", 0x00ff00 },
935 		{ "x11 grey", 0xbebebe },
936 		{ "x11 maroon", 0xb03060 },
937 		{ "x11 purple", 0xa020f0 },
938 		{ "yellow green", 0x9acd32 },
939 		{ "yellow", 0xffff00 },
940 		{ "yellow1", 0xffff00 },
941 		{ "yellow2", 0xeeee00 },
942 		{ "yellow3", 0xcdcd00 },
943 		{ "yellow4", 0x8b8b00 }
944 	};
945 	u_int		 i;
946 	int		 c;
947 	const char	*errstr;
948 
949 	if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) {
950 		if (name[4] == '\0')
951 			return (0xbebebe|COLOUR_FLAG_RGB);
952 		c = strtonum(name + 4, 0, 100, &errstr);
953 		if (errstr != NULL)
954 			return (-1);
955 		c = round(2.55 * c);
956 		if (c < 0 || c > 255)
957 			return (-1);
958 		return (colour_join_rgb(c, c, c));
959 	}
960 	for (i = 0; i < nitems(colours); i++) {
961 		if (strcasecmp(colours[i].name, name) == 0)
962 			return (colours[i].c|COLOUR_FLAG_RGB);
963 	}
964 	return (-1);
965 }
966 
967 /* Parse colour from an X11 string. */
968 int
colour_parseX11(const char * p)969 colour_parseX11(const char *p)
970 {
971 	double	 c, m, y, k = 0;
972 	u_int	 r, g, b;
973 	size_t	 len = strlen(p);
974 	int	 colour = -1;
975 	char	*copy;
976 
977 	if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
978 	    (len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
979 	    sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
980 		colour = colour_join_rgb(r, g, b);
981 	else if ((len == 18 &&
982 	    sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
983 	    (len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
984 		colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
985 	else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
986 	    sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
987 	    c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
988 	    y >= 0 && y <= 1 && k >= 0 && k <= 1) {
989 		colour = colour_join_rgb(
990 		    (1 - c) * (1 - k) * 255,
991 		    (1 - m) * (1 - k) * 255,
992 		    (1 - y) * (1 - k) * 255);
993 	} else {
994 		while (len != 0 && *p == ' ') {
995 			p++;
996 			len--;
997 		}
998 		while (len != 0 && p[len - 1] == ' ')
999 			len--;
1000 		copy = xstrndup(p, len);
1001 		colour = colour_byname(copy);
1002 		free(copy);
1003 	}
1004 	log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
1005 	return (colour);
1006 }
1007 
1008 /* Initialize palette. */
1009 void
colour_palette_init(struct colour_palette * p)1010 colour_palette_init(struct colour_palette *p)
1011 {
1012 	p->fg = 8;
1013 	p->bg = 8;
1014 	p->palette = NULL;
1015 	p->default_palette = NULL;
1016 }
1017 
1018 /* Clear palette. */
1019 void
colour_palette_clear(struct colour_palette * p)1020 colour_palette_clear(struct colour_palette *p)
1021 {
1022 	if (p != NULL) {
1023 		p->fg = 8;
1024 		p->bg = 8;
1025  		free(p->palette);
1026 		p->palette = NULL;
1027 	}
1028 }
1029 
1030 /* Free a palette. */
1031 void
colour_palette_free(struct colour_palette * p)1032 colour_palette_free(struct colour_palette *p)
1033 {
1034 	if (p != NULL) {
1035 		free(p->palette);
1036 		p->palette = NULL;
1037 		free(p->default_palette);
1038 		p->default_palette = NULL;
1039 	}
1040 }
1041 
1042 /* Get a colour from a palette. */
1043 int
colour_palette_get(struct colour_palette * p,int c)1044 colour_palette_get(struct colour_palette *p, int c)
1045 {
1046 	if (p == NULL)
1047 		return (-1);
1048 
1049 	if (c >= 90 && c <= 97)
1050 		c = 8 + c - 90;
1051 	else if (c & COLOUR_FLAG_256)
1052 		c &= ~COLOUR_FLAG_256;
1053 	else if (c >= 8)
1054 		return (-1);
1055 
1056 	if (p->palette != NULL && p->palette[c] != -1)
1057 		return (p->palette[c]);
1058 	if (p->default_palette != NULL && p->default_palette[c] != -1)
1059 		return (p->default_palette[c]);
1060 	return (-1);
1061 }
1062 
1063 /* Set a colour in a palette. */
1064 int
colour_palette_set(struct colour_palette * p,int n,int c)1065 colour_palette_set(struct colour_palette *p, int n, int c)
1066 {
1067 	u_int	i;
1068 
1069 	if (p == NULL || n > 255)
1070 		return (0);
1071 
1072 	if (c == -1 && p->palette == NULL)
1073 		return (0);
1074 
1075 	if (c != -1 && p->palette == NULL) {
1076 		if (p->palette == NULL)
1077 			p->palette = xcalloc(256, sizeof *p->palette);
1078 		for (i = 0; i < 256; i++)
1079 			p->palette[i] = -1;
1080 	}
1081 	p->palette[n] = c;
1082 	return (1);
1083 }
1084 
1085 /* Build palette defaults from an option. */
1086 void
colour_palette_from_option(struct colour_palette * p,struct options * oo)1087 colour_palette_from_option(struct colour_palette *p, struct options *oo)
1088 {
1089 	struct options_entry		*o;
1090 	struct options_array_item	*a;
1091 	u_int				 i, n;
1092 	int				 c;
1093 
1094 	if (p == NULL)
1095 		return;
1096 
1097 	o = options_get(oo, "pane-colours");
1098 	if ((a = options_array_first(o)) == NULL) {
1099 		if (p->default_palette != NULL) {
1100 			free(p->default_palette);
1101 			p->default_palette = NULL;
1102 		}
1103 		return;
1104 	}
1105 	if (p->default_palette == NULL)
1106 		p->default_palette = xcalloc(256, sizeof *p->default_palette);
1107 	for (i = 0; i < 256; i++)
1108 		p->default_palette[i] = -1;
1109 	while (a != NULL) {
1110 		n = options_array_item_index(a);
1111 		if (n < 256) {
1112 			c = options_array_item_value(a)->number;
1113 			p->default_palette[n] = c;
1114 		}
1115 		a = options_array_next(a);
1116 	}
1117 }
1118