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 30
teken_funcs_bell(const teken_t *t)
69
{
70
71 30
        if (t->t_funcs->tf_bell != NULL)
72 0
                t->t_funcs->tf_bell(t->t_softc);
73 30
}
74
75
static inline void
76 697087
teken_funcs_cursor(const teken_t *t)
77
{
78
79 697087
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
80 697087
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
81
82 697087
        teken_assert(t->t_funcs->tf_cursor != NULL);
83 697087
        t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
84 697087
}
85
86
static inline void
87 630330
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 630330
        teken_assert(p->tp_row < t->t_winsize.tp_row);
92 630330
        teken_assert(p->tp_col < t->t_winsize.tp_col);
93
94 630330
        teken_assert(t->t_funcs->tf_putchar != NULL);
95 630330
        t->t_funcs->tf_putchar(t->t_softc, p, c, a);
96 630330
}
97
98
static inline void
99 9045
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 9045
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
104 9045
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
105 9045
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
106 9045
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
107
108 9045
        teken_assert(t->t_funcs->tf_fill != NULL);
109 9045
        t->t_funcs->tf_fill(t->t_softc, r, c, a);
110 9045
}
111
112
static inline void
113 8485
teken_funcs_copy(const teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
114
{
115
116 8485
        teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
117 8485
        teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
118 8485
        teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
119 8485
        teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
120 8485
        teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
121 8485
        teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
122
123 8485
        teken_assert(t->t_funcs->tf_copy != NULL);
124 8485
        t->t_funcs->tf_copy(t->t_softc, r, p);
125 8485
}
126
127
static inline void
128 21884
teken_funcs_pre_input(const teken_t *t)
129
{
130
131 21884
        if (t->t_funcs->tf_pre_input != NULL)
132 0
                t->t_funcs->tf_pre_input(t->t_softc);
133 21884
}
134
135
static inline void
136 21884
teken_funcs_post_input(const teken_t *t)
137
{
138
139 21884
        if (t->t_funcs->tf_post_input != NULL)
140 0
                t->t_funcs->tf_post_input(t->t_softc);
141 21884
}
142
143
static inline void
144 695
teken_funcs_param(const teken_t *t, int cmd, unsigned int value)
145
{
146
147 695
        teken_assert(t->t_funcs->tf_param != NULL);
148 695
        t->t_funcs->tf_param(t->t_softc, cmd, value);
149 695
}
150
151
static inline void
152 80
teken_funcs_respond(const teken_t *t, const void *buf, size_t len)
153
{
154
155 80
        teken_assert(t->t_funcs->tf_respond != NULL);
156 80
        t->t_funcs->tf_respond(t->t_softc, buf, len);
157 80
}
158
159
#include "teken_subr.h"
160
#include "teken_subr_compat.h"
161
162
/*
163
 * Programming interface.
164
 */
165
166
void
167 295
teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
168
{
169 295
        teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
170
171 295
        t->t_funcs = tf;
172 295
        t->t_softc = softc;
173
174 295
        t->t_nextstate = teken_state_init;
175 295
        t->t_stateflags = 0;
176 295
        t->t_utf8_left = 0;
177
178 295
        t->t_defattr.ta_format = 0;
179 295
        t->t_defattr.ta_fgcolor = TC_WHITE;
180 295
        t->t_defattr.ta_bgcolor = TC_BLACK;
181 295
        teken_subr_do_reset(t);
182
183 295
        teken_set_winsize(t, &tp);
184 295
}
185
186
static void
187 930692
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 930692
        if (t->t_stateflags & TS_INSTRING) {
196 220
                switch (c) {
197
                case '\x1B':
198 20
                        t->t_stateflags &= ~TS_INSTRING;
199 20
                        break;
200
                case '\a':
201 0
                        t->t_stateflags &= ~TS_INSTRING;
202 0
                        return;
203
                default:
204 200
                        return;
205
                }
206 20
        }
207
208 930492
        switch (c) {
209
        case '\0':
210 0
                break;
211
        case '\a':
212 30
                teken_subr_bell(t);
213 30
                break;
214
        case '\b':
215 4110
                teken_subr_backspace(t);
216 4110
                break;
217
        case '\n':
218
        case '\x0B':
219 9265
                teken_subr_newline(t);
220 9265
                break;
221
        case '\x0C':
222 40
                teken_subr_newpage(t);
223 40
                break;
224
        case '\x0E':
225 30
                if (t->t_stateflags & TS_CONS25)
226 10
                        t->t_nextstate(t, c);
227
                else
228 20
                        t->t_curscs = 1;
229 30
                break;
230
        case '\x0F':
231 450
                if (t->t_stateflags & TS_CONS25)
232 10
                        t->t_nextstate(t, c);
233
                else
234 440
                        t->t_curscs = 0;
235 450
                break;
236
        case '\r':
237 11536
                teken_subr_carriage_return(t);
238 11536
                break;
239
        case '\t':
240 760
                teken_subr_horizontal_tab(t);
241 760
                break;
242
        default:
243 904271
                t->t_nextstate(t, c);
244 904271
                break;
245
        }
246
247
        /* Post-processing assertions. */
248 930492
        teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
249 930492
        teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
250 930492
        teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
251 930492
        teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
252 930492
        teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
253 930492
        teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
254 930492
        teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
255 930492
        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 930492
        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 930654
}
262
263
static void
264 930837
teken_input_byte(teken_t *t, unsigned char c)
265
{
266
267
        /*
268
         * UTF-8 handling.
269
         */
270 930837
        if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) {
271
                /* One-byte sequence. */
272 930627
                t->t_utf8_left = 0;
273 930627
                teken_input_char(t, c);
274 930837
        } else if ((c & 0xe0) == 0xc0) {
275
                /* Two-byte sequence. */
276 10
                t->t_utf8_left = 1;
277 10
                t->t_utf8_partial = c & 0x1f;
278 210
        } else if ((c & 0xf0) == 0xe0) {
279
                /* Three-byte sequence. */
280 10
                t->t_utf8_left = 2;
281 10
                t->t_utf8_partial = c & 0x0f;
282 200
        } else if ((c & 0xf8) == 0xf0) {
283
                /* Four-byte sequence. */
284 40
                t->t_utf8_left = 3;
285 40
                t->t_utf8_partial = c & 0x07;
286 190
        } else if ((c & 0xc0) == 0x80) {
287 150
                if (t->t_utf8_left == 0)
288 0
                        return;
289 150
                t->t_utf8_left--;
290 150
                t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
291 150
                if (t->t_utf8_left == 0) {
292
                        teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
293 60
                        teken_input_char(t, t->t_utf8_partial);
294 60
                }
295 150
        }
