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 */
52 static 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 
96 static inline void
98 {
99 
100  t->t_funcs->tf_bell(t->t_softc);
101 }
102 
103 static inline void
105 {
106 
109 
110  t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
111 }
112 
113 static 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 
124 static 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 
137 static inline void
139 {
140 
147 
148  t->t_funcs->tf_copy(t->t_softc, r, p);
149 }
150 
151 static inline void
152 teken_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 
158 static inline void
159 teken_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 
172 void
173 teken_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 
194 static void
196 {
197 
198  switch (c) {
199  case '\0':
200  break;
201  case '\a':
202  teken_subr_bell(t);
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. */
244  t->t_originreg.ts_end == t->t_scrollreg.ts_end) ||
245  (t->t_originreg.ts_begin == 0 &&
246  t->t_originreg.ts_end == t->t_winsize.tp_row));
247 }
248 
249 static void
250 teken_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 
288 void
289 teken_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 
297 void
299 {
300 
301  /* XXX: bounds checking with originreg! */
304 
305  t->t_cursor = *p;
306 }
307 
308 const teken_attr_t *
310 {
311 
312  return (&t->t_curattr);
313 }
314 
315 void
317 {
318 
319  t->t_curattr = *a;
320 }
321 
322 const teken_attr_t *
324 {
325 
326  return (&t->t_defattr);
327 }
328 
329 void
331 {
332 
333  t->t_curattr = t->t_saved_curattr = t->t_defattr = *a;
334 }
335 
336 void
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 
351 static void
353 {
354 
355  t->t_nextstate = s;
356  t->t_curnum = 0;
358 }
359 
360 static 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) {
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) {
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"
teken_attr_t::ta_format
teken_format_t ta_format
Definition: teken.h:77
teken_state_t
void teken_state_t(teken_t *, teken_char_t)
Definition: teken.h:88
teken_funcs_fill
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
teken_subr_carriage_return
static void teken_subr_carriage_return(teken_t *t)
Definition: teken_subr.h:233
__teken::t_scrollreg
teken_span_t t_scrollreg
Definition: teken.h:151
teken_subr_newpage
static void teken_subr_newpage(teken_t *t)
Definition: teken_subr.h:711
teken_subr_do_reset
static void teken_subr_do_reset(teken_t *t)
Definition: teken_subr.h:925
teken_funcs_copy
static void teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
Definition: teken.c:138
teken_span_t::ts_begin
teken_unit_t ts_begin
Definition: teken.h:82
teken_subr.h
teken_funcs_param
static void teken_funcs_param(teken_t *t, int cmd, unsigned int value)
Definition: teken.c:152
TC_BLACK
#define TC_BLACK
Definition: teken.h:58
teken_input_byte
static void teken_input_byte(teken_t *t, unsigned char c)
Definition: teken.c:250
types.h
teken_subr_compat.h
teken_attr_t::ta_fgcolor
teken_color_t ta_fgcolor
Definition: teken.h:78
string.h
teken_subr_backspace
static void teken_subr_backspace(teken_t *t)
Definition: teken_subr.h:202
teken_funcs_bell
static void teken_funcs_bell(teken_t *t)
Definition: teken.c:97
__teken::t_cursor
teken_pos_t t_cursor
Definition: teken.h:142
TS_FIRSTDIGIT
#define TS_FIRSTDIGIT
Definition: teken.c:77
__teken::t_winsize
teken_pos_t t_winsize
Definition: teken.h:148
teken_get_curattr
const teken_attr_t * teken_get_curattr(teken_t *t)
Definition: teken.c:309
teken_funcs_putchar
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
teken_get_defattr
const teken_attr_t * teken_get_defattr(teken_t *t)
Definition: teken.c:323
teken_printf
#define teken_printf(x,...)
Definition: teken.c:46
teken_funcs_t::tf_copy
tf_copy_t * tf_copy
Definition: teken.h:118
teken_scs.h
teken_subr_newline
static void teken_subr_newline(teken_t *t)
Definition: teken_subr.h:696
teken_attr_t
Definition: teken.h:76
__teken::t_curnum
unsigned int t_curnum
Definition: teken.h:140
teken_rect_t::tr_end
teken_pos_t tr_end
Definition: teken.h:74
teken_set_cursor
void teken_set_cursor(teken_t *t, const teken_pos_t *p)
Definition: teken.c:298
teken_funcs_t::tf_respond
tf_respond_t * tf_respond
Definition: teken.h:120
__teken::t_stateflags
unsigned int t_stateflags
Definition: teken.h:136
teken_attr_t::ta_bgcolor
teken_color_t ta_bgcolor
Definition: teken.h:79
teken_set_curattr
void teken_set_curattr(teken_t *t, const teken_attr_t *a)
Definition: teken.c:316
teken_pos_t::tp_col
teken_unit_t tp_col
Definition: teken.h:70
teken_funcs_t::tf_putchar
tf_putchar_t * tf_putchar
Definition: teken.h:116
teken_funcs_respond
static void teken_funcs_respond(teken_t *t, const void *buf, size_t len)
Definition: teken.c:159
teken_set_winsize
void teken_set_winsize(teken_t *t, const teken_pos_t *p)
Definition: teken.c:337
teken_funcs_t
Definition: teken.h:113
teken_subr_bell
static void teken_subr_bell(teken_t *t)
Definition: teken_subr.h:226
teken_state_init
static teken_state_t teken_state_init
Definition: teken.c:90
teken_input
void teken_input(teken_t *t, const void *buf, size_t len)
Definition: teken.c:289
teken_subr_horizontal_tab
static void teken_subr_horizontal_tab(teken_t *t)
Definition: teken_subr.h:589
teken.h
stdio.h
teken_funcs_cursor
static void teken_funcs_cursor(teken_t *t)
Definition: teken.c:104
teken_init
void teken_init(teken_t *t, const teken_funcs_t *tf, void *softc)
Definition: teken.c:173
teken_state_numbers
static int teken_state_numbers(teken_t *t, teken_char_t c)
Definition: teken.c:361
__teken::t_saved_cursor
teken_pos_t t_saved_cursor
Definition: teken.h:144
teken_assert
#define teken_assert(x)
Definition: teken.c:43
__teken::t_softc
void * t_softc
Definition: teken.h:133
teken_funcs_t::tf_param
tf_param_t * tf_param
Definition: teken.h:119
teken_char_t
unsigned char teken_char_t
Definition: teken.h:49
teken_pos_t::tp_row
teken_unit_t tp_row
Definition: teken.h:69
T_NUMSIZE
#define T_NUMSIZE
Definition: teken.h:138
teken_rect_t::tr_begin
teken_pos_t tr_begin
Definition: teken.h:73
df
static FILE * df
Definition: teken.c:52
teken_wcwidth.h
teken_state_switch
static void teken_state_switch(teken_t *t, teken_state_t *s)
Definition: teken.c:352
unistd.h
__teken
Definition: teken.h:131
teken_state.h
__teken::t_saved_curattr
teken_attr_t t_saved_curattr
Definition: teken.h:145
__teken::t_originreg
teken_span_t t_originreg
Definition: teken.h:153
__teken::t_nums
unsigned int t_nums[T_NUMSIZE]
Definition: teken.h:139
teken_funcs_t::tf_cursor
tf_cursor_t * tf_cursor
Definition: teken.h:115
__teken::t_nextstate
teken_state_t * t_nextstate
Definition: teken.h:135
teken_pos_t
Definition: teken.h:68
teken_funcs_t::tf_fill
tf_fill_t * tf_fill
Definition: teken.h:117
__teken::t_defattr
teken_attr_t t_defattr
Definition: teken.h:147
teken_input_char
static void teken_input_char(teken_t *t, teken_char_t c)
Definition: teken.c:195
FILE
A structure containing information about a file.
Definition: stdio.h:60
teken_funcs_t::tf_bell
tf_bell_t * tf_bell
Definition: teken.h:114
teken_scs_switch
#define teken_scs_switch(t, g)
Definition: teken.c:73
__teken::t_funcs
const teken_funcs_t * t_funcs
Definition: teken.h:132
teken_set_defattr
void teken_set_defattr(teken_t *t, const teken_attr_t *a)
Definition: teken.c:330
TC_WHITE
#define TC_WHITE
Definition: teken.h:65
teken_span_t::ts_end
teken_unit_t ts_end
Definition: teken.h:83
__teken::t_curattr
teken_attr_t t_curattr
Definition: teken.h:143
teken_rect_t
Definition: teken.h:72