Adding upstream version 3.50~pre5.
[syslinux-debian/hramrach.git] / com32 / lib / sys / ansi.c
blob64e7f34f4440b250d205e386fc12b66fdc884216
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
12 * conditions:
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 * ----------------------------------------------------------------------- */
29 * ansi.c
31 * ANSI character code engine
34 #include <string.h>
35 #include <colortbl.h>
36 #include "ansi.h"
38 static const struct term_state default_state =
40 .xy = { 0, 0 },
41 .cindex = 0, /* First color table entry */
42 .vtgraphics = 0,
43 .intensity = 1,
44 .underline = 0,
45 .blink = 0,
46 .reverse = 0,
47 .fg = 7,
48 .bg = 0,
49 .autocr = 0,
50 .saved_xy = { 0, 0 },
51 .cursor = 1,
52 .state = st_init,
53 .pvt = 0,
54 .nparms = 0,
55 .xy = { 0, 0 },
58 /* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
59 static const char decvt_to_cp437[] =
61 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361,
62 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
63 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302,
64 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00
67 void __ansi_init(const struct term_info *ti)
69 memcpy(ti->ts, &default_state, sizeof default_state);
72 void __ansi_putchar(const struct term_info *ti, uint8_t ch)
74 const struct ansi_ops *op = ti->op;
75 struct term_state *st = ti->ts;
76 const int rows = ti->rows;
77 const int cols = ti->cols;
78 struct curxy xy = st->xy;
80 switch ( st->state ) {
81 case st_init:
82 switch ( ch ) {
83 case 1:
84 st->state = st_soh;
85 break;
86 case '\b':
87 if ( xy.x > 0 ) xy.x--;
88 break;
89 case '\t':
91 int nsp = 8 - (xy.x & 7);
92 while ( nsp-- )
93 __ansi_putchar(ti, ' ');
95 return; /* Cursor already updated */
96 case '\n':
97 case '\v':
98 case '\f':
99 xy.y++;
100 if ( st->autocr )
101 xy.x = 0;
102 break;
103 case '\r':
104 xy.x = 0;
105 break;
106 case 127:
107 /* Ignore delete */
108 break;
109 case 14:
110 st->vtgraphics = 1;
111 break;
112 case 15:
113 st->vtgraphics = 0;
114 break;
115 case 27:
116 st->state = st_esc;
117 break;
118 default:
119 /* Print character */
120 if ( ch >= 32 ) {
121 if ( st->vtgraphics && (ch & 0xe0) == 0x60 )
122 ch = decvt_to_cp437[ch - 0x60];
124 op->write_char(xy.x, xy.y, ch, st);
125 xy.x++;
127 break;
129 break;
131 case st_esc:
132 switch ( ch ) {
133 case '%':
134 case '(':
135 case ')':
136 case '#':
137 /* Ignore this plus the subsequent character, allows
138 compatibility with Linux sequence to set charset */
139 break;
140 case '[':
141 st->state = st_csi;
142 st->nparms = st->pvt = 0;
143 memset(st->parms, 0, sizeof st->parms);
144 break;
145 case 'c':
146 /* Reset terminal */
147 memcpy(&st, &default_state, sizeof st);
148 op->erase(st, 0, 0, cols-1, rows-1);
149 xy.x = xy.y = 0;
150 st->state = st_init;
151 break;
152 default:
153 /* Ignore sequence */
154 st->state = st_init;
155 break;
157 break;
159 case st_csi:
161 int p0 = st->parms[0] ? st->parms[0] : 1;
163 if ( ch >= '0' && ch <= '9' ) {
164 st->parms[st->nparms] = st->parms[st->nparms]*10 + (ch-'0');
165 } else if ( ch == ';' ) {
166 st->nparms++;
167 if ( st->nparms >= ANSI_MAX_PARMS )
168 st->nparms = ANSI_MAX_PARMS-1;
169 break;
170 } else if ( ch == '?' ) {
171 st->pvt = 1;
172 } else {
173 switch ( ch ) {
174 case 'A':
176 int y = xy.y - p0;
177 xy.y = (y < 0) ? 0 : y;
179 break;
180 case 'B':
182 int y = xy.y + p0;
183 xy.y = (y >= rows) ? rows-1 : y;
185 break;
186 case 'C':
188 int x = xy.x + p0;
189 xy.x = (x >= cols) ? cols-1 : x;
191 break;
192 case 'D':
194 int x = xy.x - p0;
195 xy.x = (x < 0) ? 0 : x;
197 break;
198 case 'E':
200 int y = xy.y + p0;
201 xy.y = (y >= rows) ? rows-1 : y;
202 xy.x = 0;
204 break;
205 case 'F':
207 int y = xy.y - p0;
208 xy.y = (y < 0) ? 0 : y;
209 xy.x = 0;
211 break;
212 case 'G':
213 case '\'':
215 int x = st->parms[0] - 1;
216 xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
218 break;
219 case 'H':
220 case 'f':
222 int y = st->parms[0] - 1;
223 int x = st->parms[1] - 1;
225 xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
226 xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;
228 break;
229 case 'J':
231 switch ( st->parms[0] ) {
232 case 0:
233 op->erase(st, xy.x, xy.y, cols-1, xy.y);
234 if ( xy.y < rows-1 )
235 op->erase(st, 0, xy.y+1, cols-1, rows-1);
236 break;
238 case 1:
239 if ( xy.y > 0 )
240 op->erase(st, 0, 0, cols-1, xy.y-1);
241 if ( xy.y > 0 )
242 op->erase(st, 0, xy.y, xy.x-1, xy.y);
243 break;
245 case 2:
246 op->erase(st, 0, 0, cols-1, rows-1);
247 break;
249 default:
250 /* Ignore */
251 break;
254 break;
255 case 'K':
257 switch ( st->parms[0] ) {
258 case 0:
259 op->erase(st, xy.x, xy.y, cols-1, xy.y);
260 break;
262 case 1:
263 if ( xy.x > 0 )
264 op->erase(st, 0, xy.y, xy.x-1, xy.y);
265 break;
267 case 2:
268 op->erase(st, 0, xy.y, cols-1, xy.y);
269 break;
271 default:
272 /* Ignore */
273 break;
276 break;
277 case 'h':
278 case 'l':
280 int set = (ch == 'h');
281 switch ( st->parms[0] ) {
282 case 20:
283 st->autocr = set;
284 break;
285 case 25:
286 st->cursor = set;
287 op->showcursor(st);
288 break;
289 default:
290 /* Ignore */
291 break;
294 break;
295 case 'm':
297 static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
299 int i;
300 for ( i = 0 ; i <= st->nparms ; i++ ) {
301 int a = st->parms[i];
302 switch ( a ) {
303 case 0:
304 st->fg = 7;
305 st->bg = 0;
306 st->intensity = 1;
307 st->underline = 0;
308 st->blink = 0;
309 st->reverse = 0;
310 break;
311 case 1:
312 st->intensity = 2;
313 break;
314 case 2:
315 st->intensity = 0;
316 break;
317 case 4:
318 st->underline = 1;
319 break;
320 case 5:
321 st->blink = 1;
322 break;
323 case 7:
324 st->reverse = 1;
325 break;
326 case 21:
327 case 22:
328 st->intensity = 1;
329 break;
330 case 24:
331 st->underline = 0;
332 break;
333 case 25:
334 st->blink = 0;
335 break;
336 case 27:
337 st->reverse = 0;
338 break;
339 case 30 ... 37:
340 st->fg = ansi2pc[a-30];
341 break;
342 case 38:
343 st->fg = 7;
344 st->underline = 1;
345 break;
346 case 39:
347 st->fg = 7;
348 st->underline = 0;
349 break;
350 case 40 ... 47:
351 st->bg = ansi2pc[a-40];
352 break;
353 case 49:
354 st->bg = 7;
355 break;
356 default:
357 /* Do nothing */
358 break;
362 break;
363 case 's':
364 st->saved_xy = xy;
365 break;
366 case 'u':
367 xy = st->saved_xy;
368 break;
369 default: /* Includes CAN and SUB */
370 break; /* Drop unknown sequence */
372 st->state = st_init;
375 break;
377 case st_soh:
378 if ( ch == '#' )
379 st->state = st_sohc;
380 else
381 st->state = st_init;
382 break;
384 case st_sohc:
386 int n = (unsigned char)ch - '0';
387 if (n < 10) {
388 st->parms[0] = n*10;
389 st->state = st_sohc1;
390 } else {
391 st->state = st_init;
394 break;
396 case st_sohc1:
398 int n = (unsigned char)ch - '0';
399 const char *p;
401 if (n < 10) {
402 st->parms[0] += n;
403 if (st->parms[0] < console_color_table_size) {
404 /* Set the color table index */
405 st->cindex = st->parms[0];
407 /* See if there are any other attributes we care about */
408 p = console_color_table[st->parms[0]].ansi;
409 st->state = st_esc;
410 __ansi_putchar(ti, '[');
411 __ansi_putchar(ti, '0');
412 __ansi_putchar(ti, ';');
413 while (*p)
414 __ansi_putchar(ti, *p++);
415 __ansi_putchar(ti, 'm');
419 st->state = st_init;
421 break;
424 /* If we fell off the end of the screen, adjust */
425 if ( xy.x >= cols ) {
426 xy.x = 0;
427 xy.y++;
429 while ( xy.y >= rows ) {
430 xy.y--;
431 op->scroll_up(st);
434 /* Update cursor position */
435 op->set_cursor(xy.x, xy.y, st->cursor);
436 st->xy = xy;