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