FreeNOS
teken.c
Go to the documentation of this file.
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$
27 */
28
29#define __unused __attribute((unused))
30#include <sys/types.h>
31#include <Config.h>
32#include <stdio.h>
33#include <string.h>
34#include <unistd.h>
35
36#ifdef DEBUG
37#define teken_assert(x) \
38 if (!((x))) { \
39 printf("%s:%d *** assertion `%s' failed\n", __FILE__, __FUNC__, #x); \
40 exit(EXIT_FAILURE); \
41 }
42#else
43#define teken_assert(x)
44#endif /* DEBUG */
45
46#define teken_printf(x,...) do { \
47 if (df != NULL) \
48 printf(x, ## __VA_ARGS__); \
49} while (0)
50
51/* debug messages */
52static FILE *df;
53
54#include "teken.h"
55
56#ifdef TEKEN_UTF8
57#include "teken_wcwidth.h"
58#else /* !TEKEN_UTF8 */
59#ifdef TEKEN_XTERM
60#define teken_wcwidth(c) ((c <= 0x1B) ? -1 : 1)
61#else /* !TEKEN_XTERM */
62#define teken_wcwidth(c) (1)
63#endif /* TEKEN_XTERM */
64#endif /* TEKEN_UTF8 */
65
66#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
67#include "teken_scs.h"
68#else /* !(TEKEN_XTERM && TEKEN_UTF8) */
69#define teken_scs_process(t, c) (c)
70#define teken_scs_restore(t)
71#define teken_scs_save(t)
72#define teken_scs_set(t, g, ts)
73#define teken_scs_switch(t, g)
74#endif /* TEKEN_XTERM && TEKEN_UTF8 */
75
76/* Private flags for t_stateflags. */
77#define TS_FIRSTDIGIT 0x01 /* First numeric digit in escape sequence. */
78#define TS_INSERT 0x02 /* Insert mode. */
79#define TS_AUTOWRAP 0x04 /* Autowrap. */
80#define TS_ORIGIN 0x08 /* Origin mode. */
81#ifdef TEKEN_XTERM
82#define TS_WRAPPED 0x10 /* Next character should be printed on col 0. */
83#else /* !TEKEN_XTERM */
84#define TS_WRAPPED 0x00 /* Simple line wrapping. */
85#endif /* TEKEN_XTERM */
86
87/* Character that blanks a cell. */
88#define BLANK ' '
89
91
92/*
93 * Wrappers for hooks.
94 */
95
96static inline void
98{
99
100 t->t_funcs->tf_bell(t->t_softc);
101}
102
103static inline void
112
113static inline void
115 const teken_attr_t *a)
116{
117
120
121 t->t_funcs->tf_putchar(t->t_softc, p, c, a);
122}
123
124static inline void
126 const teken_char_t c, const teken_attr_t *a)
127{
128
133
134 t->t_funcs->tf_fill(t->t_softc, r, c, a);
135}
136
137static inline void
150
151static inline void
152teken_funcs_param(teken_t *t, int cmd, unsigned int value)
153{
154
155 t->t_funcs->tf_param(t->t_softc, cmd, value);
156}
157
158static inline void
159teken_funcs_respond(teken_t *t, const void *buf, size_t len)
160{
161
162 t->t_funcs->tf_respond(t->t_softc, buf, len);
163}
164
165#include "teken_subr.h"
166#include "teken_subr_compat.h"
167
168/*
169 * Programming interface.
170 */
171
172void
173teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
174{
175 teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
176
177 t->t_funcs = tf;
178 t->t_softc = softc;
179
181
182 t->t_defattr.ta_format = 0;
186
187#ifdef TEKEN_UTF8
188 t->t_utf8_left = 0;
189#endif /* TEKEN_UTF8 */
190
191 teken_set_winsize(t, &tp);
192}
193
194static void
196{
197
198 switch (c) {
199 case '\0':
200 break;
201 case '\a':
203 break;
204 case '\b':
206 break;
207 case '\n':
208 case '\x0B':
210 break;
211 case '\x0C':
213 break;
214#if defined(TEKEN_XTERM) && defined(TEKEN_UTF8)
215 case '\x0E':
216 teken_scs_switch(t, 1);
217 break;
218 case '\x0F':
219 teken_scs_switch(t, 0);
220 break;
221#endif /* TEKEN_XTERM && TEKEN_UTF8 */
222 case '\r':
224 break;
225 case '\t':
227 break;
228 default:
229 t->t_nextstate(t, c);
230 break;
231 }
232
233 /* Post-processing assertions. */
242 /* Origin region has to be window size or the same as scrollreg. */
245 (t->t_originreg.ts_begin == 0 &&
247}
248
249static void
250teken_input_byte(teken_t *t, unsigned char c)
251{
252
253#ifdef TEKEN_UTF8
254 /*
255 * UTF-8 handling.
256 */
257 if ((c & 0x80) == 0x00) {
258 /* One-byte sequence. */
259 t->t_utf8_left = 0;
260 teken_input_char(t, c);
261 } else if ((c & 0xe0) == 0xc0) {
262 /* Two-byte sequence. */
263 t->t_utf8_left = 1;
264 t->t_utf8_partial = c & 0x1f;
265 } else if ((c & 0xf0) == 0xe0) {
266 /* Three-byte sequence. */
267 t->t_utf8_left = 2;
268 t->t_utf8_partial = c & 0x0f;
269 } else if ((c & 0xf8) == 0xf0) {
270 /* Four-byte sequence. */
271 t->t_utf8_left = 3;
272 t->t_utf8_partial = c & 0x07;
273 } else if ((c & 0xc0) == 0x80) {
274 if (t->t_utf8_left == 0)
275 return;
276 t->t_utf8_left--;
277 t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
278 if (t->t_utf8_left == 0) {
279 teken_printf("Got UTF-8 char %x\n", t->t_utf8_partial);
280 teken_input_char(t, t->t_utf8_partial);
281 }
282 }
283#else /* !TEKEN_UTF8 */
284 teken_input_char(t, c);
285#endif /* TEKEN_UTF8 */
286}
287
288void
289teken_input(teken_t *t, const void *buf, size_t len)
290{
291 const char *c = (const char *)buf;
292
293 while (len-- > 0)
294 teken_input_byte(t, *c++);
295}
296
297void
299{
300
301 /* XXX: bounds checking with originreg! */
304
305 t->t_cursor = *p;
306}
307
308const teken_attr_t *
310{
311
312 return (&t->t_curattr);
313}
314
315void
317{
318
319 t->t_curattr = *a;
320}
321
322const teken_attr_t *
324{
325
326 return (&t->t_defattr);
327}
328
329void
331{
332
333 t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
334}
335
336void
338{
339
340 t->t_winsize = *p;
341 /* XXX: bounds checking with cursor/etc! */
342 t->t_scrollreg.ts_begin = 0;
344 t->t_originreg = t->t_scrollreg;
345}
346
347/*
348 * State machine.
349 */
350
351static void
353{
354
355 t->t_nextstate = s;
356 t->t_curnum = 0;
358}
359
360static int
362{
363
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 == ';') {
382 t->t_nums[t->t_curnum] = 0;
383
384 /* Only allow a limited set of arguments. */
385 if (++t->t_curnum == T_NUMSIZE) {
387 return (1);
388 }
389
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"
A structure containing information about a file.
Definition stdio.h:61
teken_pos_t t_cursor
Definition teken.h:142
void * t_softc
Definition teken.h:133
unsigned int t_curnum
Definition teken.h:140
unsigned int t_nums[T_NUMSIZE]
Definition teken.h:139
const teken_funcs_t * t_funcs
Definition teken.h:132
teken_attr_t t_saved_curattr
Definition teken.h:145
teken_pos_t t_winsize
Definition teken.h:148
unsigned int t_stateflags
Definition teken.h:136
teken_attr_t t_defattr
Definition teken.h:147
teken_state_t * t_nextstate
Definition teken.h:135
teken_span_t t_scrollreg
Definition teken.h:151
teken_pos_t t_saved_cursor
Definition teken.h:144
teken_span_t t_originreg
Definition teken.h:153
teken_attr_t t_curattr
Definition teken.h:143
teken_color_t ta_fgcolor
Definition teken.h:78
teken_format_t ta_format
Definition teken.h:77
teken_color_t ta_bgcolor
Definition teken.h:79
tf_cursor_t * tf_cursor
Definition teken.h:115
tf_param_t * tf_param
Definition teken.h:119
tf_copy_t * tf_copy
Definition teken.h:118
tf_putchar_t * tf_putchar
Definition teken.h:116
tf_bell_t * tf_bell
Definition teken.h:114
tf_fill_t * tf_fill
Definition teken.h:117
tf_respond_t * tf_respond
Definition teken.h:120
teken_unit_t tp_col
Definition teken.h:70
teken_unit_t tp_row
Definition teken.h:69
teken_pos_t tr_begin
Definition teken.h:73
teken_pos_t tr_end
Definition teken.h:74
teken_unit_t ts_begin
Definition teken.h:82
teken_unit_t ts_end
Definition teken.h:83
static void teken_funcs_bell(teken_t *t)
Definition teken.c:97
static void teken_funcs_respond(teken_t *t, const void *buf, size_t len)
Definition teken.c:159
void teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
Definition teken.c:173
static int teken_state_numbers(teken_t *t, teken_char_t c)
Definition teken.c:361
static void teken_input_byte(teken_t *t, unsigned char c)
Definition teken.c:250
static void teken_state_switch(teken_t *t, teken_state_t *s)
Definition teken.c:352
void teken_input(teken_t *t, const void *buf, size_t len)
Definition teken.c:289
void teken_set_winsize(teken_t *t, const teken_pos_t *p)
Definition teken.c:337
static void teken_funcs_param(teken_t *t, int cmd, unsigned int value)
Definition teken.c:152
void teken_set_cursor(teken_t *t, const teken_pos_t *p)
Definition teken.c:298
static void teken_input_char(teken_t *t, teken_char_t c)
Definition teken.c:195
void teken_set_curattr(teken_t *t, const teken_attr_t *a)
Definition teken.c:316
static teken_state_t teken_state_init
Definition teken.c:90
void teken_set_defattr(teken_t *t, const teken_attr_t *a)
Definition teken.c:330
const teken_attr_t * teken_get_curattr(teken_t *t)
Definition teken.c:309
static void teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c, const teken_attr_t *a)
Definition teken.c:114
const teken_attr_t * teken_get_defattr(teken_t *t)
Definition teken.c:323
#define teken_printf(x,...)
Definition teken.c:46
#define TS_FIRSTDIGIT
Definition teken.c:77
#define teken_scs_switch(t, g)
Definition teken.c:73
static void teken_funcs_fill(teken_t *t, const teken_rect_t *r, const teken_char_t c, const teken_attr_t *a)
Definition teken.c:125
static void teken_funcs_cursor(teken_t *t)
Definition teken.c:104
#define teken_assert(x)
Definition teken.c:43
static FILE * df
Definition teken.c:52
static void teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
Definition teken.c:138
void teken_state_t(teken_t *, teken_char_t)
Definition teken.h:88
#define T_NUMSIZE
Definition teken.h:138
unsigned char teken_char_t
Definition teken.h:49
#define TC_BLACK
Definition teken.h:58
#define TC_WHITE
Definition teken.h:65
static void teken_subr_newline(teken_t *t)
Definition teken_subr.h:696
static void teken_subr_newpage(teken_t *t)
Definition teken_subr.h:711
static void teken_subr_horizontal_tab(teken_t *t)
Definition teken_subr.h:589
static void teken_subr_do_reset(teken_t *t)
Definition teken_subr.h:925
static void teken_subr_backspace(teken_t *t)
Definition teken_subr.h:202
static void teken_subr_carriage_return(teken_t *t)
Definition teken_subr.h:233
static void teken_subr_bell(teken_t *t)
Definition teken_subr.h:226