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