296 930837
}
297
298
void
299 21884
teken_input(teken_t *t, const void *buf, size_t len)
300
{
301 21884
        const char *c = buf;
302
303 21884
        teken_funcs_pre_input(t);
304 952730
        while (len-- > 0)
305 930846
                teken_input_byte(t, *c++);
306 21884
        teken_funcs_post_input(t);
307 21884
}
308
309
const teken_pos_t *
310 830
teken_get_cursor(const teken_t *t)
311
{
312
313 830
        return (&t->t_cursor);
314
}
315
316
void
317 295
teken_set_cursor(teken_t *t, const teken_pos_t *p)
318
{
319
320
        /* XXX: bounds checking with originreg! */
321 295
        teken_assert(p->tp_row < t->t_winsize.tp_row);
322 295
        teken_assert(p->tp_col < t->t_winsize.tp_col);
323
324 295
        t->t_cursor = *p;
325 295
}
326
327
const teken_attr_t *
328 295
teken_get_curattr(const teken_t *t)
329
{
330
331 295
        return (&t->t_curattr);
332
}
333
334
void
335 295
teken_set_curattr(teken_t *t, const teken_attr_t *a)
336
{
337
338 295
        t->t_curattr = *a;
339 295
}
340
341
const teken_attr_t *
342 295
teken_get_defattr(const teken_t *t)
343
{
344
345 295
        return (&t->t_defattr);
346
}
347
348
void
349 295
teken_set_defattr(teken_t *t, const teken_attr_t *a)
350
{
351
352 295
        t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
353 295
}
354
355
const teken_pos_t *
356 295
teken_get_winsize(const teken_t *t)
357
{
358
359 295
        return (&t->t_winsize);
360
}
361
362
static void
363 815
teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new)
364
{
365
        const teken_pos_t *cur;
366
367 815
        cur = &t->t_winsize;
368
369 815
        if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col)
