xref: /netbsd-src/external/bsd/tmux/dist/colour.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
5  *
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.
9  *
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.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "tmux.h"
26 
27 /*
28  * Colour to string conversion functions. Bit 8 of the colour means it is one
29  * of the 256 colour palette.
30  */
31 
32 struct colour_rgb {
33 	u_char  i;
34 	u_char	r;
35 	u_char	g;
36 	u_char	b;
37 };
38 
39 const struct colour_rgb colour_from_256[] = {
40 	{   0, 0x00, 0x00, 0x00 }, {   1, 0x00, 0x00, 0x5f },
41 	{   2, 0x00, 0x00, 0x87 }, {   3, 0x00, 0x00, 0xaf },
42 	{   4, 0x00, 0x00, 0xd7 }, {   5, 0x00, 0x00, 0xff },
43 	{   6, 0x00, 0x5f, 0x00 }, {   7, 0x00, 0x5f, 0x5f },
44 	{   8, 0x00, 0x5f, 0x87 }, {   9, 0x00, 0x5f, 0xaf },
45 	{  10, 0x00, 0x5f, 0xd7 }, {  11, 0x00, 0x5f, 0xff },
46 	{  12, 0x00, 0x87, 0x00 }, {  13, 0x00, 0x87, 0x5f },
47 	{  14, 0x00, 0x87, 0x87 }, {  15, 0x00, 0x87, 0xaf },
48 	{  16, 0x00, 0x87, 0xd7 }, {  17, 0x00, 0x87, 0xff },
49 	{  18, 0x00, 0xaf, 0x00 }, {  19, 0x00, 0xaf, 0x5f },
50 	{  20, 0x00, 0xaf, 0x87 }, {  21, 0x00, 0xaf, 0xaf },
51 	{  22, 0x00, 0xaf, 0xd7 }, {  23, 0x00, 0xaf, 0xff },
52 	{  24, 0x00, 0xd7, 0x00 }, {  25, 0x00, 0xd7, 0x5f },
53 	{  26, 0x00, 0xd7, 0x87 }, {  27, 0x00, 0xd7, 0xaf },
54 	{  28, 0x00, 0xd7, 0xd7 }, {  29, 0x00, 0xd7, 0xff },
55 	{  30, 0x00, 0xff, 0x00 }, {  31, 0x00, 0xff, 0x5f },
56 	{  32, 0x00, 0xff, 0x87 }, {  33, 0x00, 0xff, 0xaf },
57 	{  34, 0x00, 0xff, 0xd7 }, {  35, 0x00, 0xff, 0xff },
58 	{  36, 0x5f, 0x00, 0x00 }, {  37, 0x5f, 0x00, 0x5f },
59 	{  38, 0x5f, 0x00, 0x87 }, {  39, 0x5f, 0x00, 0xaf },
60 	{  40, 0x5f, 0x00, 0xd7 }, {  41, 0x5f, 0x00, 0xff },
61 	{  42, 0x5f, 0x5f, 0x00 }, {  43, 0x5f, 0x5f, 0x5f },
62 	{  44, 0x5f, 0x5f, 0x87 }, {  45, 0x5f, 0x5f, 0xaf },
63 	{  46, 0x5f, 0x5f, 0xd7 }, {  47, 0x5f, 0x5f, 0xff },
64 	{  48, 0x5f, 0x87, 0x00 }, {  49, 0x5f, 0x87, 0x5f },
65 	{  50, 0x5f, 0x87, 0x87 }, {  51, 0x5f, 0x87, 0xaf },
66 	{  52, 0x5f, 0x87, 0xd7 }, {  53, 0x5f, 0x87, 0xff },
67 	{  54, 0x5f, 0xaf, 0x00 }, {  55, 0x5f, 0xaf, 0x5f },
68 	{  56, 0x5f, 0xaf, 0x87 }, {  57, 0x5f, 0xaf, 0xaf },
69 	{  58, 0x5f, 0xaf, 0xd7 }, {  59, 0x5f, 0xaf, 0xff },
70 	{  60, 0x5f, 0xd7, 0x00 }, {  61, 0x5f, 0xd7, 0x5f },
71 	{  62, 0x5f, 0xd7, 0x87 }, {  63, 0x5f, 0xd7, 0xaf },
72 	{  64, 0x5f, 0xd7, 0xd7 }, {  65, 0x5f, 0xd7, 0xff },
73 	{  66, 0x5f, 0xff, 0x00 }, {  67, 0x5f, 0xff, 0x5f },
74 	{  68, 0x5f, 0xff, 0x87 }, {  69, 0x5f, 0xff, 0xaf },
75 	{  70, 0x5f, 0xff, 0xd7 }, {  71, 0x5f, 0xff, 0xff },
76 	{  72, 0x87, 0x00, 0x00 }, {  73, 0x87, 0x00, 0x5f },
77 	{  74, 0x87, 0x00, 0x87 }, {  75, 0x87, 0x00, 0xaf },
78 	{  76, 0x87, 0x00, 0xd7 }, {  77, 0x87, 0x00, 0xff },
79 	{  78, 0x87, 0x5f, 0x00 }, {  79, 0x87, 0x5f, 0x5f },
80 	{  80, 0x87, 0x5f, 0x87 }, {  81, 0x87, 0x5f, 0xaf },
81 	{  82, 0x87, 0x5f, 0xd7 }, {  83, 0x87, 0x5f, 0xff },
82 	{  84, 0x87, 0x87, 0x00 }, {  85, 0x87, 0x87, 0x5f },
83 	{  86, 0x87, 0x87, 0x87 }, {  87, 0x87, 0x87, 0xaf },
84 	{  88, 0x87, 0x87, 0xd7 }, {  89, 0x87, 0x87, 0xff },
85 	{  90, 0x87, 0xaf, 0x00 }, {  91, 0x87, 0xaf, 0x5f },
86 	{  92, 0x87, 0xaf, 0x87 }, {  93, 0x87, 0xaf, 0xaf },
87 	{  94, 0x87, 0xaf, 0xd7 }, {  95, 0x87, 0xaf, 0xff },
88 	{  96, 0x87, 0xd7, 0x00 }, {  97, 0x87, 0xd7, 0x5f },
89 	{  98, 0x87, 0xd7, 0x87 }, {  99, 0x87, 0xd7, 0xaf },
90 	{ 100, 0x87, 0xd7, 0xd7 }, { 101, 0x87, 0xd7, 0xff },
91 	{ 102, 0x87, 0xff, 0x00 }, { 103, 0x87, 0xff, 0x5f },
92 	{ 104, 0x87, 0xff, 0x87 }, { 105, 0x87, 0xff, 0xaf },
93 	{ 106, 0x87, 0xff, 0xd7 }, { 107, 0x87, 0xff, 0xff },
94 	{ 108, 0xaf, 0x00, 0x00 }, { 109, 0xaf, 0x00, 0x5f },
95 	{ 110, 0xaf, 0x00, 0x87 }, { 111, 0xaf, 0x00, 0xaf },
96 	{ 112, 0xaf, 0x00, 0xd7 }, { 113, 0xaf, 0x00, 0xff },
97 	{ 114, 0xaf, 0x5f, 0x00 }, { 115, 0xaf, 0x5f, 0x5f },
98 	{ 116, 0xaf, 0x5f, 0x87 }, { 117, 0xaf, 0x5f, 0xaf },
99 	{ 118, 0xaf, 0x5f, 0xd7 }, { 119, 0xaf, 0x5f, 0xff },
100 	{ 120, 0xaf, 0x87, 0x00 }, { 121, 0xaf, 0x87, 0x5f },
101 	{ 122, 0xaf, 0x87, 0x87 }, { 123, 0xaf, 0x87, 0xaf },
102 	{ 124, 0xaf, 0x87, 0xd7 }, { 125, 0xaf, 0x87, 0xff },
103 	{ 126, 0xaf, 0xaf, 0x00 }, { 127, 0xaf, 0xaf, 0x5f },
104 	{ 128, 0xaf, 0xaf, 0x87 }, { 129, 0xaf, 0xaf, 0xaf },
105 	{ 130, 0xaf, 0xaf, 0xd7 }, { 131, 0xaf, 0xaf, 0xff },
106 	{ 132, 0xaf, 0xd7, 0x00 }, { 133, 0xaf, 0xd7, 0x5f },
107 	{ 134, 0xaf, 0xd7, 0x87 }, { 135, 0xaf, 0xd7, 0xaf },
108 	{ 136, 0xaf, 0xd7, 0xd7 }, { 137, 0xaf, 0xd7, 0xff },
109 	{ 138, 0xaf, 0xff, 0x00 }, { 139, 0xaf, 0xff, 0x5f },
110 	{ 140, 0xaf, 0xff, 0x87 }, { 141, 0xaf, 0xff, 0xaf },
111 	{ 142, 0xaf, 0xff, 0xd7 }, { 143, 0xaf, 0xff, 0xff },
112 	{ 144, 0xd7, 0x00, 0x00 }, { 145, 0xd7, 0x00, 0x5f },
113 	{ 146, 0xd7, 0x00, 0x87 }, { 147, 0xd7, 0x00, 0xaf },
114 	{ 148, 0xd7, 0x00, 0xd7 }, { 149, 0xd7, 0x00, 0xff },
115 	{ 150, 0xd7, 0x5f, 0x00 }, { 151, 0xd7, 0x5f, 0x5f },
116 	{ 152, 0xd7, 0x5f, 0x87 }, { 153, 0xd7, 0x5f, 0xaf },
117 	{ 154, 0xd7, 0x5f, 0xd7 }, { 155, 0xd7, 0x5f, 0xff },
118 	{ 156, 0xd7, 0x87, 0x00 }, { 157, 0xd7, 0x87, 0x5f },
119 	{ 158, 0xd7, 0x87, 0x87 }, { 159, 0xd7, 0x87, 0xaf },
120 	{ 160, 0xd7, 0x87, 0xd7 }, { 161, 0xd7, 0x87, 0xff },
121 	{ 162, 0xd7, 0xaf, 0x00 }, { 163, 0xd7, 0xaf, 0x5f },
122 	{ 164, 0xd7, 0xaf, 0x87 }, { 165, 0xd7, 0xaf, 0xaf },
123 	{ 166, 0xd7, 0xaf, 0xd7 }, { 167, 0xd7, 0xaf, 0xff },
124 	{ 168, 0xd7, 0xd7, 0x00 }, { 169, 0xd7, 0xd7, 0x5f },
125 	{ 170, 0xd7, 0xd7, 0x87 }, { 171, 0xd7, 0xd7, 0xaf },
126 	{ 172, 0xd7, 0xd7, 0xd7 }, { 173, 0xd7, 0xd7, 0xff },
127 	{ 174, 0xd7, 0xff, 0x00 }, { 175, 0xd7, 0xff, 0x5f },
128 	{ 176, 0xd7, 0xff, 0x87 }, { 177, 0xd7, 0xff, 0xaf },
129 	{ 178, 0xd7, 0xff, 0xd7 }, { 179, 0xd7, 0xff, 0xff },
130 	{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
131 	{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
132 	{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
133 	{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
134 	{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
135 	{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
136 	{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
137 	{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
138 	{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
139 	{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
140 	{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
141 	{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
142 	{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
143 	{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
144 	{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
145 	{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
146 	{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
147 	{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
148 	{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
149 	{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
150 	{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
151 	{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
152 	{ 224, 0x58, 0x58, 0x58 }, { 225, 0x62, 0x62, 0x62 },
153 	{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
154 	{ 228, 0x80, 0x80, 0x80 }, { 229, 0x8a, 0x8a, 0x8a },
155 	{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
156 	{ 232, 0xa8, 0xa8, 0xa8 }, { 233, 0xb2, 0xb2, 0xb2 },
157 	{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
158 	{ 236, 0xd0, 0xd0, 0xd0 }, { 237, 0xda, 0xda, 0xda },
159 	{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
160 };
161 const struct colour_rgb colour_to_256[] = {
162 	{   0, 0x00, 0x00, 0x00 }, {   1, 0x00, 0x00, 0x5f },
163 	{   2, 0x00, 0x00, 0x87 }, {   3, 0x00, 0x00, 0xaf },
164 	{   4, 0x00, 0x00, 0xd7 }, {   5, 0x00, 0x00, 0xff },
165 	{   6, 0x00, 0x5f, 0x00 }, {   7, 0x00, 0x5f, 0x5f },
166 	{   8, 0x00, 0x5f, 0x87 }, {   9, 0x00, 0x5f, 0xaf },
167 	{  10, 0x00, 0x5f, 0xd7 }, {  11, 0x00, 0x5f, 0xff },
168 	{  12, 0x00, 0x87, 0x00 }, {  13, 0x00, 0x87, 0x5f },
169 	{  14, 0x00, 0x87, 0x87 }, {  15, 0x00, 0x87, 0xaf },
170 	{  16, 0x00, 0x87, 0xd7 }, {  17, 0x00, 0x87, 0xff },
171 	{  18, 0x00, 0xaf, 0x00 }, {  19, 0x00, 0xaf, 0x5f },
172 	{  20, 0x00, 0xaf, 0x87 }, {  21, 0x00, 0xaf, 0xaf },
173 	{  22, 0x00, 0xaf, 0xd7 }, {  23, 0x00, 0xaf, 0xff },
174 	{  24, 0x00, 0xd7, 0x00 }, {  25, 0x00, 0xd7, 0x5f },
175 	{  26, 0x00, 0xd7, 0x87 }, {  27, 0x00, 0xd7, 0xaf },
176 	{  28, 0x00, 0xd7, 0xd7 }, {  29, 0x00, 0xd7, 0xff },
177 	{  30, 0x00, 0xff, 0x00 }, {  31, 0x00, 0xff, 0x5f },
178 	{  32, 0x00, 0xff, 0x87 }, {  33, 0x00, 0xff, 0xaf },
179 	{  34, 0x00, 0xff, 0xd7 }, {  35, 0x00, 0xff, 0xff },
180 	{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
181 	{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
182 	{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
183 	{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
184 	{ 224, 0x58, 0x58, 0x58 }, {  36, 0x5f, 0x00, 0x00 },
185 	{  37, 0x5f, 0x00, 0x5f }, {  38, 0x5f, 0x00, 0x87 },
186 	{  39, 0x5f, 0x00, 0xaf }, {  40, 0x5f, 0x00, 0xd7 },
187 	{  41, 0x5f, 0x00, 0xff }, {  42, 0x5f, 0x5f, 0x00 },
188 	{  43, 0x5f, 0x5f, 0x5f }, {  44, 0x5f, 0x5f, 0x87 },
189 	{  45, 0x5f, 0x5f, 0xaf }, {  46, 0x5f, 0x5f, 0xd7 },
190 	{  47, 0x5f, 0x5f, 0xff }, {  48, 0x5f, 0x87, 0x00 },
191 	{  49, 0x5f, 0x87, 0x5f }, {  50, 0x5f, 0x87, 0x87 },
192 	{  51, 0x5f, 0x87, 0xaf }, {  52, 0x5f, 0x87, 0xd7 },
193 	{  53, 0x5f, 0x87, 0xff }, {  54, 0x5f, 0xaf, 0x00 },
194 	{  55, 0x5f, 0xaf, 0x5f }, {  56, 0x5f, 0xaf, 0x87 },
195 	{  57, 0x5f, 0xaf, 0xaf }, {  58, 0x5f, 0xaf, 0xd7 },
196 	{  59, 0x5f, 0xaf, 0xff }, {  60, 0x5f, 0xd7, 0x00 },
197 	{  61, 0x5f, 0xd7, 0x5f }, {  62, 0x5f, 0xd7, 0x87 },
198 	{  63, 0x5f, 0xd7, 0xaf }, {  64, 0x5f, 0xd7, 0xd7 },
199 	{  65, 0x5f, 0xd7, 0xff }, {  66, 0x5f, 0xff, 0x00 },
200 	{  67, 0x5f, 0xff, 0x5f }, {  68, 0x5f, 0xff, 0x87 },
201 	{  69, 0x5f, 0xff, 0xaf }, {  70, 0x5f, 0xff, 0xd7 },
202 	{  71, 0x5f, 0xff, 0xff }, { 225, 0x62, 0x62, 0x62 },
203 	{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
204 	{ 228, 0x80, 0x80, 0x80 }, {  72, 0x87, 0x00, 0x00 },
205 	{  73, 0x87, 0x00, 0x5f }, {  74, 0x87, 0x00, 0x87 },
206 	{  75, 0x87, 0x00, 0xaf }, {  76, 0x87, 0x00, 0xd7 },
207 	{  77, 0x87, 0x00, 0xff }, {  78, 0x87, 0x5f, 0x00 },
208 	{  79, 0x87, 0x5f, 0x5f }, {  80, 0x87, 0x5f, 0x87 },
209 	{  81, 0x87, 0x5f, 0xaf }, {  82, 0x87, 0x5f, 0xd7 },
210 	{  83, 0x87, 0x5f, 0xff }, {  84, 0x87, 0x87, 0x00 },
211 	{  85, 0x87, 0x87, 0x5f }, {  86, 0x87, 0x87, 0x87 },
212 	{  87, 0x87, 0x87, 0xaf }, {  88, 0x87, 0x87, 0xd7 },
213 	{  89, 0x87, 0x87, 0xff }, {  90, 0x87, 0xaf, 0x00 },
214 	{  91, 0x87, 0xaf, 0x5f }, {  92, 0x87, 0xaf, 0x87 },
215 	{  93, 0x87, 0xaf, 0xaf }, {  94, 0x87, 0xaf, 0xd7 },
216 	{  95, 0x87, 0xaf, 0xff }, {  96, 0x87, 0xd7, 0x00 },
217 	{  97, 0x87, 0xd7, 0x5f }, {  98, 0x87, 0xd7, 0x87 },
218 	{  99, 0x87, 0xd7, 0xaf }, { 100, 0x87, 0xd7, 0xd7 },
219 	{ 101, 0x87, 0xd7, 0xff }, { 102, 0x87, 0xff, 0x00 },
220 	{ 103, 0x87, 0xff, 0x5f }, { 104, 0x87, 0xff, 0x87 },
221 	{ 105, 0x87, 0xff, 0xaf }, { 106, 0x87, 0xff, 0xd7 },
222 	{ 107, 0x87, 0xff, 0xff }, { 229, 0x8a, 0x8a, 0x8a },
223 	{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
224 	{ 232, 0xa8, 0xa8, 0xa8 }, { 108, 0xaf, 0x00, 0x00 },
225 	{ 109, 0xaf, 0x00, 0x5f }, { 110, 0xaf, 0x00, 0x87 },
226 	{ 111, 0xaf, 0x00, 0xaf }, { 112, 0xaf, 0x00, 0xd7 },
227 	{ 113, 0xaf, 0x00, 0xff }, { 114, 0xaf, 0x5f, 0x00 },
228 	{ 115, 0xaf, 0x5f, 0x5f }, { 116, 0xaf, 0x5f, 0x87 },
229 	{ 117, 0xaf, 0x5f, 0xaf }, { 118, 0xaf, 0x5f, 0xd7 },
230 	{ 119, 0xaf, 0x5f, 0xff }, { 120, 0xaf, 0x87, 0x00 },
231 	{ 121, 0xaf, 0x87, 0x5f }, { 122, 0xaf, 0x87, 0x87 },
232 	{ 123, 0xaf, 0x87, 0xaf }, { 124, 0xaf, 0x87, 0xd7 },
233 	{ 125, 0xaf, 0x87, 0xff }, { 126, 0xaf, 0xaf, 0x00 },
234 	{ 127, 0xaf, 0xaf, 0x5f }, { 128, 0xaf, 0xaf, 0x87 },
235 	{ 129, 0xaf, 0xaf, 0xaf }, { 130, 0xaf, 0xaf, 0xd7 },
236 	{ 131, 0xaf, 0xaf, 0xff }, { 132, 0xaf, 0xd7, 0x00 },
237 	{ 133, 0xaf, 0xd7, 0x5f }, { 134, 0xaf, 0xd7, 0x87 },
238 	{ 135, 0xaf, 0xd7, 0xaf }, { 136, 0xaf, 0xd7, 0xd7 },
239 	{ 137, 0xaf, 0xd7, 0xff }, { 138, 0xaf, 0xff, 0x00 },
240 	{ 139, 0xaf, 0xff, 0x5f }, { 140, 0xaf, 0xff, 0x87 },
241 	{ 141, 0xaf, 0xff, 0xaf }, { 142, 0xaf, 0xff, 0xd7 },
242 	{ 143, 0xaf, 0xff, 0xff }, { 233, 0xb2, 0xb2, 0xb2 },
243 	{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
244 	{ 236, 0xd0, 0xd0, 0xd0 }, { 144, 0xd7, 0x00, 0x00 },
245 	{ 145, 0xd7, 0x00, 0x5f }, { 146, 0xd7, 0x00, 0x87 },
246 	{ 147, 0xd7, 0x00, 0xaf }, { 148, 0xd7, 0x00, 0xd7 },
247 	{ 149, 0xd7, 0x00, 0xff }, { 150, 0xd7, 0x5f, 0x00 },
248 	{ 151, 0xd7, 0x5f, 0x5f }, { 152, 0xd7, 0x5f, 0x87 },
249 	{ 153, 0xd7, 0x5f, 0xaf }, { 154, 0xd7, 0x5f, 0xd7 },
250 	{ 155, 0xd7, 0x5f, 0xff }, { 156, 0xd7, 0x87, 0x00 },
251 	{ 157, 0xd7, 0x87, 0x5f }, { 158, 0xd7, 0x87, 0x87 },
252 	{ 159, 0xd7, 0x87, 0xaf }, { 160, 0xd7, 0x87, 0xd7 },
253 	{ 161, 0xd7, 0x87, 0xff }, { 162, 0xd7, 0xaf, 0x00 },
254 	{ 163, 0xd7, 0xaf, 0x5f }, { 164, 0xd7, 0xaf, 0x87 },
255 	{ 165, 0xd7, 0xaf, 0xaf }, { 166, 0xd7, 0xaf, 0xd7 },
256 	{ 167, 0xd7, 0xaf, 0xff }, { 168, 0xd7, 0xd7, 0x00 },
257 	{ 169, 0xd7, 0xd7, 0x5f }, { 170, 0xd7, 0xd7, 0x87 },
258 	{ 171, 0xd7, 0xd7, 0xaf }, { 172, 0xd7, 0xd7, 0xd7 },
259 	{ 173, 0xd7, 0xd7, 0xff }, { 174, 0xd7, 0xff, 0x00 },
260 	{ 175, 0xd7, 0xff, 0x5f }, { 176, 0xd7, 0xff, 0x87 },
261 	{ 177, 0xd7, 0xff, 0xaf }, { 178, 0xd7, 0xff, 0xd7 },
262 	{ 179, 0xd7, 0xff, 0xff }, { 237, 0xda, 0xda, 0xda },
263 	{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
264 	{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
265 	{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
266 	{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
267 	{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
268 	{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
269 	{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
270 	{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
271 	{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
272 	{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
273 	{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
274 	{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
275 	{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
276 	{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
277 	{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
278 	{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
279 	{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
280 	{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
281 	{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
282 };
283 
284 int	colour_cmp_rgb(const void *, const void *);
285 
286 /* Compare function for bsearch(). */
287 int
288 colour_cmp_rgb(const void *lhs0, const void *rhs0)
289 {
290 	const struct colour_rgb *lhs = lhs0, *rhs = rhs0;
291 
292 	if (lhs->r < rhs->r)
293 		return (-1);
294 	if (lhs->r > rhs->r)
295 		return (1);
296 
297 	if (lhs->g < rhs->g)
298 		return (-1);
299 	if (lhs->g > rhs->g)
300 		return (1);
301 
302 	if (lhs->b < rhs->b)
303 		return (-1);
304 	if (lhs->b > rhs->b)
305 		return (1);
306 
307 	return (0);
308 }
309 
310 /* Work out the nearest colour from the 256 colour set. */
311 int
312 colour_find_rgb(u_char r, u_char g, u_char b)
313 {
314 	struct colour_rgb	rgb = { .r = r, .g = g, .b = b }, *found;
315 	u_int			distance, lowest, colour, i;
316 	int			dr, dg, db;
317 
318 	found = bsearch(&rgb, colour_to_256, nitems(colour_to_256),
319 	    sizeof colour_to_256[0], colour_cmp_rgb);
320 	if (found != NULL)
321 		return (16 + found->i);
322 
323 	colour = 16;
324 	lowest = UINT_MAX;
325 	for (i = 0; i < 240; i++) {
326 		dr = (int)colour_from_256[i].r - r;
327 		dg = (int)colour_from_256[i].g - g;
328 		db = (int)colour_from_256[i].b - b;
329 
330 		distance = dr * dr + dg * dg + db * db;
331 		if (distance < lowest) {
332 			lowest = distance;
333 			colour = 16 + i;
334 		}
335 	}
336 	return (colour);
337 }
338 
339 /* Set grid cell foreground colour. */
340 void
341 colour_set_fg(struct grid_cell *gc, int c)
342 {
343 	if (c & 0x100)
344 		gc->flags |= GRID_FLAG_FG256;
345 	gc->fg = c;
346 }
347 
348 /* Set grid cell background colour. */
349 void
350 colour_set_bg(struct grid_cell *gc, int c)
351 {
352 	if (c & 0x100)
353 		gc->flags |= GRID_FLAG_BG256;
354 	gc->bg = c;
355 }
356 
357 /* Convert colour to a string. */
358 const char *
359 colour_tostring(int c)
360 {
361 	static char	s[32];
362 
363 	if (c & 0x100) {
364 		xsnprintf(s, sizeof s, "colour%d", c & ~0x100);
365 		return (s);
366 	}
367 
368 	switch (c) {
369 	case 0:
370 		return ("black");
371 	case 1:
372 		return ("red");
373 	case 2:
374 		return ("green");
375 	case 3:
376 		return ("yellow");
377 	case 4:
378 		return ("blue");
379 	case 5:
380 		return ("magenta");
381 	case 6:
382 		return ("cyan");
383 	case 7:
384 		return ("white");
385 	case 8:
386 		return ("default");
387 	case 90:
388 		return ("brightblack");
389 	case 91:
390 		return ("brightred");
391 	case 92:
392 		return ("brightgreen");
393 	case 93:
394 		return ("brightyellow");
395 	case 94:
396 		return ("brightblue");
397 	case 95:
398 		return ("brightmagenta");
399 	case 96:
400 		return ("brightcyan");
401 	case 97:
402 		return ("brightwhite");
403 	}
404 	return (NULL);
405 }
406 
407 /* Convert colour from string. */
408 int
409 colour_fromstring(const char *s)
410 {
411 	const char	*errstr;
412 	const char	*cp;
413 	int		 n;
414 	u_char		 r, g, b;
415 
416 	if (*s == '#' && strlen(s) == 7) {
417 		for (cp = s + 1; isxdigit((u_char) *cp); cp++)
418 			;
419 		if (*cp != '\0')
420 			return (-1);
421 		n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
422 		if (n != 3)
423 			return (-1);
424 		return (colour_find_rgb(r, g, b) | 0x100);
425 	}
426 
427 	if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
428 		n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
429 		if (errstr != NULL)
430 			return (-1);
431 		return (n | 0x100);
432 	}
433 
434 	if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
435 		return (0);
436 	if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
437 		return (1);
438 	if (strcasecmp(s, "green") == 0 || strcmp(s, "2") == 0)
439 		return (2);
440 	if (strcasecmp(s, "yellow") == 0 || strcmp(s, "3") == 0)
441 		return (3);
442 	if (strcasecmp(s, "blue") == 0 || strcmp(s, "4") == 0)
443 		return (4);
444 	if (strcasecmp(s, "magenta") == 0 || strcmp(s, "5") == 0)
445 		return (5);
446 	if (strcasecmp(s, "cyan") == 0 || strcmp(s, "6") == 0)
447 		return (6);
448 	if (strcasecmp(s, "white") == 0 || strcmp(s, "7") == 0)
449 		return (7);
450 	if (strcasecmp(s, "default") == 0 || strcmp(s, "8") == 0)
451 		return (8);
452 	if (strcasecmp(s, "brightblack") == 0 || strcmp(s, "90") == 0)
453 		return (90);
454 	if (strcasecmp(s, "brightred") == 0 || strcmp(s, "91") == 0)
455 		return (91);
456 	if (strcasecmp(s, "brightgreen") == 0 || strcmp(s, "92") == 0)
457 		return (92);
458 	if (strcasecmp(s, "brightyellow") == 0 || strcmp(s, "93") == 0)
459 		return (93);
460 	if (strcasecmp(s, "brightblue") == 0 || strcmp(s, "94") == 0)
461 		return (94);
462 	if (strcasecmp(s, "brightmagenta") == 0 || strcmp(s, "95") == 0)
463 		return (95);
464 	if (strcasecmp(s, "brightcyan") == 0 || strcmp(s, "96") == 0)
465 		return (96);
466 	if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
467 		return (97);
468 	return (-1);
469 }
470 
471 /* Convert 256 colour palette to 16. */
472 u_char
473 colour_256to16(u_char c)
474 {
475 	static const u_char table[256] = {
476 		 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
477 		 0,  4,  4,  4, 12, 12,  2,  6,  4,  4, 12, 12,  2,  2,  6,  4,
478 		12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
479 		10, 10, 10, 14,  1,  5,  4,  4, 12, 12,  3,  8,  4,  4, 12, 12,
480 		 2,  2,  6,  4, 12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10,
481 		14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  5,  4, 12, 12,  1,  1,
482 		 5,  4, 12, 12,  3,  3,  8,  4, 12, 12,  2,  2,  2,  6, 12, 12,
483 		10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  1,  5,
484 		12, 12,  1,  1,  1,  5, 12, 12,  1,  1,  1,  5, 12, 12,  3,  3,
485 		 3,  7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
486 		 9,  9,  9,  9, 13, 12,  9,  9,  9,  9, 13, 12,  9,  9,  9,  9,
487 		13, 12,  9,  9,  9,  9, 13, 12, 11, 11, 11, 11,  7, 12, 10, 10,
488 		10, 10, 10, 14,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,
489 		 9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,
490 		 9, 13, 11, 11, 11, 11, 11, 15,  0,  0,  0,  0,  0,  0,  8,  8,
491 		 8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15
492 	};
493 
494 	return (table[c]);
495 }
496