4 * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
28 * Colour to string conversion functions. Bit 8 of the colour means it is one
29 * of the 256 colour palette.
39 /* 256 colour RGB table, generated on first use. */
40 struct colour_rgb
*colour_rgb_256
;
42 void colour_rgb_generate256(void);
43 u_int
colour_rgb_distance(struct colour_rgb
*, struct colour_rgb
*);
44 int colour_rgb_find(struct colour_rgb
*);
46 /* Generate 256 colour RGB table. */
48 colour_rgb_generate256(void)
50 struct colour_rgb
*rgb
;
54 * Allocate the table. The first 16 colours are often changed by users
55 * and terminals so don't include them.
57 colour_rgb_256
= xcalloc(240, sizeof *colour_rgb_256
);
59 /* Add the colours first. */
61 for (i
= 240; i
> 24; i
--) {
62 rgb
= &colour_rgb_256
[240 - i
];
65 rgb
->r
= (r
* 40) + 55;
67 rgb
->g
= (g
* 40) + 55;
69 rgb
->b
= (b
* 40) + 55;
82 /* Then add the greys. */
83 for (i
= 24; i
> 0; i
--) {
84 rgb
= &colour_rgb_256
[240 - i
];
86 rgb
->r
= 8 + (24 - i
) * 10;
87 rgb
->g
= 8 + (24 - i
) * 10;
88 rgb
->b
= 8 + (24 - i
) * 10;
92 /* Get colour RGB distance. */
94 colour_rgb_distance(struct colour_rgb
*rgb1
, struct colour_rgb
*rgb2
)
98 r
= rgb1
->r
- rgb2
->r
;
99 g
= rgb1
->g
- rgb2
->g
;
100 b
= rgb1
->b
- rgb2
->b
;
101 return (r
* r
+ g
* g
+ b
* b
);
104 /* Work out the nearest colour from the 256 colour set. */
106 colour_rgb_find(struct colour_rgb
*rgb
)
108 u_int distance
, lowest
, colour
, i
;
110 if (colour_rgb_256
== NULL
)
111 colour_rgb_generate256();
115 for (i
= 0; i
< 240; i
++) {
116 distance
= colour_rgb_distance(&colour_rgb_256
[i
], rgb
);
117 if (distance
< lowest
) {
125 /* Set grid cell foreground colour. */
127 colour_set_fg(struct grid_cell
*gc
, int c
)
130 gc
->flags
|= GRID_FLAG_FG256
;
134 /* Set grid cell background colour. */
136 colour_set_bg(struct grid_cell
*gc
, int c
)
139 gc
->flags
|= GRID_FLAG_BG256
;
143 /* Convert colour to a string. */
145 colour_tostring(int c
)
150 xsnprintf(s
, sizeof s
, "colour%u", c
& ~0x100);
174 return ("brightblack");
176 return ("brightred");
178 return ("brightgreen");
180 return ("brightyellow");
182 return ("brightblue");
184 return ("brightmagenta");
186 return ("brightcyan");
188 return ("brightwhite");
193 /* Convert colour from string. */
195 colour_fromstring(const char *s
)
199 struct colour_rgb rgb
;
202 if (*s
== '#' && strlen(s
) == 7) {
203 for (cp
= s
+ 1; isxdigit((u_char
) *cp
); cp
++)
207 n
= sscanf(s
+ 1, "%2hhx%2hhx%2hhx", &rgb
.r
, &rgb
.g
, &rgb
.b
);
210 return (colour_rgb_find(&rgb
) | 0x100);
213 if (strncasecmp(s
, "colour", (sizeof "colour") - 1) == 0) {
214 n
= strtonum(s
+ (sizeof "colour") - 1, 0, 255, &errstr
);
220 if (strcasecmp(s
, "black") == 0 || (s
[0] == '0' && s
[1] == '\0'))
222 if (strcasecmp(s
, "red") == 0 || (s
[0] == '1' && s
[1] == '\0'))
224 if (strcasecmp(s
, "green") == 0 || (s
[0] == '2' && s
[1] == '\0'))
226 if (strcasecmp(s
, "yellow") == 0 || (s
[0] == '3' && s
[1] == '\0'))
228 if (strcasecmp(s
, "blue") == 0 || (s
[0] == '4' && s
[1] == '\0'))
230 if (strcasecmp(s
, "magenta") == 0 || (s
[0] == '5' && s
[1] == '\0'))
232 if (strcasecmp(s
, "cyan") == 0 || (s
[0] == '6' && s
[1] == '\0'))
234 if (strcasecmp(s
, "white") == 0 || (s
[0] == '7' && s
[1] == '\0'))
236 if (strcasecmp(s
, "default") == 0 || (s
[0] == '8' && s
[1] == '\0'))
238 if (strcasecmp(s
, "brightblack") == 0 ||
239 (s
[0] == '9' && s
[1] == '0' && s
[1] == '\0'))
241 if (strcasecmp(s
, "brightred") == 0 ||
242 (s
[0] == '9' && s
[1] == '1' && s
[1] == '\0'))
244 if (strcasecmp(s
, "brightgreen") == 0 ||
245 (s
[0] == '9' && s
[1] == '2' && s
[1] == '\0'))
247 if (strcasecmp(s
, "brightyellow") == 0 ||
248 (s
[0] == '9' && s
[1] == '3' && s
[1] == '\0'))
250 if (strcasecmp(s
, "brightblue") == 0 ||
251 (s
[0] == '9' && s
[1] == '4' && s
[1] == '\0'))
253 if (strcasecmp(s
, "brightmagenta") == 0 ||
254 (s
[0] == '9' && s
[1] == '5' && s
[1] == '\0'))
256 if (strcasecmp(s
, "brightcyan") == 0 ||
257 (s
[0] == '9' && s
[1] == '6' && s
[1] == '\0'))
259 if (strcasecmp(s
, "brightwhite") == 0 ||
260 (s
[0] == '9' && s
[1] == '7' && s
[1] == '\0'))
265 /* Convert 256 colour palette to 16. */
267 colour_256to16(u_char c
)
269 static const u_char table
[256] = {
270 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
271 0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
272 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
273 10, 10, 10, 14, 1, 5, 4, 4, 12, 12, 3, 8, 4, 4, 12, 12,
274 2, 2, 6, 4, 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10,
275 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 5, 4, 12, 12, 1, 1,
276 5, 4, 12, 12, 3, 3, 8, 4, 12, 12, 2, 2, 2, 6, 12, 12,
277 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 1, 5,
278 12, 12, 1, 1, 1, 5, 12, 12, 1, 1, 1, 5, 12, 12, 3, 3,
279 3, 7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
280 9, 9, 9, 9, 13, 12, 9, 9, 9, 9, 13, 12, 9, 9, 9, 9,
281 13, 12, 9, 9, 9, 9, 13, 12, 11, 11, 11, 11, 7, 12, 10, 10,
282 10, 10, 10, 14, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13,
283 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9,
284 9, 13, 11, 11, 11, 11, 11, 15, 0, 0, 0, 0, 0, 0, 8, 8,
285 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15