370 395
                return;
371 420
        if (t->t_cursor.tp_row >= new->tp_row)
372 0
                t->t_cursor.tp_row = new->tp_row - 1;
373 420
        if (t->t_cursor.tp_col >= new->tp_col)
374 20
                t->t_cursor.tp_col = new->tp_col - 1;
375 815
}
376
377
void
378 815
teken_set_winsize(teken_t *t, const teken_pos_t *p)
379
{
380
381 815
        teken_trim_cursor_pos(t, p);
382 815
        t->t_winsize = *p;
383 815
        teken_subr_do_reset(t);
384 815
}
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 158343
teken_state_switch(teken_t *t, teken_state_t *s)
415
{
416
417 158343
        t->t_nextstate = s;
418 158343
        t->t_curnum = 0;
419 158343
        t->t_stateflags |= TS_FIRSTDIGIT;
420 158343
}
421
422
static int
423 165620
teken_state_numbers(teken_t *t, teken_char_t c)
424
{
425
426 165620
        teken_assert(t->t_curnum < T_NUMSIZE);
427
428 165620
        if (c >= '0' && c <= '9') {
429 98001
                if (t->t_stateflags & TS_FIRSTDIGIT) {
430
                        /* First digit. */
431 64042
                        t->t_stateflags &= ~TS_FIRSTDIGIT;
432 64042
                        t->t_nums[t->t_curnum] = c - '0';
433 98001
                } 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 33959
                        t->t_nums[t->t_curnum] =
445 33959
                            t->t_nums[t->t_curnum] * 10 + c - '0';
446 33959
                }
447 98001
                return (1);
448 67619
        } else if (c == ';') {
449 19438
                if (t->t_stateflags & TS_FIRSTDIGIT)
450 240
                        t->t_nums[t->t_curnum] = 0;
451
452
                /* Only allow a limited set of arguments. */
453 19438
                if (++t->t_curnum == T_NUMSIZE) {
454 10
                        teken_state_switch(t, teken_state_init);
455 10
                        return (1);
456
                }
457
458 19428
                t->t_stateflags |= TS_FIRSTDIGIT;
459 19428
                return (1);
460
        } else {
461 48181
                if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
462
                        /* Finish off the last empty argument. */
463 10
                        t->t_nums[t->t_curnum] = 0;
464 10
                        t->t_curnum++;
465 48181
                } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
466
                        /* Also count the last argument. */
467 44844
                        t->t_curnum++;
468 44844
                }
469
        }
470
471 48181
        return (0);
472 165620
}
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 885
teken_256to8(teken_color_t c)
661
{
662
663 885
        return (teken_256to8tab[c % 256]);
664
}
665
666
teken_color_t
667 295
teken_256to16(teken_color_t c)
668
{
669
670 295
        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 590
teken_get_sequence(const teken_t *t, unsigned int k)
714
{
715
716
        /* Cons25 mode. */
717 590
        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 590
        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 590
        if (k < sizeof special_strings_normal / sizeof(char *))
728 590
                return (special_strings_normal[k]);
729
730 0
        return (NULL);
731 590
}
732
733
#include "teken_state.h"