Deleted Added
full compact
teken.c (197114) teken.c (197115)
1/*-
2 * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/teken/teken.c 197114 2009-09-12 08:19:24Z ed $
26 * $FreeBSD: head/sys/teken/teken.c 197115 2009-09-12 10:34:34Z ed $
27 */
28
29#include <sys/cdefs.h>
30#if defined(__FreeBSD__) && defined(_KERNEL)
31#include <sys/param.h>
32#include <sys/lock.h>
33#include <sys/systm.h>
34#define teken_assert(x) MPASS(x)
35#define teken_printf(x,...)
36#else /* !(__FreeBSD__ && _KERNEL) */
37#include <sys/types.h>
38#include <assert.h>
39#include <inttypes.h>
40#include <stdio.h>
41#include <string.h>
42#define teken_assert(x) assert(x)
43#define teken_printf(x,...) do { \
44 if (df != NULL) \
45 fprintf(df, x, ## __VA_ARGS__); \
46} while (0)
47/* debug messages */
48static FILE *df;
49#endif /* __FreeBSD__ && _KERNEL */
50
51#include "teken.h"
27 */
28
29#include <sys/cdefs.h>
30#if defined(__FreeBSD__) && defined(_KERNEL)
31#include <sys/param.h>
32#include <sys/lock.h>
33#include <sys/systm.h>
34#define teken_assert(x) MPASS(x)
35#define teken_printf(x,...)
36#else /* !(__FreeBSD__ && _KERNEL) */
37#include <sys/types.h>
38#include <assert.h>
39#include <inttypes.h>
40#include <stdio.h>
41#include <string.h>
42#define teken_assert(x) assert(x)
43#define teken_printf(x,...) do { \
44 if (df != NULL) \
45 fprintf(df, x, ## __VA_ARGS__); \
46} while (0)
47/* debug messages */
48static FILE *df;
49#endif /* __FreeBSD__ && _KERNEL */
50
51#include "teken.h"
52
53#ifdef TEKEN_UTF8
54#include "teken_wcwidth.h"
52#include "teken_wcwidth.h"
55#else /* !TEKEN_UTF8 */
56#ifdef TEKEN_XTERM
57#define teken_wcwidth(c) ((c <= 0x1B) ? -1 : 1)
58#else /* !TEKEN_XTERM */
59#define teken_wcwidth(c) (1)
60#endif /* TEKEN_XTERM */
61#endif /* TEKEN_UTF8 */
62
53
63#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
54#ifdef TEKEN_XTERM
64#include "teken_scs.h"
55#include "teken_scs.h"
65#else /* !(TEKEN_XTERM && TEKEN_UTF8) */
56#else /* !TEKEN_XTERM */
66#define teken_scs_process(t, c) (c)
67#define teken_scs_restore(t)
68#define teken_scs_save(t)
69#define teken_scs_set(t, g, ts)
70#define teken_scs_switch(t, g)
57#define teken_scs_process(t, c) (c)
58#define teken_scs_restore(t)
59#define teken_scs_save(t)
60#define teken_scs_set(t, g, ts)
61#define teken_scs_switch(t, g)
71#endif /* TEKEN_XTERM && TEKEN_UTF8 */
62#endif /* TEKEN_XTERM */
72
73/* Private flags for t_stateflags. */
74#define TS_FIRSTDIGIT 0x01 /* First numeric digit in escape sequence. */
75#define TS_INSERT 0x02 /* Insert mode. */
76#define TS_AUTOWRAP 0x04 /* Autowrap. */
77#define TS_ORIGIN 0x08 /* Origin mode. */
78#ifdef TEKEN_XTERM
79#define TS_WRAPPED 0x10 /* Next character should be printed on col 0. */
80#else /* !TEKEN_XTERM */
81#define TS_WRAPPED 0x00 /* Simple line wrapping. */
82#endif /* TEKEN_XTERM */
83
84/* Character that blanks a cell. */
85#define BLANK ' '
86
87static teken_state_t teken_state_init;
88
89/*
90 * Wrappers for hooks.
91 */
92
93static inline void
94teken_funcs_bell(teken_t *t)
95{
96
97 t->t_funcs->tf_bell(t->t_softc);
98}
99
100static inline void
101teken_funcs_cursor(teken_t *t)
102{
103
104 teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
105 teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
106
107 t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
108}
109
110static inline void
111teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c,
112 const teken_attr_t *a)
113{
114
115 teken_assert(p->tp_row < t->t_winsize.tp_row);
116 teken_assert(p->tp_col < t->t_winsize.tp_col);
117
118 t->t_funcs->tf_putchar(t->t_softc, p, c, a);
119}
120
121static inline void
122teken_funcs_fill(teken_t *t, const teken_rect_t *r,
123 const teken_char_t c, const teken_attr_t *a)
124{
125
126 teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
127 teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
128 teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
129 teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
130
131 t->t_funcs->tf_fill(t->t_softc, r, c, a);
132}
133
134static inline void
135teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
136{
137
138 teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
139 teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
140 teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
141 teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
142 teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
143 teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
144
145 t->t_funcs->tf_copy(t->t_softc, r, p);
146}
147
148static inline void
149teken_funcs_param(teken_t *t, int cmd, unsigned int value)
150{
151
152 t->t_funcs->tf_param(t->t_softc, cmd, value);
153}
154
155static inline void
156teken_funcs_respond(teken_t *t, const void *buf, size_t len)
157{
158
159 t->t_funcs->tf_respond(t->t_softc, buf, len);
160}
161
162#include "teken_subr.h"
163#include "teken_subr_compat.h"
164
165/*
166 * Programming interface.
167 */
168
169void
170teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
171{
172 teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
173
174#if !(defined(__FreeBSD__) && defined(_KERNEL))
175 df = fopen("teken.log", "w");
176 if (df != NULL)
177 setvbuf(df, NULL, _IOLBF, BUFSIZ);
178#endif /* !(__FreeBSD__ && _KERNEL) */
179
180 t->t_funcs = tf;
181 t->t_softc = softc;
182
183 t->t_nextstate = teken_state_init;
184
185 t->t_defattr.ta_format = 0;
186 t->t_defattr.ta_fgcolor = TC_WHITE;
187 t->t_defattr.ta_bgcolor = TC_BLACK;
188 teken_subr_do_reset(t);
189
63
64/* Private flags for t_stateflags. */
65#define TS_FIRSTDIGIT 0x01 /* First numeric digit in escape sequence. */
66#define TS_INSERT 0x02 /* Insert mode. */
67#define TS_AUTOWRAP 0x04 /* Autowrap. */
68#define TS_ORIGIN 0x08 /* Origin mode. */
69#ifdef TEKEN_XTERM
70#define TS_WRAPPED 0x10 /* Next character should be printed on col 0. */
71#else /* !TEKEN_XTERM */
72#define TS_WRAPPED 0x00 /* Simple line wrapping. */
73#endif /* TEKEN_XTERM */
74
75/* Character that blanks a cell. */
76#define BLANK ' '
77
78static teken_state_t teken_state_init;
79
80/*
81 * Wrappers for hooks.
82 */
83
84static inline void
85teken_funcs_bell(teken_t *t)
86{
87
88 t->t_funcs->tf_bell(t->t_softc);
89}
90
91static inline void
92teken_funcs_cursor(teken_t *t)
93{
94
95 teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
96 teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
97
98 t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
99}
100
101static inline void
102teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c,
103 const teken_attr_t *a)
104{
105
106 teken_assert(p->tp_row < t->t_winsize.tp_row);
107 teken_assert(p->tp_col < t->t_winsize.tp_col);
108
109 t->t_funcs->tf_putchar(t->t_softc, p, c, a);
110}
111
112static inline void
113teken_funcs_fill(teken_t *t, const teken_rect_t *r,
114 const teken_char_t c, const teken_attr_t *a)
115{
116
117 teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
118 teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
119 teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
120 teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
121
122 t->t_funcs->tf_fill(t->t_softc, r, c, a);
123}
124
125static inline void
126teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
127{
128
129 teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
130 teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
131 teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
132 teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
133 teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
134 teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
135
136 t->t_funcs->tf_copy(t->t_softc, r, p);
137}
138
139static inline void
140teken_funcs_param(teken_t *t, int cmd, unsigned int value)
141{
142
143 t->t_funcs->tf_param(t->t_softc, cmd, value);
144}
145
146static inline void
147teken_funcs_respond(teken_t *t, const void *buf, size_t len)
148{
149
150 t->t_funcs->tf_respond(t->t_softc, buf, len);
151}
152
153#include "teken_subr.h"
154#include "teken_subr_compat.h"
155
156/*
157 * Programming interface.
158 */
159
160void
161teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
162{
163 teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
164
165#if !(defined(__FreeBSD__) && defined(_KERNEL))
166 df = fopen("teken.log", "w");
167 if (df != NULL)
168 setvbuf(df, NULL, _IOLBF, BUFSIZ);
169#endif /* !(__FreeBSD__ && _KERNEL) */
170
171 t->t_funcs = tf;
172 t->t_softc = softc;
173
174 t->t_nextstate = teken_state_init;
175
176 t->t_defattr.ta_format = 0;
177 t->t_defattr.ta_fgcolor = TC_WHITE;
178 t->t_defattr.ta_bgcolor = TC_BLACK;
179 teken_subr_do_reset(t);
180
190#ifdef TEKEN_UTF8
191 t->t_utf8_left = 0;
181 t->t_utf8_left = 0;
192#endif /* TEKEN_UTF8 */
193
194 teken_set_winsize(t, &tp);
195}
196
197static void
198teken_input_char(teken_t *t, teken_char_t c)
199{
200
201 switch (c) {
202 case '\0':
203 break;
204 case '\a':
205 teken_subr_bell(t);
206 break;
207 case '\b':
208 teken_subr_backspace(t);
209 break;
210 case '\n':
211 case '\x0B':
212 teken_subr_newline(t);
213 break;
214 case '\x0C':
215 teken_subr_newpage(t);
216 break;
182
183 teken_set_winsize(t, &tp);
184}
185
186static void
187teken_input_char(teken_t *t, teken_char_t c)
188{
189
190 switch (c) {
191 case '\0':
192 break;
193 case '\a':
194 teken_subr_bell(t);
195 break;
196 case '\b':
197 teken_subr_backspace(t);
198 break;
199 case '\n':
200 case '\x0B':
201 teken_subr_newline(t);
202 break;
203 case '\x0C':
204 teken_subr_newpage(t);
205 break;
217#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
206#ifdef TEKEN_XTERM
218 case '\x0E':
219 teken_scs_switch(t, 1);
220 break;
221 case '\x0F':
222 teken_scs_switch(t, 0);
223 break;
207 case '\x0E':
208 teken_scs_switch(t, 1);
209 break;
210 case '\x0F':
211 teken_scs_switch(t, 0);
212 break;
224#endif /* TEKEN_XTERM && TEKEN_UTF8 */
213#endif /* TEKEN_XTERM */
225 case '\r':
226 teken_subr_carriage_return(t);
227 break;
228 case '\t':
229 teken_subr_horizontal_tab(t);
230 break;
231 default:
232 t->t_nextstate(t, c);
233 break;
234 }
235
236 /* Post-processing assertions. */
237 teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
238 teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
239 teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
240 teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
241 teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
242 teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
243 teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
244 teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end);
245 /* Origin region has to be window size or the same as scrollreg. */
246 teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin &&
247 t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
248 (t->t_originreg.ts_begin == 0 &&
249 t->t_originreg.ts_end == t->t_winsize.tp_row));
250}
251
252static void
253teken_input_byte(teken_t *t, unsigned char c)
254{
255
214 case '\r':
215 teken_subr_carriage_return(t);
216 break;
217 case '\t':
218 teken_subr_horizontal_tab(t);
219 break;
220 default:
221 t->t_nextstate(t, c);
222 break;
223 }
224
225 /* Post-processing assertions. */
226 teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
227 teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
228 teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
229 teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
230 teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
231 teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
232 teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
233 teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end);
234 /* Origin region has to be window size or the same as scrollreg. */
235 teken_assert((t->t_originreg.ts_begin == t->t_scrollreg.ts_begin &&
236 t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
237 (t->t_originreg.ts_begin == 0 &&
238 t->t_originreg.ts_end == t->t_winsize.tp_row));
239}
240
241static void
242teken_input_byte(teken_t *t, unsigned char c)
243{
244
256#ifdef TEKEN_UTF8
257 /*
258 * UTF-8 handling.
259 */
245 /*
246 * UTF-8 handling.
247 */
260 if ((c & 0x80) == 0x00) {
248 if (t->t_utf8_left == -1) {
249 /* UTF-8 disabled. */
250 teken_input_char(t, c);
251 } else if ((c & 0x80) == 0x00) {
261 /* One-byte sequence. */
262 t->t_utf8_left = 0;
263 teken_input_char(t, c);
264 } else if ((c & 0xe0) == 0xc0) {
265 /* Two-byte sequence. */
266 t->t_utf8_left = 1;
267 t->t_utf8_partial = c & 0x1f;
268 } else if ((c & 0xf0) == 0xe0) {
269 /* Three-byte sequence. */
270 t->t_utf8_left = 2;
271 t->t_utf8_partial = c & 0x0f;
272 } else if ((c & 0xf8) == 0xf0) {
273 /* Four-byte sequence. */
274 t->t_utf8_left = 3;
275 t->t_utf8_partial = c & 0x07;
276 } else if ((c & 0xc0) == 0x80) {
277 if (t->t_utf8_left == 0)
278 return;
279 t->t_utf8_left--;
280 t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
281 if (t->t_utf8_left == 0) {
282 teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
283 teken_input_char(t, t->t_utf8_partial);
284 }
285 }
252 /* One-byte sequence. */
253 t->t_utf8_left = 0;
254 teken_input_char(t, c);
255 } else if ((c & 0xe0) == 0xc0) {
256 /* Two-byte sequence. */
257 t->t_utf8_left = 1;
258 t->t_utf8_partial = c & 0x1f;
259 } else if ((c & 0xf0) == 0xe0) {
260 /* Three-byte sequence. */
261 t->t_utf8_left = 2;
262 t->t_utf8_partial = c & 0x0f;
263 } else if ((c & 0xf8) == 0xf0) {
264 /* Four-byte sequence. */
265 t->t_utf8_left = 3;
266 t->t_utf8_partial = c & 0x07;
267 } else if ((c & 0xc0) == 0x80) {
268 if (t->t_utf8_left == 0)
269 return;
270 t->t_utf8_left--;
271 t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
272 if (t->t_utf8_left == 0) {
273 teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
274 teken_input_char(t, t->t_utf8_partial);
275 }
276 }
286#else /* !TEKEN_UTF8 */
287 teken_input_char(t, c);
288#endif /* TEKEN_UTF8 */
289}
290
291void
292teken_input(teken_t *t, const void *buf, size_t len)
293{
294 const char *c = buf;
295
296 while (len-- > 0)
297 teken_input_byte(t, *c++);
298}
299
300void
301teken_set_cursor(teken_t *t, const teken_pos_t *p)
302{
303
304 /* XXX: bounds checking with originreg! */
305 teken_assert(p->tp_row < t->t_winsize.tp_row);
306 teken_assert(p->tp_col < t->t_winsize.tp_col);
307
308 t->t_cursor = *p;
309}
310
311const teken_attr_t *
312teken_get_curattr(teken_t *t)
313{
314
315 return (&t->t_curattr);
316}
317
318void
319teken_set_curattr(teken_t *t, const teken_attr_t *a)
320{
321
322 t->t_curattr = *a;
323}
324
325const teken_attr_t *
326teken_get_defattr(teken_t *t)
327{
328
329 return (&t->t_defattr);
330}
331
332void
333teken_set_defattr(teken_t *t, const teken_attr_t *a)
334{
335
336 t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
337}
338
339void
340teken_set_winsize(teken_t *t, const teken_pos_t *p)
341{
342
343 t->t_winsize = *p;
344 teken_subr_do_reset(t);
345}
346
277}
278
279void
280teken_input(teken_t *t, const void *buf, size_t len)
281{
282 const char *c = buf;
283
284 while (len-- > 0)
285 teken_input_byte(t, *c++);
286}
287
288void
289teken_set_cursor(teken_t *t, const teken_pos_t *p)
290{
291
292 /* XXX: bounds checking with originreg! */
293 teken_assert(p->tp_row < t->t_winsize.tp_row);
294 teken_assert(p->tp_col < t->t_winsize.tp_col);
295
296 t->t_cursor = *p;
297}
298
299const teken_attr_t *
300teken_get_curattr(teken_t *t)
301{
302
303 return (&t->t_curattr);
304}
305
306void
307teken_set_curattr(teken_t *t, const teken_attr_t *a)
308{
309
310 t->t_curattr = *a;
311}
312
313const teken_attr_t *
314teken_get_defattr(teken_t *t)
315{
316
317 return (&t->t_defattr);
318}
319
320void
321teken_set_defattr(teken_t *t, const teken_attr_t *a)
322{
323
324 t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
325}
326
327void
328teken_set_winsize(teken_t *t, const teken_pos_t *p)
329{
330
331 t->t_winsize = *p;
332 teken_subr_do_reset(t);
333}
334
335void
336teken_set_8bit(teken_t *t)
337{
338
339 t->t_utf8_left = -1;
340}
341
347/*
348 * State machine.
349 */
350
351static void
352teken_state_switch(teken_t *t, teken_state_t *s)
353{
354
355 t->t_nextstate = s;
356 t->t_curnum = 0;
357 t->t_stateflags |= TS_FIRSTDIGIT;
358}
359
360static int
361teken_state_numbers(teken_t *t, teken_char_t c)
362{
363
364 teken_assert(t->t_curnum < T_NUMSIZE);
365
366 if (c >= '0' && c <= '9') {
367 /*
368 * Don't do math with the default value of 1 when a
369 * custom number is inserted.
370 */
371 if (t->t_stateflags & TS_FIRSTDIGIT) {
372 t->t_stateflags &= ~TS_FIRSTDIGIT;
373 t->t_nums[t->t_curnum] = 0;
374 } else {
375 t->t_nums[t->t_curnum] *= 10;
376 }
377
378 t->t_nums[t->t_curnum] += c - '0';
379 return (1);
380 } else if (c == ';') {
381 if (t->t_stateflags & TS_FIRSTDIGIT)
382 t->t_nums[t->t_curnum] = 0;
383
384 /* Only allow a limited set of arguments. */
385 if (++t->t_curnum == T_NUMSIZE) {
386 teken_state_switch(t, teken_state_init);
387 return (1);
388 }
389
390 t->t_stateflags |= TS_FIRSTDIGIT;
391 return (1);
392 } else {
393 if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
394 /* Finish off the last empty argument. */
395 t->t_nums[t->t_curnum] = 0;
396 t->t_curnum++;
397 } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
398 /* Also count the last argument. */
399 t->t_curnum++;
400 }
401 }
402
403 return (0);
404}
405
406#include "teken_state.h"
342/*
343 * State machine.
344 */
345
346static void
347teken_state_switch(teken_t *t, teken_state_t *s)
348{
349
350 t->t_nextstate = s;
351 t->t_curnum = 0;
352 t->t_stateflags |= TS_FIRSTDIGIT;
353}
354
355static int
356teken_state_numbers(teken_t *t, teken_char_t c)
357{
358
359 teken_assert(t->t_curnum < T_NUMSIZE);
360
361 if (c >= '0' && c <= '9') {
362 /*
363 * Don't do math with the default value of 1 when a
364 * custom number is inserted.
365 */
366 if (t->t_stateflags & TS_FIRSTDIGIT) {
367 t->t_stateflags &= ~TS_FIRSTDIGIT;
368 t->t_nums[t->t_curnum] = 0;
369 } else {
370 t->t_nums[t->t_curnum] *= 10;
371 }
372
373 t->t_nums[t->t_curnum] += c - '0';
374 return (1);
375 } else if (c == ';') {
376 if (t->t_stateflags & TS_FIRSTDIGIT)
377 t->t_nums[t->t_curnum] = 0;
378
379 /* Only allow a limited set of arguments. */
380 if (++t->t_curnum == T_NUMSIZE) {
381 teken_state_switch(t, teken_state_init);
382 return (1);
383 }
384
385 t->t_stateflags |= TS_FIRSTDIGIT;
386 return (1);
387 } else {
388 if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
389 /* Finish off the last empty argument. */
390 t->t_nums[t->t_curnum] = 0;
391 t->t_curnum++;
392 } else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
393 /* Also count the last argument. */
394 t->t_curnum++;
395 }
396 }
397
398 return (0);
399}
400
401#include "teken_state.h"