ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/sys/teken/teken.c
Revision: 12320
Committed: Sat Feb 8 19:46:22 2020 UTC (4 years, 2 months ago) by laffer1
Content type: text/plain
File size: 16980 byte(s)
Log Message:
sync with FreeBSD 11-stable

File Contents

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

Properties

Name Value
svn:keywords MidnightBSD=%H