varnish-cache/bin/varnishtest/vtest2/src/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 240
69
static inline void
70
teken_funcs_bell(const teken_t *t)
71 240
{
72 0
73 240
        if (t->t_funcs->tf_bell != NULL)
74
                t->t_funcs->tf_bell(t->t_softc);
75
}
76 3752752
77
static inline void
78
teken_funcs_cursor(const teken_t *t)
79 3752752
{
80 3752752
81
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
82 3752752
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
83 3752752
84 3752752
        teken_assert(t->t_funcs->tf_cursor != NULL);
85
        t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
86
}
87 3414785
88
static inline void
89
teken_funcs_putchar(const teken_t *t, const teken_pos_t *p, teken_char_t c,
90
    const teken_attr_t *a)
91 3414785
{
92 3414785
93
        teken_assert(p->tp_row < t->t_winsize.tp_row);
94 3414785
        teken_assert(p->tp_col < t->t_winsize.tp_col);
95 3414785
96 3414785
        teken_assert(t->t_funcs->tf_putchar != NULL);
97
        t->t_funcs->tf_putchar(t->t_softc, p, c, a);
98
}
99 44071
100
static inline void
101
teken_funcs_fill(const teken_t *t, const teken_rect_t *r,
102
    const teken_char_t c, const teken_attr_t *a)
103 44071
{
104 44071
105 44071
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
106 44071
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
107
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
108 44071
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
109 44071
110 44071
        teken_assert(t->t_funcs->tf_fill != NULL);
111
        t->t_funcs->tf_fill(t->t_softc, r, c, a);
112
}
113 40188
114
static inline void
115
teken_funcs_copy(const teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
116 40188
{
117 40188
118 40188
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
119 40188
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
120 40188
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
121 40188
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
122
        teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
123 40188
        teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
124 40188
125 40188
        teken_assert(t->t_funcs->tf_copy != NULL);
126
        t->t_funcs->tf_copy(t->t_softc, r, p);
127
}
128 93803
129
static inline void
130
teken_funcs_pre_input(const teken_t *t)
131 93803
{
132 0
133 93803
        if (t->t_funcs->tf_pre_input != NULL)
134
                t->t_funcs->tf_pre_input(t->t_softc);
135
}
136 93800
137
static inline void
138
teken_funcs_post_input(const teken_t *t)
139 93800
{
140 0
141 93800
        if (t->t_funcs->tf_post_input != NULL)
142
                t->t_funcs->tf_post_input(t->t_softc);
143
}
144 3840
145
static inline void
146
teken_funcs_param(const teken_t *t, int cmd, unsigned int value)
147 3840
{
148 3840
149 3840
        teken_assert(t->t_funcs->tf_param != NULL);
150
        t->t_funcs->tf_param(t->t_softc, cmd, value);
151
}
152 320
153
static inline void
154
teken_funcs_respond(const teken_t *t, const void *buf, size_t len)
155 320
{
156 320
157 320
        teken_assert(t->t_funcs->tf_respond != NULL);
158
        t->t_funcs->tf_respond(t->t_softc, buf, len);
159
}
160
161
#include "teken_subr.h"
162
#include "teken_subr_compat.h"
163
164
/*
165
 * Programming interface.
166
 */
167 1920
168
void
169 1920
teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
170
{
171 1920
        teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
172 1920
173
        t->t_funcs = tf;
174 1920
        t->t_softc = softc;
175 1920
176 1920
        t->t_nextstate = teken_state_init;
177
        t->t_stateflags = 0;
178 1920
        t->t_utf8_left = 0;
179 1920
180 1920
        t->t_defattr.ta_format = 0;
181 1920
        t->t_defattr.ta_fgcolor = TC_WHITE;
182
        t->t_defattr.ta_bgcolor = TC_BLACK;
183 1920
        teken_subr_do_reset(t);
184 1920
185
        teken_set_winsize(t, &tp);
186
}
187 4926970
188
static void
189
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 4926970
         * termination.
196 880
         */
197
        if (t->t_stateflags & TS_INSTRING) {
198 80
                switch (c) {
199 80
                case '\x1B':
200
                        t->t_stateflags &= ~TS_INSTRING;
201 0
                        break;
202 0
                case '\a':
203
                        t->t_stateflags &= ~TS_INSTRING;
204 800
                        return;
205
                default:
206 80
                        return;
207
                }
208 4926170
        }
209
210 0
        switch (c) {
211
        case '\0':
212 240
                break;
213 240
        case '\a':
214
                teken_subr_bell(t);
215 20103
                break;
216 20103
        case '\b':
217
                teken_subr_backspace(t);
218
                break;
219 47711
        case '\n':
220 47711
        case '\x0B':
221
                teken_subr_newline(t);
222 160
                break;
223 160
        case '\x0C':
224
                teken_subr_newpage(t);
225 120
                break;
226 40
        case '\x0E':
227
                if (t->t_stateflags & TS_CONS25)
228 80
                        t->t_nextstate(t, c);
229 120
                else
230
                        t->t_curscs = 1;
231 1800
                break;
232 40
        case '\x0F':
233
                if (t->t_stateflags & TS_CONS25)
234 1760
                        t->t_nextstate(t, c);
235 1800
                else
236
                        t->t_curscs = 0;
237 63578
                break;
238 63578
        case '\r':
239
                teken_subr_carriage_return(t);
240 3080
                break;
241 3080
        case '\t':
242
                teken_subr_horizontal_tab(t);
243 4789378
                break;
244 4789378
        default:
245
                t->t_nextstate(t, c);
246
                break;
247
        }
248 4926170
249 4926170
        /* Post-processing assertions. */
250 4926170
        teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
251 4926170
        teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
252 4926170
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
253 4926170
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
254 4926170
        teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
255 4926170
        teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
256
        teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
257 4926170
        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
        teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin &&
260
            t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
261 4926604
            (t->t_originreg.ts_begin == 0 &&
262
            t->t_originreg.ts_end == t->t_winsize.tp_row));
