source: bootcd/isolinux/syslinux-6.03/com32/lib/sys/ansi.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 9.0 KB
RevLine 
[e16e8f2]1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
4 *
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:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
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.
25 *
26 * ----------------------------------------------------------------------- */
27
28/*
29 * ansi.c
30 *
31 * ANSI character code engine
32 */
33
34#include <string.h>
35#include <colortbl.h>
36#include "ansi.h"
37
38static 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,
55};
56
57/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
58static 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
63};
64
65void __ansi_init(const struct term_info *ti)
66{
67    memcpy(ti->ts, &default_state, sizeof default_state);
68}
69
70void __ansi_putchar(const struct term_info *ti, uint8_t ch)
71{
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;
77
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':
93            {
94                int nsp = 8 - (xy.x & 7);
95                while (nsp--)
96                    __ansi_putchar(ti, ' ');
97            }
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];
126
127                op->write_char(xy.x, xy.y, ch, st);
128                xy.x++;
129            }
130            break;
131        }
132        break;
133
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;
160        }
161        break;
162
163    case st_csi:
164        {
165            int p0 = st->parms[0] ? st->parms[0] : 1;
166
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':
179                    {
180                        int y = xy.y - p0;
181                        xy.y = (y < 0) ? 0 : y;
182                    }
183                    break;
184                case 'B':
185                    {
186                        int y = xy.y + p0;
187                        xy.y = (y >= rows) ? rows - 1 : y;
188                    }
189                    break;
190                case 'C':
191                    {
192                        int x = xy.x + p0;
193                        xy.x = (x >= cols) ? cols - 1 : x;
194                    }
195                    break;
196                case 'D':
197                    {
198                        int x = xy.x - p0;
199                        xy.x = (x < 0) ? 0 : x;
200                    }
201                    break;
202                case 'E':
203                    {
204                        int y = xy.y + p0;
205                        xy.y = (y >= rows) ? rows - 1 : y;
206                        xy.x = 0;
207                    }
208                    break;
209                case 'F':
210                    {
211                        int y = xy.y - p0;
212                        xy.y = (y < 0) ? 0 : y;
213                        xy.x = 0;
214                    }
215                    break;
216                case 'G':
217                case '\'':
218                    {
219                        int x = st->parms[0] - 1;
220                        xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x;
221                    }
222                    break;
223                case 'H':
224                case 'f':
225                    {
226                        int y = st->parms[0] - 1;
227                        int x = st->parms[1] - 1;
228
229                        xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x;
230                        xy.y = (y >= rows) ? rows - 1 : (y < 0) ? 0 : y;
231                    }
232                    break;
233                case 'J':
234                    {
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;
241
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;
248
249                        case 2:
250                            op->erase(st, 0, 0, cols - 1, rows - 1);
251                            break;
252
253                        default:
254                            /* Ignore */
255                            break;
256                        }
257                    }
258                    break;
259                case 'K':
260                    {
261                        switch (st->parms[0]) {
262                        case 0:
263                            op->erase(st, xy.x, xy.y, cols - 1, xy.y);
264                            break;
265
266                        case 1:
267                            if (xy.x > 0)
268                                op->erase(st, 0, xy.y, xy.x - 1, xy.y);
269                            break;
270
271                        case 2:
272                            op->erase(st, 0, xy.y, cols - 1, xy.y);
273                            break;
274
275                        default:
276                            /* Ignore */
277                            break;
278                        }
279                    }
280                    break;
281                case 'h':
282                case 'l':
283                {
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;
299                    }
300                    break;
301                }
302                case 'm':
303                    {
304                        static const int ansi2pc[8] =
305                            { 0, 4, 2, 6, 1, 5, 3, 7 };
306
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;
367                            }
368                        }
369                    }
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 */
379                }
380                st->state = st_init;
381            }
382        }
383        break;
384
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;
392
393    case st_tblc:
394        {
395            unsigned int n = (unsigned char)ch - '0';
396            const char *p;
397
398            if (n < 10) {
399                st->parms[1] = st->parms[1] * 10 + n;
400
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];
405
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');
416                        }
417                    }
418                    st->state = st_init;
419                }
420            } else {
421                st->state = st_init;
422            }
423        }
424        break;
425    }
426
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;
434        }
435    }
436    while (xy.y >= rows) {
437        xy.y--;
438        op->scroll_up(st);
439    }
440
441    /* Update cursor position */
442    op->set_cursor(xy.x, xy.y, st->cursor);
443    st->xy = xy;
444}
Note: See TracBrowser for help on using the repository browser.