Add memtest support.
[syslinux-debian/hramrach.git] / com32 / lib / sys / ansi.c
blobf73c03e236826206bb26c02b966a83989eaadcd2
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004-2008 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 = {
39 .state = st_init,
40 .pvt = false,
41 .nparms = 0,
42 .xy = {0, 0},
43 .cindex = 0, /* First color table entry */
44 .vtgraphics = false,
45 .intensity = 1,
46 .underline = false,
47 .blink = false,
48 .reverse = false,
49 .fg = 7,
50 .bg = 0,
51 .autocr = true, /* Mimic \n -> \r\n conversion by default */
52 .autowrap = true, /* Wrap lines by default */
53 .saved_xy = {0, 0},
54 .cursor = true,
57 /* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
58 static const char decvt_to_cp437[] = {
59 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361,
60 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
61 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302,
62 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00
65 void __ansi_init(const struct term_info *ti)
67 memcpy(ti->ts, &default_state, sizeof default_state);
70 void __ansi_putchar(const struct term_info *ti, uint8_t ch)
72 const struct ansi_ops *op = ti->op;
73 struct term_state *st = ti->ts;
74 const int rows = ti->rows;
75 const int cols = ti->cols;
76 struct curxy xy = st->xy;
78 switch (st->state) {
79 case st_init:
80 switch (ch) {
81 case 1 ... 5:
82 st->state = st_tbl;
83 st->parms[0] = ch;
84 break;
85 case '\a':
86 op->beep();
87 break;
88 case '\b':
89 if (xy.x > 0)
90 xy.x--;
91 break;
92 case '\t':
94 int nsp = 8 - (xy.x & 7);
95 while (nsp--)
96 __ansi_putchar(ti, ' ');
98 return; /* Cursor already updated */
99 case '\n':
100 case '\v':
101 case '\f':
102 xy.y++;
103 if (st->autocr)
104 xy.x = 0;
105 break;
106 case '\r':
107 xy.x = 0;
108 break;
109 case 127:
110 /* Ignore delete */
111 break;
112 case 14:
113 st->vtgraphics = 1;
114 break;
115 case 15:
116 st->vtgraphics = 0;
117 break;
118 case 27:
119 st->state = st_esc;
120 break;
121 default:
122 /* Print character */
123 if (ch >= 32) {
124 if (st->vtgraphics && (ch & 0xe0) == 0x60)
125 ch = decvt_to_cp437[ch - 0x60];
127 op->write_char(xy.x, xy.y, ch, st);
128 xy.x++;
130 break;
132 break;
134 case st_esc:
135 switch (ch) {
136 case '%':
137 case '(':
138 case ')':
139 case '#':
140 /* Ignore this plus the subsequent character, allows
141 compatibility with Linux sequence to set charset */
142 break;
143 case '[':
144 st->state = st_csi;
145 st->nparms = 0;
146 st->pvt = false;
147 memset(st->parms, 0, sizeof st->parms);
148 break;
149 case 'c':
150 /* Reset terminal */
151 memcpy(&st, &default_state, sizeof st);
152 op->erase(st, 0, 0, cols - 1, rows - 1);
153 xy.x = xy.y = 0;
154 st->state = st_init;
155 break;
156 default:
157 /* Ignore sequence */
158 st->state = st_init;
159 break;
161 break;
163 case st_csi:
165 int p0 = st->parms[0] ? st->parms[0] : 1;
167 if (ch >= '0' && ch <= '9') {
168 st->parms[st->nparms] = st->parms[st->nparms] * 10 + (ch - '0');
169 } else if (ch == ';') {
170 st->nparms++;
171 if (st->nparms >= ANSI_MAX_PARMS)
172 st->nparms = ANSI_MAX_PARMS - 1;
173 break;
174 } else if (ch == '?') {
175 st->pvt = true;
176 } else {
177 switch (ch) {
178 case 'A':
180 int y = xy.y - p0;
181 xy.y = (y < 0) ? 0 : y;
183 break;
184 case 'B':
186 int y = xy.y + p0;
187 xy.y = (y >= rows) ? rows - 1 : y;
189 break;
190 case 'C':
192 int x = xy.x + p0;
193 xy.x = (x >= cols) ? cols - 1 : x;
195 break;
196 case 'D':
198 int x = xy.x - p0;
199 xy.x = (x < 0) ? 0 : x;
201 break;
202 case 'E':
204 int y = xy.y + p0;
205 xy.y = (y >= rows) ? rows - 1 : y;
206 xy.x = 0;
208 break;
209 case 'F':
211 int y = xy.y - p0;
212 xy.y = (y < 0) ? 0 : y;
213 xy.x = 0;
215 break;
216 case 'G':
217 case '\'':
219 int x = st->parms[0] - 1;
220 xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x;
222 break;
223 case 'H':
224 case 'f':
226 int y = st->parms[0] - 1;
227 int x = st->parms[1] - 1;
229 xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x;
230 xy.y = (y >= rows) ? rows - 1 : (y < 0) ? 0 : y;
232 break;
233 case 'J':
235 switch (st->parms[0]) {
236 case 0:
237 op->erase(st, xy.x, xy.y, cols - 1, xy.y);
238 if (xy.y < rows - 1)
239 op->erase(st, 0, xy.y + 1, cols - 1, rows - 1);
240 break;
242 case 1:
243 if (xy.y > 0)
244 op->erase(st, 0, 0, cols - 1, xy.y - 1);
245 if (xy.y > 0)
246 op->erase(st, 0, xy.y, xy.x - 1, xy.y);
247 break;
249 case 2:
250 op->erase(st, 0, 0, cols - 1, rows - 1);
251 break;
253 default:
254 /* Ignore */
255 break;
258 break;
259 case 'K':
261 switch (st->parms[0]) {
262 case 0:
263 op->erase(st, xy.x, xy.y, cols - 1, xy.y);
264 break;
266 case 1:
267 if (xy.x > 0)
268 op->erase(st, 0, xy.y, xy.x - 1, xy.y);
269 break;
271 case 2:
272 op->erase(st, 0, xy.y, cols - 1, xy.y);
273 break;
275 default:
276 /* Ignore */
277 break;
280 break;
281 case 'h':
282 case 'l':
284 bool set = (ch == 'h');
285 switch (st->parms[0]) {
286 case 7: /* DECAWM */
287 st->autowrap = set;
288 break;
289 case 20: /* LNM */
290 st->autocr = set;
291 break;
292 case 25: /* DECTECM */
293 st->cursor = set;
294 op->showcursor(st);
295 break;
296 default:
297 /* Ignore */
298 break;
300 break;
302 case 'm':
304 static const int ansi2pc[8] =
305 { 0, 4, 2, 6, 1, 5, 3, 7 };
307 int i;
308 for (i = 0; i <= st->nparms; i++) {
309 int a = st->parms[i];
310 switch (a) {
311 case 0:
312 st->fg = 7;
313 st->bg = 0;
314 st->intensity = 1;
315 st->underline = 0;
316 st->blink = 0;
317 st->reverse = 0;
318 break;
319 case 1:
320 st->intensity = 2;
321 break;
322 case 2:
323 st->intensity = 0;
324 break;
325 case 4:
326 st->underline = 1;
327 break;
328 case 5:
329 st->blink = 1;
330 break;
331 case 7:
332 st->reverse = 1;
333 break;
334 case 21:
335 case 22:
336 st->intensity = 1;
337 break;
338 case 24:
339 st->underline = 0;
340 break;
341 case 25:
342 st->blink = 0;
343 break;
344 case 27:
345 st->reverse = 0;
346 break;
347 case 30 ... 37:
348 st->fg = ansi2pc[a - 30];
349 break;
350 case 38:
351 st->fg = 7;
352 st->underline = 1;
353 break;
354 case 39:
355 st->fg = 7;
356 st->underline = 0;
357 break;
358 case 40 ... 47:
359 st->bg = ansi2pc[a - 40];
360 break;
361 case 49:
362 st->bg = 7;
363 break;
364 default:
365 /* Do nothing */
366 break;
370 break;
371 case 's':
372 st->saved_xy = xy;
373 break;
374 case 'u':
375 xy = st->saved_xy;
376 break;
377 default: /* Includes CAN and SUB */
378 break; /* Drop unknown sequence */
380 st->state = st_init;
383 break;
385 case st_tbl:
386 st->parms[1] = 0;
387 if (ch == '#')
388 st->state = st_tblc;
389 else
390 st->state = st_init;
391 break;
393 case st_tblc:
395 unsigned int n = (unsigned char)ch - '0';
396 const char *p;
398 if (n < 10) {
399 st->parms[1] = st->parms[1] * 10 + n;
401 if (!--st->parms[0]) {
402 if (st->parms[1] < console_color_table_size) {
403 /* Set the color table index */
404 st->cindex = st->parms[1];
406 /* See if there are any other attributes we care about */
407 p = console_color_table[st->parms[1]].ansi;
408 if (p) {
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');
418 st->state = st_init;
420 } else {
421 st->state = st_init;
424 break;
427 /* If we fell off the end of the screen, adjust */
428 if (xy.x >= cols) {
429 if (st->autowrap) {
430 xy.x = 0;
431 xy.y++;
432 } else {
433 xy.x = cols - 1;
436 while (xy.y >= rows) {
437 xy.y--;
438 op->scroll_up(st);
441 /* Update cursor position */
442 op->set_cursor(xy.x, xy.y, st->cursor);
443 st->xy = xy;