263
}
264 4927525
265
static void
266
teken_input_byte(teken_t *t, unsigned char c)
267
{
268
269
        /*
270 4927525
         * UTF-8 handling.
271
         */
272 4926685
        if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) {
273 4926685
                /* One-byte sequence. */
274 4927525
                t->t_utf8_left = 0;
275
                teken_input_char(t, c);
276 40
        } else if ((c & 0xe0) == 0xc0) {
277 40
                /* Two-byte sequence. */
278 840
                t->t_utf8_left = 1;
279
                t->t_utf8_partial = c & 0x1f;
280 40
        } else if ((c & 0xf0) == 0xe0) {
281 40
                /* Three-byte sequence. */
282 800
                t->t_utf8_left = 2;
283
                t->t_utf8_partial = c & 0x0f;
284 160
        } else if ((c & 0xf8) == 0xf0) {
285 160
                /* Four-byte sequence. */
286 760
                t->t_utf8_left = 3;
287 600
                t->t_utf8_partial = c & 0x07;
288 0
        } else if ((c & 0xc0) == 0x80) {
289 600
                if (t->t_utf8_left == 0)
290 600
                        return;
291 600
                t->t_utf8_left--;
292
                t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
293 240
                if (t->t_utf8_left == 0) {
294 240
                        teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
295 600
                        teken_input_char(t, t->t_utf8_partial);
296 4927525
                }
297
        }
298
}
299 93803
300
void
301 93803
teken_input(teken_t *t, const void *buf, size_t len)
302
{
303 93803
        const char *c = buf;
304 5021239
305 4927436
        teken_funcs_pre_input(t);
306 93803
        while (len-- > 0)
307 93803
                teken_input_byte(t, *c++);
308
        teken_funcs_post_input(t);
309
}
310 4240
311
const teken_pos_t *
312
teken_get_cursor(const teken_t *t)
313 4240
{
314
315
        return (&t->t_cursor);
316
}
317 1920
318
void
319
teken_set_cursor(teken_t *t, const teken_pos_t *p)
320
{
321 1920
322 1920
        /* XXX: bounds checking with originreg! */
323
        teken_assert(p->tp_row < t->t_winsize.tp_row);
324 1920
        teken_assert(p->tp_col < t->t_winsize.tp_col);
325 1920
326
        t->t_cursor = *p;
327
}
328 1920
329
const teken_attr_t *
330
teken_get_curattr(const teken_t *t)
331 1920
{
332
333
        return (&t->t_curattr);
334
}
335 1920
336
void
337
teken_set_curattr(teken_t *t, const teken_attr_t *a)
338 1920
{
339 1920
340
        t->t_curattr = *a;
341
}
342 1920
343
const teken_attr_t *
344
teken_get_defattr(const teken_t *t)
345 1920
{
346
347
        return (&t->t_defattr);
348
}
349 1920
350
void
351
teken_set_defattr(teken_t *t, const teken_attr_t *a)
352 1920
{
353 1920
354
        t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
355
}
356 1920
357
const teken_pos_t *
358
teken_get_winsize(const teken_t *t)
359 1920
{
360
361
        return (&t->t_winsize);
362
}
363 4880
364
static void
365
teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new)
366
{
367 4880
        const teken_pos_t *cur;
368
369 4880
        cur = &t->t_winsize;
370 2440
371 2440
        if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col)
