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 5606995
teken_funcs_cursor(const teken_t *t)
79
{
80
81 5606995
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
82 5606995
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
83
84 5606995
        teken_assert(t->t_funcs->tf_cursor != NULL);
85 5606995
        t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
86 5606995
}
87
88
static inline void
89 5072712
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 5072712
        teken_assert(p->tp_row < t->t_winsize.tp_row);
94 5072712
        teken_assert(p->tp_col < t->t_winsize.tp_col);
95
96 5072712
        teken_assert(t->t_funcs->tf_putchar != NULL);
97 5072712
        t->t_funcs->tf_putchar(t->t_softc, p, c, a);
98 5072712
}
99
100
static inline void
101 72312
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 72312
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
106 72312
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
107 72312
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
108 72312
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
109
110 72312
        teken_assert(t->t_funcs->tf_fill != NULL);
111 72312
        t->t_funcs->tf_fill(t->t_softc, r, c, a);
112 72312
}
113
114
static inline void
115 70182
teken_funcs_copy(const teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
116
{
117
118 70182
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
119 70182
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
120 70182
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
121 70182
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
122 70182
        teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
123 70182
        teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
124
125 70182
        teken_assert(t->t_funcs->tf_copy != NULL);
126 70182
        t->t_funcs->tf_copy(t->t_softc, r, p);
127 70182
}
128
129
static inline void
130 169972
teken_funcs_pre_input(const teken_t *t)
131
{
132
133 169972
        if (t->t_funcs->tf_pre_input != NULL)
134 0
                t->t_funcs->tf_pre_input(t->t_softc);
135 169972
}
136
137
static inline void
138 169972
teken_funcs_post_input(const teken_t *t)
139
{
140
141 169972
        if (t->t_funcs->tf_post_input != NULL)
142 0
                t->t_funcs->tf_post_input(t->t_softc);
143 169972
}
144
145
static inline void
146 5560
teken_funcs_param(const teken_t *t, int cmd, unsigned int value)
147
{
148
149 5560
        teken_assert(t->t_funcs->tf_param != NULL);
150 5560
        t->t_funcs->tf_param(t->t_softc, cmd, value);
151 5560
}
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 2280
teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
170
{
171 2280
        teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
172
173 2280
        t->t_funcs = tf;
174 2280
        t->t_softc = softc;
175
176 2280
        t->t_nextstate = teken_state_init;
177 2280
        t->t_stateflags = 0;
178 2280
        t->t_utf8_left = 0;
179
180 2280
        t->t_defattr.ta_format = 0;
181 2280
        t->t_defattr.ta_fgcolor = TC_WHITE;
182 2280
        t->t_defattr.ta_bgcolor = TC_BLACK;
183 2280
        teken_subr_do_reset(t);
184
185 2280
        teken_set_winsize(t, &tp);
186 2280
}
187
188
static void
189 7464901
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 7464901
        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 7463301
        switch (c) {
211
        case '\0':
212 0
                break;
213
        case '\a':
214 240
                teken_subr_bell(t);
215 240
                break;
216
        case '\b':
217 36168
                teken_subr_backspace(t);
218 36168
                break;
219
        case '\n':
220
        case '\x0B':
221 72675
                teken_subr_newline(t);
222 72675
                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 90602
                teken_subr_carriage_return(t);
240 90602
                break;
241
        case '\t':
242 6080
                teken_subr_horizontal_tab(t);
243 6080
                break;
244
        default:
245 7253376
                t->t_nextstate(t, c);
246 7253376
                break;
247
        }
248
249
        /* Post-processing assertions. */
250 7463301
        teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
251 7463301
        teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
252 7463301
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
253 7463301
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
254 7463301
        teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
255 7463301
        teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
256 7463301
        teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
257 7463301
        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 7463301
        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 7464713
}
264
265
static void
266 7466156
teken_input_byte(teken_t *t, unsigned char c)
267
{
268
269
        /*
270
         * UTF-8 handling.
271
         */
272 7466156
        if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) {
273
                /* One-byte sequence. */
274 7464476
                t->t_utf8_left = 0;
275 7464476
                teken_input_char(t, c);
276 7466156
        } 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 7466156
}
299
300
void
301 169972
teken_input(teken_t *t, const void *buf, size_t len)
302
{
303 169972
        const char *c = buf;
304
305 169972
        teken_funcs_pre_input(t);
306 7636096
        while (len-- > 0)
307 7466124
                teken_input_byte(t, *c++);
308 169972
        teken_funcs_post_input(t);
309 169972
}
310
311
const teken_pos_t *
312 6640
teken_get_cursor(const teken_t *t)
313
{
314
315 6640
        return (&t->t_cursor);
316
}
317
318
void
319 2280
teken_set_cursor(teken_t *t, const teken_pos_t *p)
320
{
321
322
        /* XXX: bounds checking with originreg! */
323 2280
        teken_assert(p->tp_row < t->t_winsize.tp_row);
324 2280
        teken_assert(p->tp_col < t->t_winsize.tp_col);
325
326 2280
        t->t_cursor = *p;
327 2280
}
328
329
const teken_attr_t *
330 2280
teken_get_curattr(const teken_t *t)
331
{
332
333 2280
        return (&t->t_curattr);
334
}
335
336
void
337 2280
teken_set_curattr(teken_t *t, const teken_attr_t *a)
338
{
339
340 2280
        t->t_curattr = *a;
341 2280
}
342
343
const teken_attr_t *
344 2280
teken_get_defattr(const teken_t *t)
345
{
346
347 2280
        return (&t->t_defattr);
348
}
349
350
void
351 2280
teken_set_defattr(teken_t *t, const teken_attr_t *a)
352
{
353
354 2280
        t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
355 2280
}
356
357
const teken_pos_t *
358 2280
teken_get_winsize(const teken_t *t)
359
{
360
361 2280
        return (&t->t_winsize);
362
}
363
364
static void
365 6320
teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new)
366
{
367
        const teken_pos_t *cur;
368
369 6320
        cur = &t->t_winsize;
370
371 6320
        if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col)
