xref: /freebsd/sys/teken/teken.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
19b934d09SEd Schouten /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro F. Giffuni  *
49b934d09SEd Schouten  * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
59b934d09SEd Schouten  * All rights reserved.
69b934d09SEd Schouten  *
79b934d09SEd Schouten  * Redistribution and use in source and binary forms, with or without
89b934d09SEd Schouten  * modification, are permitted provided that the following conditions
99b934d09SEd Schouten  * are met:
109b934d09SEd Schouten  * 1. Redistributions of source code must retain the above copyright
119b934d09SEd Schouten  *    notice, this list of conditions and the following disclaimer.
129b934d09SEd Schouten  * 2. Redistributions in binary form must reproduce the above copyright
139b934d09SEd Schouten  *    notice, this list of conditions and the following disclaimer in the
149b934d09SEd Schouten  *    documentation and/or other materials provided with the distribution.
159b934d09SEd Schouten  *
169b934d09SEd Schouten  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179b934d09SEd Schouten  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189b934d09SEd Schouten  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199b934d09SEd Schouten  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209b934d09SEd Schouten  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219b934d09SEd Schouten  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229b934d09SEd Schouten  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239b934d09SEd Schouten  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249b934d09SEd Schouten  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259b934d09SEd Schouten  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269b934d09SEd Schouten  * SUCH DAMAGE.
279b934d09SEd Schouten  */
289b934d09SEd Schouten 
299b934d09SEd Schouten #include <sys/cdefs.h>
309b934d09SEd Schouten #if defined(__FreeBSD__) && defined(_KERNEL)
319b934d09SEd Schouten #include <sys/param.h>
32c5b3acf2SEd Schouten #include <sys/limits.h>
339b934d09SEd Schouten #include <sys/lock.h>
349b934d09SEd Schouten #include <sys/systm.h>
359b934d09SEd Schouten #define	teken_assert(x)		MPASS(x)
3682625856SToomas Soome #elif defined(__FreeBSD__) && defined(_STANDALONE)
3782625856SToomas Soome #include <stand.h>
3882625856SToomas Soome #include <sys/limits.h>
3982625856SToomas Soome #include <assert.h>
4082625856SToomas Soome #define	teken_assert(x)		assert(x)
4182625856SToomas Soome #else /* !(__FreeBSD__ && _STANDALONE) */
429b934d09SEd Schouten #include <sys/types.h>
439b934d09SEd Schouten #include <assert.h>
44c5b3acf2SEd Schouten #include <limits.h>
45a54dd632SEd Schouten #include <stdint.h>
469b934d09SEd Schouten #include <stdio.h>
479b934d09SEd Schouten #include <string.h>
489b934d09SEd Schouten #define	teken_assert(x)		assert(x)
4982625856SToomas Soome #endif /* __FreeBSD__ && _STANDALONE */
509b934d09SEd Schouten 
51ecc16c8dSEd Schouten /* debug messages */
52ecc16c8dSEd Schouten #define	teken_printf(x,...)
53ecc16c8dSEd Schouten 
549b934d09SEd Schouten /* Private flags for t_stateflags. */
553a8a07eaSEd Schouten #define	TS_FIRSTDIGIT	0x0001	/* First numeric digit in escape sequence. */
563a8a07eaSEd Schouten #define	TS_INSERT	0x0002	/* Insert mode. */
573a8a07eaSEd Schouten #define	TS_AUTOWRAP	0x0004	/* Autowrap. */
583a8a07eaSEd Schouten #define	TS_ORIGIN	0x0008	/* Origin mode. */
593a8a07eaSEd Schouten #define	TS_WRAPPED	0x0010	/* Next character should be printed on col 0. */
603a8a07eaSEd Schouten #define	TS_8BIT		0x0020	/* UTF-8 disabled. */
613a8a07eaSEd Schouten #define	TS_CONS25	0x0040	/* cons25 emulation. */
623a8a07eaSEd Schouten #define	TS_INSTRING	0x0080	/* Inside string. */
633a8a07eaSEd Schouten #define	TS_CURSORKEYS	0x0100	/* Cursor keys mode. */
6490bdbe95SBruce Evans #define	TS_CONS25KEYS	0x0400	/* Fuller cons25 emul (fix function keys). */
659b934d09SEd Schouten 
669b934d09SEd Schouten /* Character that blanks a cell. */
679b934d09SEd Schouten #define	BLANK	' '
689b934d09SEd Schouten 
69fbcd1b6eSEd Schouten #include "teken.h"
70fbcd1b6eSEd Schouten #include "teken_wcwidth.h"
71fbcd1b6eSEd Schouten #include "teken_scs.h"
72fbcd1b6eSEd Schouten 
739b934d09SEd Schouten static teken_state_t	teken_state_init;
749b934d09SEd Schouten 
759b934d09SEd Schouten /*
769b934d09SEd Schouten  * Wrappers for hooks.
779b934d09SEd Schouten  */
789b934d09SEd Schouten 
799b934d09SEd Schouten static inline void
teken_funcs_bell(const teken_t * t)8092223bddSPoul-Henning Kamp teken_funcs_bell(const teken_t *t)
819b934d09SEd Schouten {
829b934d09SEd Schouten 
8392223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_bell != NULL);
849b934d09SEd Schouten 	t->t_funcs->tf_bell(t->t_softc);
859b934d09SEd Schouten }
869b934d09SEd Schouten 
879b934d09SEd Schouten static inline void
teken_funcs_cursor(const teken_t * t)8892223bddSPoul-Henning Kamp teken_funcs_cursor(const teken_t *t)
899b934d09SEd Schouten {
909b934d09SEd Schouten 
919b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
929b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
939b934d09SEd Schouten 
9492223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_cursor != NULL);
959b934d09SEd Schouten 	t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
969b934d09SEd Schouten }
979b934d09SEd Schouten 
989b934d09SEd Schouten static inline void
teken_funcs_putchar(const teken_t * t,const teken_pos_t * p,teken_char_t c,const teken_attr_t * a)9992223bddSPoul-Henning Kamp teken_funcs_putchar(const teken_t *t, const teken_pos_t *p, teken_char_t c,
1009b934d09SEd Schouten     const teken_attr_t *a)
1019b934d09SEd Schouten {
1029b934d09SEd Schouten 
1039b934d09SEd Schouten 	teken_assert(p->tp_row < t->t_winsize.tp_row);
1049b934d09SEd Schouten 	teken_assert(p->tp_col < t->t_winsize.tp_col);
1059b934d09SEd Schouten 
10692223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_putchar != NULL);
1079b934d09SEd Schouten 	t->t_funcs->tf_putchar(t->t_softc, p, c, a);
1089b934d09SEd Schouten }
1099b934d09SEd Schouten 
1109b934d09SEd Schouten static inline void
teken_funcs_fill(const teken_t * t,const teken_rect_t * r,const teken_char_t c,const teken_attr_t * a)11192223bddSPoul-Henning Kamp teken_funcs_fill(const teken_t *t, const teken_rect_t *r,
1129b934d09SEd Schouten     const teken_char_t c, const teken_attr_t *a)
1139b934d09SEd Schouten {
1149b934d09SEd Schouten 
1159b934d09SEd Schouten 	teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
1169b934d09SEd Schouten 	teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
1179b934d09SEd Schouten 	teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
1189b934d09SEd Schouten 	teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
1199b934d09SEd Schouten 
12092223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_fill != NULL);
1219b934d09SEd Schouten 	t->t_funcs->tf_fill(t->t_softc, r, c, a);
1229b934d09SEd Schouten }
1239b934d09SEd Schouten 
1249b934d09SEd Schouten static inline void
teken_funcs_copy(const teken_t * t,const teken_rect_t * r,const teken_pos_t * p)12592223bddSPoul-Henning Kamp teken_funcs_copy(const teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
1269b934d09SEd Schouten {
1279b934d09SEd Schouten 
1289b934d09SEd Schouten 	teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
1299b934d09SEd Schouten 	teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
1309b934d09SEd Schouten 	teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
1319b934d09SEd Schouten 	teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
1329b934d09SEd Schouten 	teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
1339b934d09SEd Schouten 	teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
1349b934d09SEd Schouten 
13592223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_copy != NULL);
1369b934d09SEd Schouten 	t->t_funcs->tf_copy(t->t_softc, r, p);
1379b934d09SEd Schouten }
1389b934d09SEd Schouten 
1399b934d09SEd Schouten static inline void
teken_funcs_pre_input(const teken_t * t)140547e74a8SJean-Sébastien Pédron teken_funcs_pre_input(const teken_t *t)
141547e74a8SJean-Sébastien Pédron {
142547e74a8SJean-Sébastien Pédron 
1434812c5c5SConrad Meyer 	if (t->t_funcs->tf_pre_input != NULL)
144547e74a8SJean-Sébastien Pédron 		t->t_funcs->tf_pre_input(t->t_softc);
145547e74a8SJean-Sébastien Pédron }
146547e74a8SJean-Sébastien Pédron 
147547e74a8SJean-Sébastien Pédron static inline void
teken_funcs_post_input(const teken_t * t)148547e74a8SJean-Sébastien Pédron teken_funcs_post_input(const teken_t *t)
149547e74a8SJean-Sébastien Pédron {
150547e74a8SJean-Sébastien Pédron 
1514812c5c5SConrad Meyer 	if (t->t_funcs->tf_post_input != NULL)
152547e74a8SJean-Sébastien Pédron 		t->t_funcs->tf_post_input(t->t_softc);
153547e74a8SJean-Sébastien Pédron }
154547e74a8SJean-Sébastien Pédron 
155547e74a8SJean-Sébastien Pédron static inline void
teken_funcs_param(const teken_t * t,int cmd,unsigned int value)15692223bddSPoul-Henning Kamp teken_funcs_param(const teken_t *t, int cmd, unsigned int value)
1579b934d09SEd Schouten {
1589b934d09SEd Schouten 
15992223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_param != NULL);
1609b934d09SEd Schouten 	t->t_funcs->tf_param(t->t_softc, cmd, value);
1619b934d09SEd Schouten }
1629b934d09SEd Schouten 
1639b934d09SEd Schouten static inline void
teken_funcs_respond(const teken_t * t,const void * buf,size_t len)16492223bddSPoul-Henning Kamp teken_funcs_respond(const teken_t *t, const void *buf, size_t len)
1659b934d09SEd Schouten {
1669b934d09SEd Schouten 
16792223bddSPoul-Henning Kamp 	teken_assert(t->t_funcs->tf_respond != NULL);
1689b934d09SEd Schouten 	t->t_funcs->tf_respond(t->t_softc, buf, len);
1699b934d09SEd Schouten }
1709b934d09SEd Schouten 
1719b934d09SEd Schouten #include "teken_subr.h"
1729b934d09SEd Schouten #include "teken_subr_compat.h"
1739b934d09SEd Schouten 
1749b934d09SEd Schouten /*
1759b934d09SEd Schouten  * Programming interface.
1769b934d09SEd Schouten  */
1779b934d09SEd Schouten 
1789b934d09SEd Schouten void
teken_init(teken_t * t,const teken_funcs_t * tf,void * softc)1799b934d09SEd Schouten teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
1809b934d09SEd Schouten {
1819b934d09SEd Schouten 	teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
1829b934d09SEd Schouten 
1839b934d09SEd Schouten 	t->t_funcs = tf;
1849b934d09SEd Schouten 	t->t_softc = softc;
1859b934d09SEd Schouten 
1869b934d09SEd Schouten 	t->t_nextstate = teken_state_init;
187eba77f5cSEd Schouten 	t->t_stateflags = 0;
188eba77f5cSEd Schouten 	t->t_utf8_left = 0;
1899b934d09SEd Schouten 
1909b934d09SEd Schouten 	t->t_defattr.ta_format = 0;
1919b934d09SEd Schouten 	t->t_defattr.ta_fgcolor = TC_WHITE;
1929b934d09SEd Schouten 	t->t_defattr.ta_bgcolor = TC_BLACK;
1939b934d09SEd Schouten 	teken_subr_do_reset(t);
1949b934d09SEd Schouten 
1959b934d09SEd Schouten 	teken_set_winsize(t, &tp);
1969b934d09SEd Schouten }
1979b934d09SEd Schouten 
1989b934d09SEd Schouten static void
teken_input_char(teken_t * t,teken_char_t c)1999b934d09SEd Schouten teken_input_char(teken_t *t, teken_char_t c)
2009b934d09SEd Schouten {
2019b934d09SEd Schouten 
2024a11e7f1SEd Schouten 	/*
2034a11e7f1SEd Schouten 	 * There is no support for DCS and OSC.  Just discard strings
2044a11e7f1SEd Schouten 	 * until we receive characters that may indicate string
2054a11e7f1SEd Schouten 	 * termination.
2064a11e7f1SEd Schouten 	 */
2074a11e7f1SEd Schouten 	if (t->t_stateflags & TS_INSTRING) {
2084a11e7f1SEd Schouten 		switch (c) {
2094a11e7f1SEd Schouten 		case '\x1B':
2104a11e7f1SEd Schouten 			t->t_stateflags &= ~TS_INSTRING;
2114a11e7f1SEd Schouten 			break;
2124a11e7f1SEd Schouten 		case '\a':
2134a11e7f1SEd Schouten 			t->t_stateflags &= ~TS_INSTRING;
2144a11e7f1SEd Schouten 			return;
2154a11e7f1SEd Schouten 		default:
2164a11e7f1SEd Schouten 			return;
2174a11e7f1SEd Schouten 		}
2184a11e7f1SEd Schouten 	}
2194a11e7f1SEd Schouten 
2209b934d09SEd Schouten 	switch (c) {
2219b934d09SEd Schouten 	case '\0':
2229b934d09SEd Schouten 		break;
2239b934d09SEd Schouten 	case '\a':
2249b934d09SEd Schouten 		teken_subr_bell(t);
2259b934d09SEd Schouten 		break;
2269b934d09SEd Schouten 	case '\b':
2279b934d09SEd Schouten 		teken_subr_backspace(t);
2289b934d09SEd Schouten 		break;
2299b934d09SEd Schouten 	case '\n':
2309b934d09SEd Schouten 	case '\x0B':
2319b934d09SEd Schouten 		teken_subr_newline(t);
2329b934d09SEd Schouten 		break;
2339b934d09SEd Schouten 	case '\x0C':
2349b934d09SEd Schouten 		teken_subr_newpage(t);
2359b934d09SEd Schouten 		break;
2369b934d09SEd Schouten 	case '\x0E':
237eba77f5cSEd Schouten 		if (t->t_stateflags & TS_CONS25)
238eba77f5cSEd Schouten 			t->t_nextstate(t, c);
239eba77f5cSEd Schouten 		else
240cd531e74SEd Schouten 			t->t_curscs = 1;
2419b934d09SEd Schouten 		break;
2429b934d09SEd Schouten 	case '\x0F':
243eba77f5cSEd Schouten 		if (t->t_stateflags & TS_CONS25)
244eba77f5cSEd Schouten 			t->t_nextstate(t, c);
245eba77f5cSEd Schouten 		else
246cd531e74SEd Schouten 			t->t_curscs = 0;
2479b934d09SEd Schouten 		break;
2489b934d09SEd Schouten 	case '\r':
2499b934d09SEd Schouten 		teken_subr_carriage_return(t);
2509b934d09SEd Schouten 		break;
2519b934d09SEd Schouten 	case '\t':
2529b934d09SEd Schouten 		teken_subr_horizontal_tab(t);
2539b934d09SEd Schouten 		break;
2549b934d09SEd Schouten 	default:
2559b934d09SEd Schouten 		t->t_nextstate(t, c);
2569b934d09SEd Schouten 		break;
2579b934d09SEd Schouten 	}
2589b934d09SEd Schouten 
2599b934d09SEd Schouten 	/* Post-processing assertions. */
2609b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
2619b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
2629b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
2639b934d09SEd Schouten 	teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
2649b934d09SEd Schouten 	teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
2659b934d09SEd Schouten 	teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
2669b934d09SEd Schouten 	teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
2679b934d09SEd Schouten 	teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end);
2689b934d09SEd Schouten 	/* Origin region has to be window size or the same as scrollreg. */
2699b934d09SEd Schouten 	teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin &&
2709b934d09SEd Schouten 	    t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
2719b934d09SEd Schouten 	    (t->t_originreg.ts_begin == 0 &&
2729b934d09SEd Schouten 	    t->t_originreg.ts_end == t->t_winsize.tp_row));
2739b934d09SEd Schouten }
2749b934d09SEd Schouten 
2759b934d09SEd Schouten static void
teken_input_byte(teken_t * t,unsigned char c)2769b934d09SEd Schouten teken_input_byte(teken_t *t, unsigned char c)
2779b934d09SEd Schouten {
2789b934d09SEd Schouten 
2799b934d09SEd Schouten 	/*
2809b934d09SEd Schouten 	 * UTF-8 handling.
2819b934d09SEd Schouten 	 */
282eba77f5cSEd Schouten 	if ((c & 0x80) == 0x00 || t->t_stateflags & TS_8BIT) {
2839b934d09SEd Schouten 		/* One-byte sequence. */
2849b934d09SEd Schouten 		t->t_utf8_left = 0;
2859b934d09SEd Schouten 		teken_input_char(t, c);
2869b934d09SEd Schouten 	} else if ((c & 0xe0) == 0xc0) {
2879b934d09SEd Schouten 		/* Two-byte sequence. */
2889b934d09SEd Schouten 		t->t_utf8_left = 1;
2899b934d09SEd Schouten 		t->t_utf8_partial = c & 0x1f;
2909b934d09SEd Schouten 	} else if ((c & 0xf0) == 0xe0) {
2919b934d09SEd Schouten 		/* Three-byte sequence. */
2929b934d09SEd Schouten 		t->t_utf8_left = 2;
2939b934d09SEd Schouten 		t->t_utf8_partial = c & 0x0f;
2949b934d09SEd Schouten 	} else if ((c & 0xf8) == 0xf0) {
2959b934d09SEd Schouten 		/* Four-byte sequence. */
2969b934d09SEd Schouten 		t->t_utf8_left = 3;
2979b934d09SEd Schouten 		t->t_utf8_partial = c & 0x07;
2989b934d09SEd Schouten 	} else if ((c & 0xc0) == 0x80) {
2999b934d09SEd Schouten 		if (t->t_utf8_left == 0)
3009b934d09SEd Schouten 			return;
3019b934d09SEd Schouten 		t->t_utf8_left--;
3029b934d09SEd Schouten 		t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
3039b934d09SEd Schouten 		if (t->t_utf8_left == 0) {
3049b934d09SEd Schouten 			teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
3059b934d09SEd Schouten 			teken_input_char(t, t->t_utf8_partial);
3069b934d09SEd Schouten 		}
3079b934d09SEd Schouten 	}
3089b934d09SEd Schouten }
3099b934d09SEd Schouten 
3109b934d09SEd Schouten void
teken_input(teken_t * t,const void * buf,size_t len)3119b934d09SEd Schouten teken_input(teken_t *t, const void *buf, size_t len)
3129b934d09SEd Schouten {
3139b934d09SEd Schouten 	const char *c = buf;
3149b934d09SEd Schouten 
315547e74a8SJean-Sébastien Pédron 	teken_funcs_pre_input(t);
3169b934d09SEd Schouten 	while (len-- > 0)
3179b934d09SEd Schouten 		teken_input_byte(t, *c++);
318547e74a8SJean-Sébastien Pédron 	teken_funcs_post_input(t);
3199b934d09SEd Schouten }
3209b934d09SEd Schouten 
321eba77f5cSEd Schouten const teken_pos_t *
teken_get_cursor(const teken_t * t)32292223bddSPoul-Henning Kamp teken_get_cursor(const teken_t *t)
323eba77f5cSEd Schouten {
324eba77f5cSEd Schouten 
325eba77f5cSEd Schouten 	return (&t->t_cursor);
326eba77f5cSEd Schouten }
327eba77f5cSEd Schouten 
3289b934d09SEd Schouten void
teken_set_cursor(teken_t * t,const teken_pos_t * p)3299b934d09SEd Schouten teken_set_cursor(teken_t *t, const teken_pos_t *p)
3309b934d09SEd Schouten {
3319b934d09SEd Schouten 
3329b934d09SEd Schouten 	/* XXX: bounds checking with originreg! */
3339b934d09SEd Schouten 	teken_assert(p->tp_row < t->t_winsize.tp_row);
3349b934d09SEd Schouten 	teken_assert(p->tp_col < t->t_winsize.tp_col);
3359b934d09SEd Schouten 
3369b934d09SEd Schouten 	t->t_cursor = *p;
3379b934d09SEd Schouten }
3389b934d09SEd Schouten 
3399b934d09SEd Schouten const teken_attr_t *
teken_get_curattr(const teken_t * t)34092223bddSPoul-Henning Kamp teken_get_curattr(const teken_t *t)
3419b934d09SEd Schouten {
3429b934d09SEd Schouten 
3439b934d09SEd Schouten 	return (&t->t_curattr);
3449b934d09SEd Schouten }
3459b934d09SEd Schouten 
3469b934d09SEd Schouten void
teken_set_curattr(teken_t * t,const teken_attr_t * a)3479b934d09SEd Schouten teken_set_curattr(teken_t *t, const teken_attr_t *a)
3489b934d09SEd Schouten {
3499b934d09SEd Schouten 
3509b934d09SEd Schouten 	t->t_curattr = *a;
3519b934d09SEd Schouten }
3529b934d09SEd Schouten 
3539b934d09SEd Schouten const teken_attr_t *
teken_get_defattr(const teken_t * t)35492223bddSPoul-Henning Kamp teken_get_defattr(const teken_t *t)
3559b934d09SEd Schouten {
3569b934d09SEd Schouten 
3579b934d09SEd Schouten 	return (&t->t_defattr);
3589b934d09SEd Schouten }
3599b934d09SEd Schouten 
3609b934d09SEd Schouten void
teken_set_defattr(teken_t * t,const teken_attr_t * a)3619b934d09SEd Schouten teken_set_defattr(teken_t *t, const teken_attr_t *a)
3629b934d09SEd Schouten {
3639b934d09SEd Schouten 
3649b934d09SEd Schouten 	t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
3659b934d09SEd Schouten }
3669b934d09SEd Schouten 
367eba77f5cSEd Schouten const teken_pos_t *
teken_get_winsize(const teken_t * t)36892223bddSPoul-Henning Kamp teken_get_winsize(const teken_t *t)
369eba77f5cSEd Schouten {
370eba77f5cSEd Schouten 
371eba77f5cSEd Schouten 	return (&t->t_winsize);
372eba77f5cSEd Schouten }
373eba77f5cSEd Schouten 
374f821d023SAleksandr Rybalko static void
teken_trim_cursor_pos(teken_t * t,const teken_pos_t * new)3750205ddebSAleksandr Rybalko teken_trim_cursor_pos(teken_t *t, const teken_pos_t *new)
376f821d023SAleksandr Rybalko {
377f821d023SAleksandr Rybalko 	const teken_pos_t *cur;
378f821d023SAleksandr Rybalko 
379f821d023SAleksandr Rybalko 	cur = &t->t_winsize;
380f821d023SAleksandr Rybalko 
381f821d023SAleksandr Rybalko 	if (cur->tp_row < new->tp_row || cur->tp_col < new->tp_col)
382f821d023SAleksandr Rybalko 		return;
383f821d023SAleksandr Rybalko 	if (t->t_cursor.tp_row >= new->tp_row)
384f821d023SAleksandr Rybalko 		t->t_cursor.tp_row = new->tp_row - 1;
385f821d023SAleksandr Rybalko 	if (t->t_cursor.tp_col >= new->tp_col)
386f821d023SAleksandr Rybalko 		t->t_cursor.tp_col = new->tp_col - 1;
387f821d023SAleksandr Rybalko }
388f821d023SAleksandr Rybalko 
3899b934d09SEd Schouten void
teken_set_winsize(teken_t * t,const teken_pos_t * p)3909b934d09SEd Schouten teken_set_winsize(teken_t *t, const teken_pos_t *p)
3919b934d09SEd Schouten {
3929b934d09SEd Schouten 
3930205ddebSAleksandr Rybalko 	teken_trim_cursor_pos(t, p);
3949b934d09SEd Schouten 	t->t_winsize = *p;
395b03552b5SEd Schouten 	teken_subr_do_reset(t);
3969b934d09SEd Schouten }
3979b934d09SEd Schouten 
398e06d84fcSEd Schouten void
teken_set_winsize_noreset(teken_t * t,const teken_pos_t * p)39927cf7d04SAleksandr Rybalko teken_set_winsize_noreset(teken_t *t, const teken_pos_t *p)
40027cf7d04SAleksandr Rybalko {
40127cf7d04SAleksandr Rybalko 
4020205ddebSAleksandr Rybalko 	teken_trim_cursor_pos(t, p);
40327cf7d04SAleksandr Rybalko 	t->t_winsize = *p;
40427cf7d04SAleksandr Rybalko 	teken_subr_do_resize(t);
40527cf7d04SAleksandr Rybalko }
40627cf7d04SAleksandr Rybalko 
40727cf7d04SAleksandr Rybalko void
teken_set_8bit(teken_t * t)408e06d84fcSEd Schouten teken_set_8bit(teken_t *t)
409e06d84fcSEd Schouten {
410e06d84fcSEd Schouten 
411eba77f5cSEd Schouten 	t->t_stateflags |= TS_8BIT;
412eba77f5cSEd Schouten }
413eba77f5cSEd Schouten 
414eba77f5cSEd Schouten void
teken_set_cons25(teken_t * t)415eba77f5cSEd Schouten teken_set_cons25(teken_t *t)
416eba77f5cSEd Schouten {
417eba77f5cSEd Schouten 
4183a199184SBruce Evans 	t->t_stateflags |= TS_CONS25;
4193a199184SBruce Evans }
4203a199184SBruce Evans 
4213a199184SBruce Evans void
teken_set_cons25keys(teken_t * t)4223a199184SBruce Evans teken_set_cons25keys(teken_t *t)
4233a199184SBruce Evans {
4243a199184SBruce Evans 
4253a199184SBruce Evans 	t->t_stateflags |= TS_CONS25KEYS;
426e06d84fcSEd Schouten }
427e06d84fcSEd Schouten 
4289b934d09SEd Schouten /*
4299b934d09SEd Schouten  * State machine.
4309b934d09SEd Schouten  */
4319b934d09SEd Schouten 
4329b934d09SEd Schouten static void
teken_state_switch(teken_t * t,teken_state_t * s)4339b934d09SEd Schouten teken_state_switch(teken_t *t, teken_state_t *s)
4349b934d09SEd Schouten {
4359b934d09SEd Schouten 
4369b934d09SEd Schouten 	t->t_nextstate = s;
4379b934d09SEd Schouten 	t->t_curnum = 0;
4389b934d09SEd Schouten 	t->t_stateflags |= TS_FIRSTDIGIT;
4399b934d09SEd Schouten }
4409b934d09SEd Schouten 
4419b934d09SEd Schouten static int
teken_state_numbers(teken_t * t,teken_char_t c)4429b934d09SEd Schouten teken_state_numbers(teken_t *t, teken_char_t c)
4439b934d09SEd Schouten {
4449b934d09SEd Schouten 
4459b934d09SEd Schouten 	teken_assert(t->t_curnum < T_NUMSIZE);
4469b934d09SEd Schouten 
4479b934d09SEd Schouten 	if (c >= '0' && c <= '9') {
4489b934d09SEd Schouten 		if (t->t_stateflags & TS_FIRSTDIGIT) {
449c5b3acf2SEd Schouten 			/* First digit. */
4509b934d09SEd Schouten 			t->t_stateflags &= ~TS_FIRSTDIGIT;
451c5b3acf2SEd Schouten 			t->t_nums[t->t_curnum] = c - '0';
452cd69db4bSEd Schouten 		} else if (t->t_nums[t->t_curnum] < UINT_MAX / 100) {
453c5b3acf2SEd Schouten 			/*
454cd69db4bSEd Schouten 			 * There is no need to continue parsing input
455cd69db4bSEd Schouten 			 * once the value exceeds the size of the
456cd69db4bSEd Schouten 			 * terminal. It would only allow for integer
457cd69db4bSEd Schouten 			 * overflows when performing arithmetic on the
458cd69db4bSEd Schouten 			 * cursor position.
459cd69db4bSEd Schouten 			 *
460cd69db4bSEd Schouten 			 * Ignore any further digits if the value is
461cd69db4bSEd Schouten 			 * already UINT_MAX / 100.
462c5b3acf2SEd Schouten 			 */
463c5b3acf2SEd Schouten 			t->t_nums[t->t_curnum] =
464c5b3acf2SEd Schouten 			    t->t_nums[t->t_curnum] * 10 + c - '0';
4659b934d09SEd Schouten 		}
4669b934d09SEd Schouten 		return (1);
4679b934d09SEd Schouten 	} else if (c == ';') {
4689b934d09SEd Schouten 		if (t->t_stateflags & TS_FIRSTDIGIT)
4699b934d09SEd Schouten 			t->t_nums[t->t_curnum] = 0;
4709b934d09SEd Schouten 
4719b934d09SEd Schouten 		/* Only allow a limited set of arguments. */
4729b934d09SEd Schouten 		if (++t->t_curnum == T_NUMSIZE) {
4739b934d09SEd Schouten 			teken_state_switch(t, teken_state_init);
4749b934d09SEd Schouten 			return (1);
4759b934d09SEd Schouten 		}
4769b934d09SEd Schouten 
4779b934d09SEd Schouten 		t->t_stateflags |= TS_FIRSTDIGIT;
4789b934d09SEd Schouten 		return (1);
4799b934d09SEd Schouten 	} else {
4809b934d09SEd Schouten 		if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
4819b934d09SEd Schouten 			/* Finish off the last empty argument. */
4829b934d09SEd Schouten 			t->t_nums[t->t_curnum] = 0;
4839b934d09SEd Schouten 			t->t_curnum++;
4849b934d09SEd Schouten 		} else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
4859b934d09SEd Schouten 			/* Also count the last argument. */
4869b934d09SEd Schouten 			t->t_curnum++;
4879b934d09SEd Schouten 		}
4889b934d09SEd Schouten 	}
4899b934d09SEd Schouten 
4909b934d09SEd Schouten 	return (0);
4919b934d09SEd Schouten }
4929b934d09SEd Schouten 
4932610c9f2SBruce Evans #define	k	TC_BLACK
4942610c9f2SBruce Evans #define	b	TC_BLUE
495cf8880d5SEd Maste #define	y	TC_YELLOW
4962610c9f2SBruce Evans #define	c	TC_CYAN
4972610c9f2SBruce Evans #define	g	TC_GREEN
4982610c9f2SBruce Evans #define	m	TC_MAGENTA
4992610c9f2SBruce Evans #define	r	TC_RED
5002610c9f2SBruce Evans #define	w	TC_WHITE
5012610c9f2SBruce Evans #define	K	(TC_BLACK | TC_LIGHT)
5022610c9f2SBruce Evans #define	B	(TC_BLUE | TC_LIGHT)
503cf8880d5SEd Maste #define	Y	(TC_YELLOW | TC_LIGHT)
5042610c9f2SBruce Evans #define	C	(TC_CYAN | TC_LIGHT)
5052610c9f2SBruce Evans #define	G	(TC_GREEN | TC_LIGHT)
5062610c9f2SBruce Evans #define	M	(TC_MAGENTA | TC_LIGHT)
5072610c9f2SBruce Evans #define	R	(TC_RED | TC_LIGHT)
5082610c9f2SBruce Evans #define	W	(TC_WHITE | TC_LIGHT)
5092610c9f2SBruce Evans 
5102610c9f2SBruce Evans /**
5112610c9f2SBruce Evans  * The xterm-256 color map has steps of 0x28 (in the range 0-0xff), except
5122610c9f2SBruce Evans  * for the first step which is 0x5f.  Scale to the range 0-6 by dividing
5132610c9f2SBruce Evans  * by 0x28 and rounding down.  The range of 0-5 cannot represent the
5142610c9f2SBruce Evans  * larger first step.
5152610c9f2SBruce Evans  *
5162610c9f2SBruce Evans  * This table is generated by the follow rules:
5172610c9f2SBruce Evans  * - if all components are equal, the result is black for (0, 0, 0) and
5182610c9f2SBruce Evans  *   (2, 2, 2), else white; otherwise:
5192610c9f2SBruce Evans  * - subtract the smallest component from all components
5202610c9f2SBruce Evans  * - if this gives only one nonzero component, then that is the color
5212610c9f2SBruce Evans  * - else if one component is 2 or more larger than the other nonzero one,
5222610c9f2SBruce Evans  *   then that component gives the color
5232610c9f2SBruce Evans  * - else there are 2 nonzero components.  The color is that of a small
5242610c9f2SBruce Evans  *   equal mixture of these components (cyan, yellow or magenta).  E.g.,
5252610c9f2SBruce Evans  *   (0, 5, 6) (Turquoise2) is a much purer cyan than (0, 2, 3)
5262610c9f2SBruce Evans  *   (DeepSkyBlue4), but we map both to cyan since we can't represent
5272610c9f2SBruce Evans  *   delicate shades of either blue or cyan and blue would be worse.
5282610c9f2SBruce Evans  *   Here it is important that components of 1 never occur.  Blue would
5292610c9f2SBruce Evans  *   be twice as large as green in (0, 1, 2).
5302610c9f2SBruce Evans  */
5312610c9f2SBruce Evans static const teken_color_t teken_256to8tab[] = {
5321370fa33SBruce Evans 	/* xterm normal colors: */
5331370fa33SBruce Evans 	k, r, g, y, b, m, c, w,
5342610c9f2SBruce Evans 
5351370fa33SBruce Evans 	/* xterm bright colors: */
5361370fa33SBruce Evans 	k, r, g, y, b, m, c, w,
5372610c9f2SBruce Evans 
5382610c9f2SBruce Evans 	/* Red0 submap. */
5392610c9f2SBruce Evans 	k, b, b, b, b, b,
5402610c9f2SBruce Evans 	g, c, c, b, b, b,
5412610c9f2SBruce Evans 	g, c, c, c, b, b,
5422610c9f2SBruce Evans 	g, g, c, c, c, b,
5432610c9f2SBruce Evans 	g, g, g, c, c, c,
5442610c9f2SBruce Evans 	g, g, g, g, c, c,
5452610c9f2SBruce Evans 
5462610c9f2SBruce Evans 	/* Red2 submap. */
5472610c9f2SBruce Evans 	r, m, m, b, b, b,
5482610c9f2SBruce Evans 	y, k, b, b, b, b,
5492610c9f2SBruce Evans 	y, g, c, c, b, b,
5502610c9f2SBruce Evans 	g, g, c, c, c, b,
5512610c9f2SBruce Evans 	g, g, g, c, c, c,
5522610c9f2SBruce Evans 	g, g, g, g, c, c,
5532610c9f2SBruce Evans 
5542610c9f2SBruce Evans 	/* Red3 submap. */
5552610c9f2SBruce Evans 	r, m, m, m, b, b,
5562610c9f2SBruce Evans 	y, r, m, m, b, b,
5572610c9f2SBruce Evans 	y, y, w, b, b, b,
5582610c9f2SBruce Evans 	y, y, g, c, c, b,
5592610c9f2SBruce Evans 	g, g, g, c, c, c,
5602610c9f2SBruce Evans 	g, g, g, g, c, c,
5612610c9f2SBruce Evans 
5622610c9f2SBruce Evans 	/* Red4 submap. */
5632610c9f2SBruce Evans 	r, r, m, m, m, b,
5642610c9f2SBruce Evans 	r, r, m, m, m, b,
5652610c9f2SBruce Evans 	y, y, r, m, m, b,
5662610c9f2SBruce Evans 	y, y, y, w, b, b,
5672610c9f2SBruce Evans 	y, y, y, g, c, c,
5682610c9f2SBruce Evans 	g, g, g, g, c, c,
5692610c9f2SBruce Evans 
5702610c9f2SBruce Evans 	/* Red5 submap. */
5712610c9f2SBruce Evans 	r, r, r, m, m, m,
5722610c9f2SBruce Evans 	r, r, r, m, m, m,
5732610c9f2SBruce Evans 	r, r, r, m, m, m,
5742610c9f2SBruce Evans 	y, y, y, r, m, m,
5752610c9f2SBruce Evans 	y, y, y, y, w, b,
5762610c9f2SBruce Evans 	y, y, y, y, g, c,
5772610c9f2SBruce Evans 
5782610c9f2SBruce Evans 	/* Red6 submap. */
5792610c9f2SBruce Evans 	r, r, r, r, m, m,
5802610c9f2SBruce Evans 	r, r, r, r, m, m,
5812610c9f2SBruce Evans 	r, r, r, r, m, m,
5822610c9f2SBruce Evans 	r, r, r, r, m, m,
5832610c9f2SBruce Evans 	y, y, y, y, r, m,
5842610c9f2SBruce Evans 	y, y, y, y, y, w,
5852610c9f2SBruce Evans 
5862610c9f2SBruce Evans 	/* Grey submap. */
5872610c9f2SBruce Evans 	k, k, k, k, k, k,
5882610c9f2SBruce Evans 	k, k, k, k, k, k,
5892610c9f2SBruce Evans 	w, w, w, w, w, w,
5902610c9f2SBruce Evans 	w, w, w, w, w, w,
5912610c9f2SBruce Evans };
5922610c9f2SBruce Evans 
5932610c9f2SBruce Evans /*
5942610c9f2SBruce Evans  * This table is generated from the previous one by setting TC_LIGHT for
5952610c9f2SBruce Evans  * entries whose luminosity in the xterm256 color map is 60% or larger.
5962610c9f2SBruce Evans  * Thus the previous table is currently not really needed.  It will be
5972610c9f2SBruce Evans  * used for different fine tuning of the tables.
5982610c9f2SBruce Evans  */
5992610c9f2SBruce Evans static const teken_color_t teken_256to16tab[] = {
6001370fa33SBruce Evans 	/* xterm normal colors: */
6011370fa33SBruce Evans 	k, r, g, y, b, m, c, w,
6022610c9f2SBruce Evans 
6031370fa33SBruce Evans 	/* xterm bright colors: */
6041370fa33SBruce Evans 	K, R, G, Y, B, M, C, W,
6052610c9f2SBruce Evans 
6062610c9f2SBruce Evans 	/* Red0 submap. */
6072610c9f2SBruce Evans 	k, b, b, b, b, b,
6082610c9f2SBruce Evans 	g, c, c, b, b, b,
6092610c9f2SBruce Evans 	g, c, c, c, b, b,
6102610c9f2SBruce Evans 	g, g, c, c, c, b,
6112610c9f2SBruce Evans 	g, g, g, c, c, c,
6122610c9f2SBruce Evans 	g, g, g, g, c, c,
6132610c9f2SBruce Evans 
6142610c9f2SBruce Evans 	/* Red2 submap. */
6152610c9f2SBruce Evans 	r, m, m, b, b, b,
6162610c9f2SBruce Evans 	y, K, b, b, B, B,
6172610c9f2SBruce Evans 	y, g, c, c, B, B,
6182610c9f2SBruce Evans 	g, g, c, c, C, B,
6192610c9f2SBruce Evans 	g, G, G, C, C, C,
6202610c9f2SBruce Evans 	g, G, G, G, C, C,
6212610c9f2SBruce Evans 
6222610c9f2SBruce Evans 	/* Red3 submap. */
6232610c9f2SBruce Evans 	r, m, m, m, b, b,
6242610c9f2SBruce Evans 	y, r, m, m, B, B,
6252610c9f2SBruce Evans 	y, y, w, B, B, B,
6262610c9f2SBruce Evans 	y, y, G, C, C, B,
6272610c9f2SBruce Evans 	g, G, G, C, C, C,
6282610c9f2SBruce Evans 	g, G, G, G, C, C,
6292610c9f2SBruce Evans 
6302610c9f2SBruce Evans 	/* Red4 submap. */
6312610c9f2SBruce Evans 	r, r, m, m, m, b,
6322610c9f2SBruce Evans 	r, r, m, m, M, B,
6332610c9f2SBruce Evans 	y, y, R, M, M, B,
6342610c9f2SBruce Evans 	y, y, Y, W, B, B,
6352610c9f2SBruce Evans 	y, Y, Y, G, C, C,
6362610c9f2SBruce Evans 	g, G, G, G, C, C,
6372610c9f2SBruce Evans 
6382610c9f2SBruce Evans 	/* Red5 submap. */
6392610c9f2SBruce Evans 	r, r, r, m, m, m,
6402610c9f2SBruce Evans 	r, R, R, M, M, M,
6412610c9f2SBruce Evans 	r, R, R, M, M, M,
6422610c9f2SBruce Evans 	y, Y, Y, R, M, M,
6432610c9f2SBruce Evans 	y, Y, Y, Y, W, B,
6442610c9f2SBruce Evans 	y, Y, Y, Y, G, C,
6452610c9f2SBruce Evans 
6462610c9f2SBruce Evans 	/* Red6 submap. */
6472610c9f2SBruce Evans 	r, r, r, r, m, m,
6482610c9f2SBruce Evans 	r, R, R, R, M, M,
6492610c9f2SBruce Evans 	r, R, R, R, M, M,
6502610c9f2SBruce Evans 	r, R, R, R, M, M,
6512610c9f2SBruce Evans 	y, Y, Y, Y, R, M,
6522610c9f2SBruce Evans 	y, Y, Y, Y, Y, W,
6532610c9f2SBruce Evans 
6542610c9f2SBruce Evans 	/* Grey submap. */
6552610c9f2SBruce Evans 	k, k, k, k, k, k,
6562610c9f2SBruce Evans 	K, K, K, K, K, K,
6572610c9f2SBruce Evans 	w, w, w, w, w, w,
6582610c9f2SBruce Evans 	W, W, W, W, W, W,
6592610c9f2SBruce Evans };
6602610c9f2SBruce Evans 
6612610c9f2SBruce Evans #undef	k
6622610c9f2SBruce Evans #undef	b
6632610c9f2SBruce Evans #undef	y
6642610c9f2SBruce Evans #undef	c
6652610c9f2SBruce Evans #undef	g
6662610c9f2SBruce Evans #undef	m
6672610c9f2SBruce Evans #undef	r
6682610c9f2SBruce Evans #undef	w
6692610c9f2SBruce Evans #undef	K
6702610c9f2SBruce Evans #undef	B
6712610c9f2SBruce Evans #undef	Y
6722610c9f2SBruce Evans #undef	C
6732610c9f2SBruce Evans #undef	G
6742610c9f2SBruce Evans #undef	M
6752610c9f2SBruce Evans #undef	R
6762610c9f2SBruce Evans #undef	W
6772610c9f2SBruce Evans 
67856a4365bSEd Schouten teken_color_t
teken_256to8(teken_color_t c)67956a4365bSEd Schouten teken_256to8(teken_color_t c)
68056a4365bSEd Schouten {
68156a4365bSEd Schouten 
6822610c9f2SBruce Evans 	return (teken_256to8tab[c % 256]);
68356a4365bSEd Schouten }
68456a4365bSEd Schouten 
6852610c9f2SBruce Evans teken_color_t
teken_256to16(teken_color_t c)6862610c9f2SBruce Evans teken_256to16(teken_color_t c)
6872610c9f2SBruce Evans {
68856a4365bSEd Schouten 
6892610c9f2SBruce Evans 	return (teken_256to16tab[c % 256]);
69056a4365bSEd Schouten }
69156a4365bSEd Schouten 
6923a8a07eaSEd Schouten static const char * const special_strings_cons25[] = {
6933a8a07eaSEd Schouten 	[TKEY_UP] = "\x1B[A",		[TKEY_DOWN] = "\x1B[B",
6943a8a07eaSEd Schouten 	[TKEY_LEFT] = "\x1B[D",		[TKEY_RIGHT] = "\x1B[C",
6953a8a07eaSEd Schouten 
6963a8a07eaSEd Schouten 	[TKEY_HOME] = "\x1B[H",		[TKEY_END] = "\x1B[F",
697d80a1e6cSEd Schouten 	[TKEY_INSERT] = "\x1B[L",	[TKEY_DELETE] = "\x7F",
6983a8a07eaSEd Schouten 	[TKEY_PAGE_UP] = "\x1B[I",	[TKEY_PAGE_DOWN] = "\x1B[G",
6993a8a07eaSEd Schouten 
7003a8a07eaSEd Schouten 	[TKEY_F1] = "\x1B[M",		[TKEY_F2] = "\x1B[N",
7013a8a07eaSEd Schouten 	[TKEY_F3] = "\x1B[O",		[TKEY_F4] = "\x1B[P",
7023a8a07eaSEd Schouten 	[TKEY_F5] = "\x1B[Q",		[TKEY_F6] = "\x1B[R",
7033a8a07eaSEd Schouten 	[TKEY_F7] = "\x1B[S",		[TKEY_F8] = "\x1B[T",
7043a8a07eaSEd Schouten 	[TKEY_F9] = "\x1B[U",		[TKEY_F10] = "\x1B[V",
7053a8a07eaSEd Schouten 	[TKEY_F11] = "\x1B[W",		[TKEY_F12] = "\x1B[X",
7063a8a07eaSEd Schouten };
7073a8a07eaSEd Schouten 
7083a8a07eaSEd Schouten static const char * const special_strings_ckeys[] = {
7093a8a07eaSEd Schouten 	[TKEY_UP] = "\x1BOA",		[TKEY_DOWN] = "\x1BOB",
7103a8a07eaSEd Schouten 	[TKEY_LEFT] = "\x1BOD",		[TKEY_RIGHT] = "\x1BOC",
7113a8a07eaSEd Schouten 
7123a8a07eaSEd Schouten 	[TKEY_HOME] = "\x1BOH",		[TKEY_END] = "\x1BOF",
7133a8a07eaSEd Schouten };
7143a8a07eaSEd Schouten 
7153a8a07eaSEd Schouten static const char * const special_strings_normal[] = {
7163a8a07eaSEd Schouten 	[TKEY_UP] = "\x1B[A",		[TKEY_DOWN] = "\x1B[B",
7173a8a07eaSEd Schouten 	[TKEY_LEFT] = "\x1B[D",		[TKEY_RIGHT] = "\x1B[C",
7183a8a07eaSEd Schouten 
7193a8a07eaSEd Schouten 	[TKEY_HOME] = "\x1B[H",		[TKEY_END] = "\x1B[F",
720d80a1e6cSEd Schouten 	[TKEY_INSERT] = "\x1B[2~",	[TKEY_DELETE] = "\x1B[3~",
7213a8a07eaSEd Schouten 	[TKEY_PAGE_UP] = "\x1B[5~",	[TKEY_PAGE_DOWN] = "\x1B[6~",
7223a8a07eaSEd Schouten 
7233a8a07eaSEd Schouten 	[TKEY_F1] = "\x1BOP",		[TKEY_F2] = "\x1BOQ",
7243a8a07eaSEd Schouten 	[TKEY_F3] = "\x1BOR",		[TKEY_F4] = "\x1BOS",
7253a8a07eaSEd Schouten 	[TKEY_F5] = "\x1B[15~",		[TKEY_F6] = "\x1B[17~",
7263a8a07eaSEd Schouten 	[TKEY_F7] = "\x1B[18~",		[TKEY_F8] = "\x1B[19~",
7273a8a07eaSEd Schouten 	[TKEY_F9] = "\x1B[20~",		[TKEY_F10] = "\x1B[21~",
7283a8a07eaSEd Schouten 	[TKEY_F11] = "\x1B[23~",	[TKEY_F12] = "\x1B[24~",
7293a8a07eaSEd Schouten };
7303a8a07eaSEd Schouten 
7313a8a07eaSEd Schouten const char *
teken_get_sequence(const teken_t * t,unsigned int k)73292223bddSPoul-Henning Kamp teken_get_sequence(const teken_t *t, unsigned int k)
7333a8a07eaSEd Schouten {
7343a8a07eaSEd Schouten 
7353a8a07eaSEd Schouten 	/* Cons25 mode. */
73690bdbe95SBruce Evans 	if ((t->t_stateflags & (TS_CONS25 | TS_CONS25KEYS)) ==
73790bdbe95SBruce Evans 	    (TS_CONS25 | TS_CONS25KEYS))
73890bdbe95SBruce Evans 		return (NULL);	/* Don't override good kbd(4) strings. */
7393a8a07eaSEd Schouten 	if (t->t_stateflags & TS_CONS25 &&
7403a8a07eaSEd Schouten 	    k < sizeof special_strings_cons25 / sizeof(char *))
7413a8a07eaSEd Schouten 		return (special_strings_cons25[k]);
7423a8a07eaSEd Schouten 
7433a8a07eaSEd Schouten 	/* Cursor keys mode. */
7443a8a07eaSEd Schouten 	if (t->t_stateflags & TS_CURSORKEYS &&
7453a8a07eaSEd Schouten 	    k < sizeof special_strings_ckeys / sizeof(char *))
7463a8a07eaSEd Schouten 		return (special_strings_ckeys[k]);
7473a8a07eaSEd Schouten 
7483a8a07eaSEd Schouten 	/* Default xterm sequences. */
7493a8a07eaSEd Schouten 	if (k < sizeof special_strings_normal / sizeof(char *))
7503a8a07eaSEd Schouten 		return (special_strings_normal[k]);
7513a8a07eaSEd Schouten 
7523a8a07eaSEd Schouten 	return (NULL);
7533a8a07eaSEd Schouten }
7543a8a07eaSEd Schouten 
7559b934d09SEd Schouten #include "teken_state.h"
756