372 0
                return;
373 2440
        if (t->t_cursor.tp_row >= new->tp_row)
374 80
                t->t_cursor.tp_row = new->tp_row - 1;
375 4880
        if (t->t_cursor.tp_col >= new->tp_col)
376
                t->t_cursor.tp_col = new->tp_col - 1;
377
}
378 4880
379
void
380
teken_set_winsize(teken_t *t, const teken_pos_t *p)
381 4880
{
382 4880
383 4880
        teken_trim_cursor_pos(t, p);
384 4880
        t->t_winsize = *p;
385
        teken_subr_do_reset(t);
386
}
387 0
388
void
389
teken_set_winsize_noreset(teken_t *t, const teken_pos_t *p)
390 0
{
391 0
392 0
        teken_trim_cursor_pos(t, p);
393 0
        t->t_winsize = *p;
394
        teken_subr_do_resize(t);
395
}
396 0
397
void
398
teken_set_8bit(teken_t *t)
399 0
{
400 0
401
        t->t_stateflags |= TS_8BIT;
402
}
403 0
404
void
405
teken_set_cons25(teken_t *t)
406 0
{
407 0
408
        t->t_stateflags |= TS_CONS25;
409
}
410
411
/*
412
 * State machine.
413
 */
414 782141
415
static void
416
teken_state_switch(teken_t *t, teken_state_t *s)
417 782141
{
418 782141
419 782141
        t->t_nextstate = s;
420 782141
        t->t_curnum = 0;
421
        t->t_stateflags |= TS_FIRSTDIGIT;
422
}
423 845483
424
static int
425
teken_state_numbers(teken_t *t, teken_char_t c)
426 845483
{
427
428 845483
        teken_assert(t->t_curnum < T_NUMSIZE);
429 500014
430
        if (c >= '0' && c <= '9') {
431 324758
                if (t->t_stateflags & TS_FIRSTDIGIT) {
432 324758
                        /* First digit. */
433 500014
                        t->t_stateflags &= ~TS_FIRSTDIGIT;
434
                        t->t_nums[t->t_curnum] = c - '0';
435
                } 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 175256
                         * already UINT_MAX / 100.
445 175256
                         */
446 175256
                        t->t_nums[t->t_curnum] =
447 500014
                            t->t_nums[t->t_curnum] * 10 + c - '0';
448 345469
                }
449 102494
                return (1);
450 960
        } else if (c == ';') {
451
                if (t->t_stateflags & TS_FIRSTDIGIT)
452
                        t->t_nums[t->t_curnum] = 0;
453 102494
454 40
                /* Only allow a limited set of arguments. */
455 40
                if (++t->t_curnum == T_NUMSIZE) {
456
                        teken_state_switch(t, teken_state_init);
457
                        return (1);
458 102454
                }
459 102454
460
                t->t_stateflags |= TS_FIRSTDIGIT;
461 242975
                return (1);
462
        } else {
463 40
                if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
464 40
                        /* Finish off the last empty argument. */
465 242975
                        t->t_nums[t->t_curnum] = 0;
466
                        t->t_curnum++;
467 223255
                } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
468 223255
                        /* Also count the last argument. */
469
                        t->t_curnum++;
470
                }
471 242975
        }
472 845483
473
        return (0);
474
}
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 5760
661
teken_color_t
662
teken_256to8(teken_color_t c)
663 5760
{
664
665
        return (teken_256to8tab[c % 256]);
666
}
667 1920
668
teken_color_t
669
teken_256to16(teken_color_t c)
670 1920
{
671
672
        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 3840
714
const char *
715
teken_get_sequence(const teken_t *t, unsigned int k)
716
{
717 3840
718 0
        /* Cons25 mode. */
719 0
        if (t->t_stateflags & TS_CONS25 &&
720
            k < sizeof special_strings_cons25 / sizeof(char *))
721
                return (special_strings_cons25[k]);
722 3840
723 0
        /* Cursor keys mode. */
724 0
        if (t->t_stateflags & TS_CURSORKEYS &&
725
            k < sizeof special_strings_ckeys / sizeof(char *))
726
                return (special_strings_ckeys[k]);
727 3840
728 3840
        /* Default xterm sequences. */
729
        if (k < sizeof special_strings_normal / sizeof(char *))
730 0
                return (special_strings_normal[k]);
731 3840
732
        return (NULL);
733
}
734
735
#include "teken_state.h"