372 3040
                return;
373 3280
        if (t->t_cursor.tp_row >= new->tp_row)
374 0
                t->t_cursor.tp_row = new->tp_row - 1;
375 3280
        if (t->t_cursor.tp_col >= new->tp_col)
376 160
                t->t_cursor.tp_col = new->tp_col - 1;
377 6320
}
378
379
void
380 6320
teken_set_winsize(teken_t *t, const teken_pos_t *p)
381
{
382
383 6320
        teken_trim_cursor_pos(t, p);
384 6320
        t->t_winsize = *p;
385 6320
        teken_subr_do_reset(t);
386 6320
}
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 1257577
teken_state_switch(teken_t *t, teken_state_t *s)
417
{
418
419 1257577
        t->t_nextstate = s;
420 1257577
        t->t_curnum = 0;
421 1257577
        t->t_stateflags |= TS_FIRSTDIGIT;
422 1257577
}
423
424
static int
425 1319938
teken_state_numbers(teken_t *t, teken_char_t c)
426
{
427
428 1319938
        teken_assert(t->t_curnum < T_NUMSIZE);
429
430 1319938
        if (c >= '0' && c <= '9') {
431 782459
                if (t->t_stateflags & TS_FIRSTDIGIT) {
432
                        /* First digit. */
433 511392
                        t->t_stateflags &= ~TS_FIRSTDIGIT;
434 511392
                        t->t_nums[t->t_curnum] = c - '0';
435 782459
                } 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 271063
                        t->t_nums[t->t_curnum] =
447 271063
                            t->t_nums[t->t_curnum] * 10 + c - '0';
448 271063
                }
449 782455
                return (1);
450 537479
        } else if (c == ';') {
451 155059
                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 155059
                if (++t->t_curnum == T_NUMSIZE) {
456 80
                        teken_state_switch(t, teken_state_init);
457 80
                        return (1);
458
                }
459
460 154979
                t->t_stateflags |= TS_FIRSTDIGIT;
461 154979
                return (1);
462
        } else {
463 382420
                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 382420
                } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
468
                        /* Also count the last argument. */
469 358271
                        t->t_curnum++;
470 358271
                }
471
        }
472
473 382420
        return (0);
474 1319934
}
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 6840
teken_256to8(teken_color_t c)
663
{
664
665 6840
        return (teken_256to8tab[c % 256]);
666
}
667
668
teken_color_t
669 2280
teken_256to16(teken_color_t c)
670
{
671
672 2280
        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 4560
teken_get_sequence(const teken_t *t, unsigned int k)
716
{
717
718
        /* Cons25 mode. */
719 4560
        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 4560
        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 4560
        if (k < sizeof special_strings_normal / sizeof(char *))
730 4560
                return (special_strings_normal[k]);
731
732 0
        return (NULL);
733 4560
}
734
735
#include "teken_state.h"