Coverage Report

Created: 2026-07-16 06:55

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