| | varnish-cache/bin/varnishtest/teken.c |
0 |
|
/*- |
1 |
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD |
2 |
|
* |
3 |
|
* Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> |
4 |
|
* All rights reserved. |
5 |
|
* |
6 |
|
* Redistribution and use in source and binary forms, with or without |
7 |
|
* modification, are permitted provided that the following conditions |
8 |
|
* are met: |
9 |
|
* 1. Redistributions of source code must retain the above copyright |
10 |
|
* notice, this list of conditions and the following disclaimer. |
11 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
12 |
|
* notice, this list of conditions and the following disclaimer in the |
13 |
|
* documentation and/or other materials provided with the distribution. |
14 |
|
* |
15 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
|
* SUCH DAMAGE. |
26 |
|
* |
27 |
|
* $FreeBSD: head/sys/teken/teken.c 333683 2018-05-16 18:12:49Z cem $ |
28 |
|
*/ |
29 |
|
|
30 |
|
#include "config.h" |
31 |
|
|
32 |
|
#include <sys/types.h> |
33 |
|
#include <limits.h> |
34 |
|
#include <stdint.h> |
35 |
|
#include <stdio.h> |
36 |
|
#include <string.h> |
37 |
|
#define teken_assert(x) assert(x) |
38 |
|
|
39 |
|
#include "vdef.h" |
40 |
|
#include "vas.h" |
41 |
|
|
42 |
|
/* debug messages */ |
43 |
|
#define teken_printf(...) |
44 |
|
|
45 |
|
/* Private flags for t_stateflags. */ |
46 |
|
#define TS_FIRSTDIGIT 0x0001 /* First numeric digit in escape sequence. */ |
47 |
|
#define TS_INSERT 0x0002 /* Insert mode. */ |
48 |
|
#define TS_AUTOWRAP 0x0004 /* Autowrap. */ |
49 |
|
#define TS_ORIGIN 0x0008 /* Origin mode. */ |
50 |
|
#define TS_WRAPPED 0x0010 /* Next character should be printed on col 0. */ |
51 |
|
#define TS_8BIT 0x0020 /* UTF-8 disabled. */ |
52 |
|
#define TS_CONS25 0x0040 /* cons25 emulation. */ |
53 |
|
#define TS_INSTRING 0x0080 /* Inside string. */ |
54 |
|
#define TS_CURSORKEYS 0x0100 /* Cursor keys mode. */ |
55 |
|
|
56 |
|
/* Character that blanks a cell. */ |
57 |
|
#define BLANK ' ' |
58 |
|
|
59 |
|
#include "teken.h" |
60 |
|
#include "teken_wcwidth.h" |
61 |
|
#include "teken_scs.h" |
62 |
|
|
63 |
|
static teken_state_t teken_state_init; |
64 |
|
|
65 |
|
/* |
66 |
|
* Wrappers for hooks. |
67 |
|
*/ |
68 |
|
|
69 |
|
static inline void |
70 |
240 |
teken_funcs_bell(const teken_t *t) |
71 |
|
{ |
72 |
|
|
73 |
240 |
if (t->t_funcs->tf_bell != NULL) |
74 |
0 |
t->t_funcs->tf_bell(t->t_softc); |
75 |
240 |
} |
76 |
|
|
77 |
|
static inline void |
78 |
5536659 |
teken_funcs_cursor(const teken_t *t) |
79 |
|
{ |
80 |
|
|
81 |
5536659 |
teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row); |
82 |
5536659 |
teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col); |
83 |
|
|
84 |
5536659 |
teken_assert(t->t_funcs->tf_cursor != NULL); |
85 |
5536659 |
t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor); |
86 |
5536659 |
} |
87 |
|
|
88 |
|
static inline void |
89 |
5011171 |
teken_funcs_putchar(const teken_t *t, const teken_pos_t *p, teken_char_t c, |
90 |
|
const teken_attr_t *a) |
91 |
|
{ |
92 |
|
|
93 |
5011171 |
teken_assert(p->tp_row < t->t_winsize.tp_row); |
94 |
5011171 |
teken_assert(p->tp_col < t->t_winsize.tp_col); |
95 |
|
|
96 |
5011171 |
teken_assert(t->t_funcs->tf_putchar != NULL); |
97 |
5011171 |
t->t_funcs->tf_putchar(t->t_softc, p, c, a); |
98 |
5011171 |
} |
99 |
|
|
100 |
|
static inline void |
101 |
71998 |
teken_funcs_fill(const teken_t *t, const teken_rect_t *r, |
102 |
|
const teken_char_t c, const teken_attr_t *a) |
103 |
|
{ |
104 |
|
|
105 |
71998 |
teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row); |
106 |
71998 |
teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row); |
107 |
71998 |
teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col); |
108 |
71998 |
teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col); |
109 |
|
|
110 |
71998 |
teken_assert(t->t_funcs->tf_fill != NULL); |
111 |
71998 |
t->t_funcs->tf_fill(t->t_softc, r, c, a); |
112 |
71998 |
} |
113 |
|
|
114 |
|
static inline void |
115 |
69941 |
teken_funcs_copy(const teken_t *t, const teken_rect_t *r, const teken_pos_t *p) |
116 |
|
{ |
117 |
|
|
118 |
69941 |
teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row); |
119 |
69941 |
teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row); |
120 |
69941 |
teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col); |
121 |
69941 |
teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col); |
122 |
69941 |
teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row); |
123 |
69941 |
teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col); |
124 |
|
|
125 |
69941 |
teken_assert(t->t_funcs->tf_copy != NULL); |
126 |
69941 |
t->t_funcs->tf_copy(t->t_softc, r, p); |
127 |
69941 |
} |
128 |
|
|
129 |
|
static inline void |
130 |
158750 |
teken_funcs_pre_input(const teken_t *t) |
131 |
|
{ |
132 |
|
|
133 |
158750 |
if (t->t_funcs->tf_pre_input != NULL) |
134 |
0 |
t->t_funcs->tf_pre_input(t->t_softc); |
135 |
158750 |
} |
136 |
|
|
137 |
|
static inline void |
138 |
158749 |
teken_funcs_post_input(const teken_t *t) |
139 |
|
{ |
140 |
|
|
141 |
158749 |
if (t->t_funcs->tf_post_input != NULL) |
142 |
0 |
t->t_funcs->tf_post_input(t->t_softc); |
143 |
158749 |
} |
144 |
|
|
145 |
|
static inline void |
146 |
5400 |
teken_funcs_param(const teken_t *t, int cmd, unsigned int value) |
147 |
|
{ |
148 |
|
|
149 |
5400 |
teken_assert(t->t_funcs->tf_param != NULL); |
150 |
5400 |
t->t_funcs->tf_param(t->t_softc, cmd, value); |
151 |
5400 |
} |
152 |
|
|
153 |
|
static inline void |
154 |
640 |
teken_funcs_respond(const teken_t *t, const void *buf, size_t len) |
155 |
|
{ |
156 |
|
|
157 |
640 |
teken_assert(t->t_funcs->tf_respond != NULL); |
158 |
640 |
t->t_funcs->tf_respond(t->t_softc, buf, len); |
159 |
640 |
} |
160 |
|
|
161 |
|
#include "teken_subr.h" |
162 |
|
#include "teken_subr_compat.h" |
163 |
|
|
164 |
|
/* |
165 |
|
* Programming interface. |
166 |
|
*/ |
167 |
|
|
168 |
|
void |
169 |
2240 |
teken_init(teken_t *t, const teken_funcs_t *tf, void *softc) |
170 |
|
{ |
171 |
2240 |
teken_pos_t tp = { .tp_row = 24, .tp_col = 80 }; |
172 |
|
|
173 |
2240 |
t->t_funcs = tf; |
174 |
2240 |
t->t_softc = softc; |
175 |
|
|
176 |
2240 |
t->t_nextstate = teken_state_init; |
177 |
2240 |
t->t_stateflags = 0; |
178 |
2240 |
t->t_utf8_left = 0; |
179 |
|
|
180 |
2240 |
t->t_defattr.ta_format = 0; |
181 |
2240 |
t->t_defattr.ta_fgcolor = TC_WHITE; |
182 |
2240 |
t->t_defattr.ta_bgcolor = TC_BLACK; |
183 |
2240 |
teken_subr_do_reset(t); |
184 |
|
|
185 |
2240 |
teken_set_winsize(t, &tp); |
186 |
2240 |
} |
187 |
|
|
188 |
|
static void |
189 |
7352580 |
teken_input_char(teken_t *t, teken_char_t c) |
190 |
|
{ |
191 |
|
|
192 |
|
/* |
193 |
|
* There is no support for DCS and OSC. Just discard strings |
194 |
|
* until we receive characters that may indicate string |
195 |
|
* termination. |
196 |
|
*/ |
197 |
7352580 |
if (t->t_stateflags & TS_INSTRING) { |
198 |
1760 |
switch (c) { |
199 |
|
case '\x1B': |
200 |
160 |
t->t_stateflags &= ~TS_INSTRING; |
201 |
160 |
break; |
202 |
|
case '\a': |
203 |
0 |
t->t_stateflags &= ~TS_INSTRING; |
204 |
0 |
return; |
205 |
|
default: |
206 |
1600 |
return; |
207 |
|
} |
208 |
160 |
} |
209 |
|
|
210 |
7350980 |
switch (c) { |
211 |
|
case '\0': |
212 |
0 |
break; |
213 |
|
case '\a': |
214 |
240 |
teken_subr_bell(t); |
215 |
240 |
break; |
216 |
|
case '\b': |
217 |
35868 |
teken_subr_backspace(t); |
218 |
35868 |
break; |
219 |
|
case '\n': |
220 |
|
case '\x0B': |
221 |
72464 |
teken_subr_newline(t); |
222 |
72464 |
break; |
223 |
|
case '\x0C': |
224 |
320 |
teken_subr_newpage(t); |
225 |
320 |
break; |
226 |
|
case '\x0E': |
227 |
240 |
if (t->t_stateflags & TS_CONS25) |
228 |
80 |
t->t_nextstate(t, c); |
229 |
|
else |
230 |
160 |
t->t_curscs = 1; |
231 |
240 |
break; |
232 |
|
case '\x0F': |
233 |
3600 |
if (t->t_stateflags & TS_CONS25) |
234 |
80 |
t->t_nextstate(t, c); |
235 |
|
else |
236 |
3520 |
t->t_curscs = 0; |
237 |
3600 |
break; |
238 |
|
case '\r': |
239 |
89561 |
teken_subr_carriage_return(t); |
240 |
89561 |
break; |
241 |
|
case '\t': |
242 |
6080 |
teken_subr_horizontal_tab(t); |
243 |
6080 |
break; |
244 |
|
default: |
245 |
7142607 |
t->t_nextstate(t, c); |
246 |
7142607 |
break; |
247 |
|
} |
248 |
|
|
249 |
|
/* Post-processing assertions. */ |
250 |
7350980 |
teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin); |
251 |
7350980 |
teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end); |
252 |
7350980 |
teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row); |
253 |
7350980 |
teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col); |
254 |
7350980 |
teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row); |
255 |
7350980 |
teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col); |
256 |
7350980 |
teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row); |
257 |
7350980 |
teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end); |
258 |
|
/* Origin region has to be window size or the same as scrollreg. */ |
259 |
7350980 |
teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin && |
260 |
|
t->t_originreg.ts_end == t->t_scrollreg.ts_end) || |
261 |
|
(t->t_originreg.ts_begin == 0 && |
262 |
|
t->t_originreg.ts_end == t->t_winsize.tp_row)); |
263 |
7352496 |
} |
264 |
|
|
265 |
|
static void |
266 |
7353783 |
teken_input_byte(teken_t *t, unsigned char c) |
267 |
|
{ |
268 |
|
|
269 |
|
/* |
270 |
|
* UTF-8 handling. |
271 |
|
*/ |
272 |
7353783 |
if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) { |
273 |
|
/* One-byte sequence. */ |
274 |
7352103 |
t->t_utf8_left = 0; |
275 |
7352103 |
teken_input_char(t, c); |
276 |
7353783 |
} else if ((c & 0xe0) == 0xc0) { |
277 |
|
/* Two-byte sequence. */ |
278 |
80 |
t->t_utf8_left = 1; |
279 |
80 |
t->t_utf8_partial = c & 0x1f; |
280 |
1680 |
} else if ((c & 0xf0) == 0xe0) { |
281 |
|
/* Three-byte sequence. */ |
282 |
80 |
t->t_utf8_left = 2; |
283 |
80 |
t->t_utf8_partial = c & 0x0f; |
284 |
1600 |
} else if ((c & 0xf8) == 0xf0) { |
285 |
|
/* Four-byte sequence. */ |
286 |
320 |
t->t_utf8_left = 3; |
287 |
320 |
t->t_utf8_partial = c & 0x07; |
288 |
1520 |
} else if ((c & 0xc0) == 0x80) { |
289 |
1200 |
if (t->t_utf8_left == 0) |
290 |
0 |
return; |
291 |
1200 |
t->t_utf8_left--; |
292 |
1200 |
t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f); |
293 |
1200 |
if (t->t_utf8_left == 0) { |
294 |
|
teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial); |
295 |
480 |
teken_input_char(t, t->t_utf8_partial); |
296 |
480 |
} |
297 |
1200 |
} |
298 |
7353783 |
} |
299 |
|
|
300 |
|
void |
301 |
158750 |
teken_input(teken_t *t, const void *buf, size_t len) |
302 |
|
{ |
303 |
158750 |
const char *c = buf; |
304 |
|
|
305 |
158750 |
teken_funcs_pre_input(t); |
306 |
7512548 |
while (len-- > 0) |
307 |
7353798 |
teken_input_byte(t, *c++); |
308 |
158750 |
teken_funcs_post_input(t); |
309 |
158750 |
} |
310 |
|
|
311 |
|
const teken_pos_t * |
312 |
6560 |
teken_get_cursor(const teken_t *t) |
313 |
|
{ |
314 |
|
|
315 |
6560 |
return (&t->t_cursor); |
316 |
|
} |
317 |
|
|
318 |
|
void |
319 |
2240 |
teken_set_cursor(teken_t *t, const teken_pos_t *p) |
320 |
|
{ |
321 |
|
|
322 |
|
/* XXX: bounds checking with originreg! */ |
323 |
2240 |
teken_assert(p->tp_row < t->t_winsize.tp_row); |
324 |
2240 |
teken_assert(p->tp_col < t->t_winsize.tp_col); |
325 |
|
|
326 |
2240 |
t->t_cursor = *p; |
327 |
2240 |
} |
328 |
|
|
329 |
|
const teken_attr_t * |
330 |
2240 |
teken_get_curattr(const teken_t *t) |
331 |
|
{ |
332 |
|
|
333 |
2240 |
return (&t->t_curattr); |
334 |
|
} |
335 |
|
|
336 |
|
void |
337 |
2240 |
teken_set_curattr(teken_t *t, const teken_attr_t *a) |
338 |
|
{ |
339 |
|
|
340 |
2240 |
t->t_curattr = *a; |
341 |
2240 |
} |
342 |
|
|
343 |
|
const teken_attr_t * |
344 |
2240 |
teken_get_defattr(const teken_t *t) |
345 |
|
{ |
346 |
|
|
347 |
2240 |
return (&t->t_defattr); |
348 |
|
} |
349 |
|
|
350 |
|
void |
351 |
2240 |
teken_set_defattr(teken_t *t, const teken_attr_t *a) |
352 |
|
{ |
353 |
|
|
354 |
2240 |
t->t_curattr = t->t_saved_curattr = t->t_defattr = *a; |
355 |
2240 |
} |
356 |
|
|
357 |
|
const teken_pos_t * |
358 |
2240 |
teken_get_winsize(const teken_t *t) |
359 |
|
{ |
360 |
|
|
361 |
2240 |
return (&t->t_winsize); |
362 |
|
} |
363 |
|
|
364 |
|
static void |
365 |
6240 |
teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new) |
366 |
|
{ |
367 |
|
const teken_pos_t *cur; |
368 |
|
|
369 |
6240 |
cur = &t->t_winsize; |
370 |
|
|
371 |
6240 |
if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col) |
372 |
3000 |
return; |
373 |
3240 |
if (t->t_cursor.tp_row >= new->tp_row) |
374 |
0 |
t->t_cursor.tp_row = new->tp_row - 1; |
375 |
3240 |
if (t->t_cursor.tp_col >= new->tp_col) |
376 |
160 |
t->t_cursor.tp_col = new->tp_col - 1; |
377 |
6240 |
} |
378 |
|
|
379 |
|
void |
380 |
6240 |
teken_set_winsize(teken_t *t, const teken_pos_t *p) |
381 |
|
{ |
382 |
|
|
383 |
6240 |
teken_trim_cursor_pos(t, p); |
384 |
6240 |
t->t_winsize = *p; |
385 |
6240 |
teken_subr_do_reset(t); |
386 |
6240 |
} |
387 |
|
|
388 |
|
void |
389 |
0 |
teken_set_winsize_noreset(teken_t *t, const teken_pos_t *p) |
390 |
|
{ |
391 |
|
|
392 |
0 |
teken_trim_cursor_pos(t, p); |
393 |
0 |
t->t_winsize = *p; |
394 |
0 |
teken_subr_do_resize(t); |
395 |
0 |
} |
396 |
|
|
397 |
|
void |
398 |
0 |
teken_set_8bit(teken_t *t) |
399 |
|
{ |
400 |
|
|
401 |
0 |
t->t_stateflags |= TS_8BIT; |
402 |
0 |
} |
403 |
|
|
404 |
|
void |
405 |
0 |
teken_set_cons25(teken_t *t) |
406 |
|
{ |
407 |
|
|
408 |
0 |
t->t_stateflags |= TS_CONS25; |
409 |
0 |
} |
410 |
|
|
411 |
|
/* |
412 |
|
* State machine. |
413 |
|
*/ |
414 |
|
|
415 |
|
static void |
416 |
1232596 |
teken_state_switch(teken_t *t, teken_state_t *s) |
417 |
|
{ |
418 |
|
|
419 |
1232596 |
t->t_nextstate = s; |
420 |
1232596 |
t->t_curnum = 0; |
421 |
1232596 |
t->t_stateflags |= TS_FIRSTDIGIT; |
422 |
1232596 |
} |
423 |
|
|
424 |
|
static int |
425 |
1287254 |
teken_state_numbers(teken_t *t, teken_char_t c) |
426 |
|
{ |
427 |
|
|
428 |
1287254 |
teken_assert(t->t_curnum < T_NUMSIZE); |
429 |
|
|
430 |
1287254 |
if (c >= '0' && c <= '9') { |
431 |
762826 |
if (t->t_stateflags & TS_FIRSTDIGIT) { |
432 |
|
/* First digit. */ |
433 |
499116 |
t->t_stateflags &= ~TS_FIRSTDIGIT; |
434 |
499116 |
t->t_nums[t->t_curnum] = c - '0'; |
435 |
762826 |
} else if (t->t_nums[t->t_curnum] < UINT_MAX / 100) { |
436 |
|
/* |
437 |
|
* There is no need to continue parsing input |
438 |
|
* once the value exceeds the size of the |
439 |
|
* terminal. It would only allow for integer |
440 |
|
* overflows when performing arithmetic on the |
441 |
|
* cursor position. |
442 |
|
* |
443 |
|
* Ignore any further digits if the value is |
444 |
|
* already UINT_MAX / 100. |
445 |
|
*/ |
446 |
263709 |
t->t_nums[t->t_curnum] = |
447 |
263709 |
t->t_nums[t->t_curnum] * 10 + c - '0'; |
448 |
263709 |
} |
449 |
762824 |
return (1); |
450 |
524428 |
} else if (c == ';') { |
451 |
150425 |
if (t->t_stateflags & TS_FIRSTDIGIT) |
452 |
1920 |
t->t_nums[t->t_curnum] = 0; |
453 |
|
|
454 |
|
/* Only allow a limited set of arguments. */ |
455 |
150425 |
if (++t->t_curnum == T_NUMSIZE) { |
456 |
80 |
teken_state_switch(t, teken_state_init); |
457 |
80 |
return (1); |
458 |
|
} |
459 |
|
|
460 |
150345 |
t->t_stateflags |= TS_FIRSTDIGIT; |
461 |
150345 |
return (1); |
462 |
|
} else { |
463 |
374003 |
if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) { |
464 |
|
/* Finish off the last empty argument. */ |
465 |
80 |
t->t_nums[t->t_curnum] = 0; |
466 |
80 |
t->t_curnum++; |
467 |
374003 |
} else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) { |
468 |
|
/* Also count the last argument. */ |
469 |
350624 |
t->t_curnum++; |
470 |
350624 |
} |
471 |
|
} |
472 |
|
|
473 |
374003 |
return (0); |
474 |
1287252 |
} |
475 |
|
|
476 |
|
#define k TC_BLACK |
477 |
|
#define b TC_BLUE |
478 |
|
#define y TC_BROWN |
479 |
|
#define c TC_CYAN |
480 |
|
#define g TC_GREEN |
481 |
|
#define m TC_MAGENTA |
482 |
|
#define r TC_RED |
483 |
|
#define w TC_WHITE |
484 |
|
#define K (TC_BLACK | TC_LIGHT) |
485 |
|
#define B (TC_BLUE | TC_LIGHT) |
486 |
|
#define Y (TC_BROWN | TC_LIGHT) |
487 |
|
#define C (TC_CYAN | TC_LIGHT) |
488 |
|
#define G (TC_GREEN | TC_LIGHT) |
489 |
|
#define M (TC_MAGENTA | TC_LIGHT) |
490 |
|
#define R (TC_RED | TC_LIGHT) |
491 |
|
#define W (TC_WHITE | TC_LIGHT) |
492 |
|
|
493 |
|
/** |
494 |
|
* The xterm-256 color map has steps of 0x28 (in the range 0-0xff), except |
495 |
|
* for the first step which is 0x5f. Scale to the range 0-6 by dividing |
496 |
|
* by 0x28 and rounding down. The range of 0-5 cannot represent the |
497 |
|
* larger first step. |
498 |
|
* |
499 |
|
* This table is generated by the follow rules: |
500 |
|
* - if all components are equal, the result is black for (0, 0, 0) and |
501 |
|
* (2, 2, 2), else white; otherwise: |
502 |
|
* - subtract the smallest component from all components |
503 |
|
* - if this gives only one nonzero component, then that is the color |
504 |
|
* - else if one component is 2 or more larger than the other nonzero one, |
505 |
|
* then that component gives the color |
506 |
|
* - else there are 2 nonzero components. The color is that of a small |
507 |
|
* equal mixture of these components (cyan, yellow or magenta). E.g., |
508 |
|
* (0, 5, 6) (Turquoise2) is a much purer cyan than (0, 2, 3) |
509 |
|
* (DeepSkyBlue4), but we map both to cyan since we can't represent |
510 |
|
* delicate shades of either blue or cyan and blue would be worse. |
511 |
|
* Here it is important that components of 1 never occur. Blue would |
512 |
|
* be twice as large as green in (0, 1, 2). |
513 |
|
*/ |
514 |
|
static const teken_color_t teken_256to8tab[] = { |
515 |
|
/* xterm normal colors: */ |
516 |
|
k, r, g, y, b, m, c, w, |
517 |
|
|
518 |
|
/* xterm bright colors: */ |
519 |
|
k, r, g, y, b, m, c, w, |
520 |
|
|
521 |
|
/* Red0 submap. */ |
522 |
|
k, b, b, b, b, b, |
523 |
|
g, c, c, b, b, b, |
524 |
|
g, c, c, c, b, b, |
525 |
|
g, g, c, c, c, b, |
526 |
|
g, g, g, c, c, c, |
527 |
|
g, g, g, g, c, c, |
528 |
|
|
529 |
|
/* Red2 submap. */ |
530 |
|
r, m, m, b, b, b, |
531 |
|
y, k, b, b, b, b, |
532 |
|
y, g, c, c, b, b, |
533 |
|
g, g, c, c, c, b, |
534 |
|
g, g, g, c, c, c, |
535 |
|
g, g, g, g, c, c, |
536 |
|
|
537 |
|
/* Red3 submap. */ |
538 |
|
r, m, m, m, b, b, |
539 |
|
y, r, m, m, b, b, |
540 |
|
y, y, w, b, b, b, |
541 |
|
y, y, g, c, c, b, |
542 |
|
g, g, g, c, c, c, |
543 |
|
g, g, g, g, c, c, |
544 |
|
|
545 |
|
/* Red4 submap. */ |
546 |
|
r, r, m, m, m, b, |
547 |
|
r, r, m, m, m, b, |
548 |
|
y, y, r, m, m, b, |
549 |
|
y, y, y, w, b, b, |
550 |
|
y, y, y, g, c, c, |
551 |
|
g, g, g, g, c, c, |
552 |
|
|
553 |
|
/* Red5 submap. */ |
554 |
|
r, r, r, m, m, m, |
555 |
|
r, r, r, m, m, m, |
556 |
|
r, r, r, m, m, m, |
557 |
|
y, y, y, r, m, m, |
558 |
|
y, y, y, y, w, b, |
559 |
|
y, y, y, y, g, c, |
560 |
|
|
561 |
|
/* Red6 submap. */ |
562 |
|
r, r, r, r, m, m, |
563 |
|
r, r, r, r, m, m, |
564 |
|
r, r, r, r, m, m, |
565 |
|
r, r, r, r, m, m, |
566 |
|
y, y, y, y, r, m, |
567 |
|
y, y, y, y, y, w, |
568 |
|
|
569 |
|
/* Grey submap. */ |
570 |
|
k, k, k, k, k, k, |
571 |
|
k, k, k, k, k, k, |
572 |
|
w, w, w, w, w, w, |
573 |
|
w, w, w, w, w, w, |
574 |
|
}; |
575 |
|
|
576 |
|
/* |
577 |
|
* This table is generated from the previous one by setting TC_LIGHT for |
578 |
|
* entries whose luminosity in the xterm256 color map is 60% or larger. |
579 |
|
* Thus the previous table is currently not really needed. It will be |
580 |
|
* used for different fine tuning of the tables. |
581 |
|
*/ |
582 |
|
static const teken_color_t teken_256to16tab[] = { |
583 |
|
/* xterm normal colors: */ |
584 |
|
k, r, g, y, b, m, c, w, |
585 |
|
|
586 |
|
/* xterm bright colors: */ |
587 |
|
K, R, G, Y, B, M, C, W, |
588 |
|
|
589 |
|
/* Red0 submap. */ |
590 |
|
k, b, b, b, b, b, |
591 |
|
g, c, c, b, b, b, |
592 |
|
g, c, c, c, b, b, |
593 |
|
g, g, c, c, c, b, |
594 |
|
g, g, g, c, c, c, |
595 |
|
g, g, g, g, c, c, |
596 |
|
|
597 |
|
/* Red2 submap. */ |
598 |
|
r, m, m, b, b, b, |
599 |
|
y, K, b, b, B, B, |
600 |
|
y, g, c, c, B, B, |
601 |
|
g, g, c, c, C, B, |
602 |
|
g, G, G, C, C, C, |
603 |
|
g, G, G, G, C, C, |
604 |
|
|
605 |
|
/* Red3 submap. */ |
606 |
|
r, m, m, m, b, b, |
607 |
|
y, r, m, m, B, B, |
608 |
|
y, y, w, B, B, B, |
609 |
|
y, y, G, C, C, B, |
610 |
|
g, G, G, C, C, C, |
611 |
|
g, G, G, G, C, C, |
612 |
|
|
613 |
|
/* Red4 submap. */ |
614 |
|
r, r, m, m, m, b, |
615 |
|
r, r, m, m, M, B, |
616 |
|
y, y, R, M, M, B, |
617 |
|
y, y, Y, W, B, B, |
618 |
|
y, Y, Y, G, C, C, |
619 |
|
g, G, G, G, C, C, |
620 |
|
|
621 |
|
/* Red5 submap. */ |
622 |
|
r, r, r, m, m, m, |
623 |
|
r, R, R, M, M, M, |
624 |
|
r, R, R, M, M, M, |
625 |
|
y, Y, Y, R, M, M, |
626 |
|
y, Y, Y, Y, W, B, |
627 |
|
y, Y, Y, Y, G, C, |
628 |
|
|
629 |
|
/* Red6 submap. */ |
630 |
|
r, r, r, r, m, m, |
631 |
|
r, R, R, R, M, M, |
632 |
|
r, R, R, R, M, M, |
633 |
|
r, R, R, R, M, M, |
634 |
|
y, Y, Y, Y, R, M, |
635 |
|
y, Y, Y, Y, Y, W, |
636 |
|
|
637 |
|
/* Grey submap. */ |
638 |
|
k, k, k, k, k, k, |
639 |
|
K, K, K, K, K, K, |
640 |
|
w, w, w, w, w, w, |
641 |
|
W, W, W, W, W, W, |
642 |
|
}; |
643 |
|
|
644 |
|
#undef k |
645 |
|
#undef b |
646 |
|
#undef y |
647 |
|
#undef c |
648 |
|
#undef g |
649 |
|
#undef m |
650 |
|
#undef r |
651 |
|
#undef w |
652 |
|
#undef K |
653 |
|
#undef B |
654 |
|
#undef Y |
655 |
|
#undef C |
656 |
|
#undef G |
657 |
|
#undef M |
658 |
|
#undef R |
659 |
|
#undef W |
660 |
|
|
661 |
|
teken_color_t |
662 |
6720 |
teken_256to8(teken_color_t c) |
663 |
|
{ |
664 |
|
|
665 |
6720 |
return (teken_256to8tab[c % 256]); |
666 |
|
} |
667 |
|
|
668 |
|
teken_color_t |
669 |
2240 |
teken_256to16(teken_color_t c) |
670 |
|
{ |
671 |
|
|
672 |
2240 |
return (teken_256to16tab[c % 256]); |
673 |
|
} |
674 |
|
|
675 |
|
static const char * const special_strings_cons25[] = { |
676 |
|
[TKEY_UP] = "\x1B[A", [TKEY_DOWN] = "\x1B[B", |
677 |
|
[TKEY_LEFT] = "\x1B[D", [TKEY_RIGHT] = "\x1B[C", |
678 |
|
|
679 |
|
[TKEY_HOME] = "\x1B[H", [TKEY_END] = "\x1B[F", |
680 |
|
[TKEY_INSERT] = "\x1B[L", [TKEY_DELETE] = "\x7F", |
681 |
|
[TKEY_PAGE_UP] = "\x1B[I", [TKEY_PAGE_DOWN] = "\x1B[G", |
682 |
|
|
683 |
|
[TKEY_F1] = "\x1B[M", [TKEY_F2] = "\x1B[N", |
684 |
|
[TKEY_F3] = "\x1B[O", [TKEY_F4] = "\x1B[P", |
685 |
|
[TKEY_F5] = "\x1B[Q", [TKEY_F6] = "\x1B[R", |
686 |
|
[TKEY_F7] = "\x1B[S", [TKEY_F8] = "\x1B[T", |
687 |
|
[TKEY_F9] = "\x1B[U", [TKEY_F10] = "\x1B[V", |
688 |
|
[TKEY_F11] = "\x1B[W", [TKEY_F12] = "\x1B[X", |
689 |
|
}; |
690 |
|
|
691 |
|
static const char * const special_strings_ckeys[] = { |
692 |
|
[TKEY_UP] = "\x1BOA", [TKEY_DOWN] = "\x1BOB", |
693 |
|
[TKEY_LEFT] = "\x1BOD", [TKEY_RIGHT] = "\x1BOC", |
694 |
|
|
695 |
|
[TKEY_HOME] = "\x1BOH", [TKEY_END] = "\x1BOF", |
696 |
|
}; |
697 |
|
|
698 |
|
static const char * const special_strings_normal[] = { |
699 |
|
[TKEY_UP] = "\x1B[A", [TKEY_DOWN] = "\x1B[B", |
700 |
|
[TKEY_LEFT] = "\x1B[D", [TKEY_RIGHT] = "\x1B[C", |
701 |
|
|
702 |
|
[TKEY_HOME] = "\x1B[H", [TKEY_END] = "\x1B[F", |
703 |
|
[TKEY_INSERT] = "\x1B[2~", [TKEY_DELETE] = "\x1B[3~", |
704 |
|
[TKEY_PAGE_UP] = "\x1B[5~", [TKEY_PAGE_DOWN] = "\x1B[6~", |
705 |
|
|
706 |
|
[TKEY_F1] = "\x1BOP", [TKEY_F2] = "\x1BOQ", |
707 |
|
[TKEY_F3] = "\x1BOR", [TKEY_F4] = "\x1BOS", |
708 |
|
[TKEY_F5] = "\x1B[15~", [TKEY_F6] = "\x1B[17~", |
709 |
|
[TKEY_F7] = "\x1B[18~", [TKEY_F8] = "\x1B[19~", |
710 |
|
[TKEY_F9] = "\x1B[20~", [TKEY_F10] = "\x1B[21~", |
711 |
|
[TKEY_F11] = "\x1B[23~", [TKEY_F12] = "\x1B[24~", |
712 |
|
}; |
713 |
|
|
714 |
|
const char * |
715 |
4480 |
teken_get_sequence(const teken_t *t, unsigned int k) |
716 |
|
{ |
717 |
|
|
718 |
|
/* Cons25 mode. */ |
719 |
4480 |
if (t->t_stateflags & TS_CONS25 && |
720 |
0 |
k < sizeof special_strings_cons25 / sizeof(char *)) |
721 |
0 |
return (special_strings_cons25[k]); |
722 |
|
|
723 |
|
/* Cursor keys mode. */ |
724 |
4480 |
if (t->t_stateflags & TS_CURSORKEYS && |
725 |
0 |
k < sizeof special_strings_ckeys / sizeof(char *)) |
726 |
0 |
return (special_strings_ckeys[k]); |
727 |
|
|
728 |
|
/* Default xterm sequences. */ |
729 |
4480 |
if (k < sizeof special_strings_normal / sizeof(char *)) |
730 |
4480 |
return (special_strings_normal[k]); |
731 |
|
|
732 |
0 |
return (NULL); |
733 |
4480 |
} |
734 |
|
|
735 |
|
#include "teken_state.h" |