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