Do not continue to send data to suspended/locked clients or there will
[tmux-openbsd.git] / colour.c
blob3530686a92874234967f052be48cf0c8808cad8f
1 /* $OpenBSD$ */
3 /*
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>
21 #include <ctype.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "tmux.h"
29 * Colour to string conversion functions. Bit 8 of the colour means it is one
30 * of the 256 colour palette.
33 /* An RGB colour. */
34 struct colour_rgb {
35 u_char r;
36 u_char g;
37 u_char b;
40 /* 256 colour RGB table, generated on first use. */
41 struct colour_rgb *colour_rgb_256;
43 void colour_rgb_generate256(void);
44 double colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
45 int colour_rgb_find(struct colour_rgb *);
47 /* Generate 256 colour RGB table. */
48 void
49 colour_rgb_generate256(void)
51 struct colour_rgb *rgb;
52 u_int i, r, g, b;
55 * Allocate the table. The first 16 colours are often changed by users
56 * and terminals so don't include them.
58 colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);
60 /* Add the colours first. */
61 r = g = b = 0;
62 for (i = 240; i > 24; i--) {
63 rgb = &colour_rgb_256[240 - i];
65 if (r != 0)
66 rgb->r = (r * 40) + 55;
67 if (g != 0)
68 rgb->g = (g * 40) + 55;
69 if (b != 0)
70 rgb->b = (b * 40) + 55;
72 b++;
73 if (b > 5) {
74 b = 0;
75 g++;
77 if (g > 5) {
78 g = 0;
79 r++;
83 /* Then add the greys. */
84 for (i = 24; i > 0; i--) {
85 rgb = &colour_rgb_256[240 - i];
87 rgb->r = 8 + (24 - i) * 10;
88 rgb->g = 8 + (24 - i) * 10;
89 rgb->b = 8 + (24 - i) * 10;
93 /* Get colour RGB distance. */
94 double
95 colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
97 int r, g, b;
99 r = rgb1->r - rgb2->r;
100 g = rgb1->g - rgb2->g;
101 b = rgb1->b - rgb2->b;
102 return (sqrt(r * r + g * g + b * b));
105 /* Work out the nearest colour from the 256 colour set. */
107 colour_rgb_find(struct colour_rgb *rgb)
109 double distance, lowest;
110 u_int colour, i;
112 if (colour_rgb_256 == NULL)
113 colour_rgb_generate256();
115 colour = 16;
116 lowest = INFINITY;
117 for (i = 0; i < 240; i++) {
118 distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
119 if (distance < lowest) {
120 lowest = distance;
121 colour = 16 + i;
124 return (colour);
127 /* Set grid cell foreground colour. */
128 void
129 colour_set_fg(struct grid_cell *gc, int c)
131 if (c & 0x100)
132 gc->flags |= GRID_FLAG_FG256;
133 gc->fg = c;
136 /* Set grid cell background colour. */
137 void
138 colour_set_bg(struct grid_cell *gc, int c)
140 if (c & 0x100)
141 gc->flags |= GRID_FLAG_BG256;
142 gc->bg = c;
145 /* Convert colour to a string. */
146 const char *
147 colour_tostring(int c)
149 static char s[32];
151 if (c & 0x100) {
152 xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
153 return (s);
156 switch (c) {
157 case 0:
158 return ("black");
159 case 1:
160 return ("red");
161 case 2:
162 return ("green");
163 case 3:
164 return ("yellow");
165 case 4:
166 return ("blue");
167 case 5:
168 return ("magenta");
169 case 6:
170 return ("cyan");
171 case 7:
172 return ("white");
173 case 8:
174 return ("default");
176 return (NULL);
179 /* Convert colour from string. */
181 colour_fromstring(const char *s)
183 const char *errstr;
184 const char *cp;
185 struct colour_rgb rgb;
186 int n;
188 if (*s == '#' && strlen(s) == 7) {
189 for (cp = s + 1; isxdigit((u_char) *cp); cp++)
191 if (*cp != '\0')
192 return (-1);
193 n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b);
194 if (n != 3)
195 return (-1);
196 return (colour_rgb_find(&rgb) | 0x100);
199 if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
200 n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
201 if (errstr != NULL)
202 return (-1);
203 return (n | 0x100);
206 if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
207 return (0);
208 if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))
209 return (1);
210 if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0'))
211 return (2);
212 if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0'))
213 return (3);
214 if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0'))
215 return (4);
216 if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0'))
217 return (5);
218 if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0'))
219 return (6);
220 if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0'))
221 return (7);
222 if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
223 return (8);
224 return (-1);
227 /* Convert 256 colour palette to 16. */
228 u_char
229 colour_256to16(u_char c)
231 static const u_char table[256] = {
232 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
233 0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
234 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
235 10, 10, 10, 14, 1, 5, 4, 4, 12, 12, 3, 8, 4, 4, 12, 12,
236 2, 2, 6, 4, 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10,
237 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 5, 4, 12, 12, 1, 1,
238 5, 4, 12, 12, 3, 3, 8, 4, 12, 12, 2, 2, 2, 6, 12, 12,
239 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 1, 5,
240 12, 12, 1, 1, 1, 5, 12, 12, 1, 1, 1, 5, 12, 12, 3, 3,
241 3, 7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
242 9, 9, 9, 9, 13, 12, 9, 9, 9, 9, 13, 12, 9, 9, 9, 9,
243 13, 12, 9, 9, 9, 9, 13, 12, 11, 11, 11, 11, 7, 12, 10, 10,
244 10, 10, 10, 14, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13,
245 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9,
246 9, 13, 11, 11, 11, 11, 11, 15, 0, 0, 0, 0, 0, 0, 8, 8,
247 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15
250 return (table[c]);
253 /* Convert 256 colour palette to 88. */
254 u_char
255 colour_256to88(u_char c)
257 static const u_char table[256] = {
258 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
259 16, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, 23, 20, 21, 21, 22,
260 22, 23, 24, 25, 25, 26, 26, 27, 24, 25, 25, 26, 26, 27, 28, 29,
261 29, 30, 30, 31, 32, 33, 33, 34, 34, 35, 36, 37, 37, 38, 38, 39,
262 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43, 40, 41, 41, 42,
263 42, 43, 44, 45, 45, 46, 46, 47, 32, 33, 33, 34, 34, 35, 36, 37,
264 37, 38, 38, 39, 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43,
265 40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 46, 47, 48, 49, 49, 50,
266 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54, 54, 55, 56, 57,
267 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63,
268 48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54,
269 54, 55, 56, 57, 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61,
270 61, 62, 62, 63, 64, 65, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71,
271 68, 69, 69, 70, 70, 71, 72, 73, 73, 74, 74, 75, 72, 73, 73, 74,
272 74, 75, 76, 77, 77, 78, 78, 79, 0, 0, 80, 80, 80, 81, 81, 81,
273 82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87
276 return (table[c]);