Add support for line drawing characters and the alternate character set.
[coreboot.git] / payloads / libpayload / curses / tinycurses.c
index 5e707c47db893a7385f01066278e5c69d1c59ad4..86f07818df4b27db2dbb14326bab83f1d0cb6449 100644 (file)
@@ -2,6 +2,7 @@
  * This file is part of the libpayload project.
  *
  * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 2008 Ulf Jordan <jordan@chalmers.se>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -66,7 +67,7 @@ static WINDOW window_list[MAX_WINDOWS];
 static int window_count = 1;
 
 // struct ldat foo;
-static struct ldat ldat_list[3];
+static struct ldat ldat_list[MAX_WINDOWS][SCREEN_Y];
 static int ldat_count = 0;
 
 /* One item bigger than SCREEN_X to reverse place for a NUL byte. */
@@ -79,8 +80,8 @@ int COLOR_PAIRS;
 WINDOW *stdscr;
 WINDOW *curscr;
 WINDOW *newscr;
-int LINES;
-int COLS;
+int LINES = 25;
+int COLS = 80;
 int TABSIZE;
 int ESCDELAY;
 // char ttytype[];
@@ -88,6 +89,69 @@ int ESCDELAY;
 SCREEN *SP;
 chtype acs_map[128];
 
+/* See terminfo(5). */
+chtype fallback_acs_map[128] =
+       {
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    '>',    '<',    '^',    'v',    ' ',
+       '#',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',    ' ',
+       '+',    ':',    ' ',    ' ',    ' ',    ' ',    '\\',   '#',
+       '#',    '#',    '+',    '+',    '+',    '+',    '+',    '~',
+       '-',    '-',    '-',    '_',    '+',    '+',    '+',    '+',
+       '|',    '<',    '>',    '*',    '!',    'f',    'o',    ' ',
+       };
+
+/* See acsc of vt100. */
+chtype serial_acs_map[128] =
+       {
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       '`',    'a',    0,      0,      0,      0,      'f',    'g',
+       0,      0,      'j',    'k',    'l',    'm',    'n',    'o',
+       'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
+       'x',    'y',    'z',    '{',    '|',    '}',    '~',    0,
+       };
+
+/* See acsc of linux. */
+chtype console_acs_map[128] =
+       {
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      '\020', '\021', '\030', '\031', 0,
+       '\333', 0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       '\004', '\261', 0,      0,      0,      0,      '\370', '\361',
+       '\260', '\316', '\331', '\277', '\332', '\300', '\305', '~',
+       '\304', '\304', '\304', '_',    '\303', '\264', '\301', '\302',
+       '\263', '\363', '\362', '\342', '\330', '\234', '\376', 0,
+       };
+
 // FIXME: Ugly (and insecure!) hack!
 char sprintf_tmp[1024];
 
@@ -202,7 +266,7 @@ int endwin(void)
 // char erasechar (void) {}
 // void filter (void) {}
 // int flash(void) {}
-// int flushinp (void) {}
+int flushinp(void) { /* TODO */ return 0; }
 // WINDOW *getwin (FILE *) {}
 bool has_colors (void) { /* TODO */ return(*(bool *)0); }
 // bool has_ic (void) {}
@@ -213,15 +277,23 @@ void immedok(WINDOW *win, bool flag) { win->_immed = flag; }
 /** Note: Must _not_ be called twice! */
 WINDOW *initscr(void)
 {
-       int x, y;
+       int x, y, i;
 
        // newterm(name, stdout, stdin);
        // def_prog_mode();
 
+       for (i = 0; i < 128; i++)
+         acs_map[i] = (chtype) i | A_ALTCHARSET;
+
+       if (curses_flags & F_ENABLE_SERIAL) {
+               serial_clear();
+       }
+
        if (curses_flags & F_ENABLE_CONSOLE) {
-               /* Clear the screen and kill the cursor. */
-               vga_clear();
-               vga_cursor_enable(0);
+               /* Clear the screen and kill the cursor */
+
+               video_console_clear();
+               video_console_cursor_enable(0);
        }
 
        // Speaker init?
@@ -305,7 +377,7 @@ WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
        win->_begx = begx;
        // win->_yoffset = SP->_topstolen;
 
-       win->_line = &ldat_list[ldat_count++];
+       win->_line = ldat_list[ldat_count++];
 
        /* FIXME: Is this right? Should the window attributes be normal? */
        win->_color = PAIR_NUMBER(0);
@@ -318,12 +390,11 @@ WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
        return win;
 }
 /* D */ int nl(void) { SP->_nl = TRUE; return OK; }
-int nocbreak(void) { /* TODO */ return(*(int *)0); }
 /* D */ int noecho(void) { SP->_echo = FALSE; return OK; }
 /* D */ int nonl(void) { SP->_nl = FALSE; return OK; }
 // void noqiflush (void) {}
 // int noraw (void) {}
-// int notimeout (WINDOW *,bool) {}
+/* D */ int notimeout (WINDOW *win, bool f) { win->_notimeout = f; return OK; }
 // int overlay (const WINDOW*,WINDOW *) {}
 // int overwrite (const WINDOW*,WINDOW *) {}
 // int pair_content (short,short*,short*) {}
@@ -405,12 +476,12 @@ int waddch(WINDOW *win, const chtype ch)
        // NCURSES_CH_T wch;
        // SetChar2(wch, ch);
 
-       win->_line[win->_cury].text[win->_curx].chars[0] = ch;
-
-       /* Use the window attributes - perhaps we also pull attributes from
-          the ch itself, I don't know */
+       win->_line[win->_cury].text[win->_curx].chars[0] =
+               ((ch) & (chtype)A_CHARTEXT);
 
        win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
+       win->_line[win->_cury].text[win->_curx].attr |=
+               ((ch) & (chtype)A_ATTRIBUTES);
        win->_curx++;   // FIXME
 
        // if (win && (waddch_nosync(win, wch) != ERR)) {
@@ -464,7 +535,39 @@ int wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
 }
 // int wbkgd (WINDOW *, chtype) {}
 void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ }
-// int wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype) {}
+
+int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs,
+               chtype tl, chtype tr, chtype bl, chtype br)
+{
+       int x, y;
+
+       for(y = 0; y <= win->_maxy; y++) {
+
+               if (y == 0) {
+                        mvwaddch(win, y, 0, tl);
+
+                       for(x = 1; x < win->_maxx; x++)
+                               mvwaddch(win, y, x, ts);
+
+                       mvwaddch(win, y, win->_maxx, tr);
+               }
+               else if (y == win->_maxy) {
+                       mvwaddch(win, y, 0, bl);
+
+                       for(x = 1; x < win->_maxx; x++)
+                               mvwaddch(win, y, x, bs);
+
+                       mvwaddch(win, y, win->_maxx, br);
+               }
+               else {
+                       mvwaddch(win, y, 0, ls);
+                       mvwaddch(win, y, win->_maxx, rs);
+               }
+       }
+
+       return OK;
+}
+
 // int wchgat (WINDOW *, int, attr_t, short, const void *) {}
 /* D */ int wclear(WINDOW *win)
 {
@@ -491,8 +594,8 @@ int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
 int werase(WINDOW *win)
 {
        int x, y;
-       for (y = 0; y < win->_maxy; y++) {
-               for (x = 0; x < win->_maxx; x++) {
+       for (y = 0; y <= win->_maxy; y++) {
+               for (x = 0; x <= win->_maxx; x++) {
                        win->_line[y].text[x].chars[0] = ' ';
                        win->_line[y].text[x].attr = WINDOW_ATTRS(win);
                }
@@ -554,20 +657,71 @@ int whline(WINDOW *win, chtype ch, int n)
        win->_flags |= _HASMOVED;
        return OK;
 }
+
 int wnoutrefresh(WINDOW *win)
 {
        // FIXME.
+       int serial_is_bold = 0;
+       int serial_is_altcharset = 0;
+
        int x, y;
+       chtype ch;
+       int need_altcharset;
+
+       serial_end_bold();
+       serial_end_altcharset();
+
+       for (y = 0; y <= win->_maxy; y++) {
+
+               /* Position the serial cursor */
+
+               if (curses_flags & F_ENABLE_SERIAL)
+                       serial_set_cursor(win->_begy + y, win->_begx);
+
+               for (x = 0; x <= win->_maxx; x++) {
+                       attr_t attr = win->_line[y].text[x].attr;
+
+                       unsigned int c =
+                               ((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
 
-       for (y = 0; y < win->_maxy; y++) {
-               for (x = 0; x < win->_maxx; x++) {
-                       if (curses_flags & F_ENABLE_SERIAL)
-                               serial_putchar(win->_line[y].text[x].chars[0]);
+                       if (curses_flags & F_ENABLE_SERIAL) {
+                               ch = win->_line[y].text[x].chars[0];
+
+                               if (attr & A_BOLD) {
+                                       if (!serial_is_bold) {
+                                               serial_start_bold();
+                                               serial_is_bold = 1;
+                                       }
+                               }
+                               else {
+                                       if (serial_is_bold) {
+                                               serial_end_bold();
+                                               serial_is_bold = 0;
+                                       }
+                               }
+
+                               need_altcharset = 0;
+                               if (attr & A_ALTCHARSET) {
+                                       if (serial_acs_map[ch & 0x7f]) {
+                                               ch = serial_acs_map[ch & 0x7f];
+                                               need_altcharset = 1;
+                                       } else
+                                               ch = fallback_acs_map[ch & 0x7f];
+                               }
+                               if (need_altcharset && !serial_is_altcharset) {
+                                       serial_start_altcharset();
+                                       serial_is_altcharset = 1;
+                               }
+                               if (!need_altcharset && serial_is_altcharset) {
+                                       serial_end_altcharset();
+                                       serial_is_altcharset = 0;
+                               }
+
+                               serial_putchar(ch);
+                       }
 
                        if (curses_flags & F_ENABLE_CONSOLE) {
-                               attr_t attr = win->_line[y].text[x].attr;
-                               unsigned int c =
-                                 ((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
+                               ch = win->_line[y].text[x].chars[0];
 
                                /* Handle some of the attributes. */
                                if (attr & A_BOLD)
@@ -579,6 +733,12 @@ int wnoutrefresh(WINDOW *win)
                                        c = (c >> 4) & 0xf00;
                                        c |= tmp << 12;
                                }
+                               if (attr & A_ALTCHARSET) {
+                                       if (console_acs_map[ch & 0x7f])
+                                               ch = console_acs_map[ch & 0x7f];
+                                       else
+                                               ch = fallback_acs_map[ch & 0x7f];
+                               }
 
                                /*
                                 * FIXME: Somewhere along the line, the
@@ -586,8 +746,8 @@ int wnoutrefresh(WINDOW *win)
                                 * For now grab just the 8 bit character,
                                 * but this will break wide characters!
                                 */
-                               c |= (chtype) (win->_line[y].text[x].chars[0] & 0xff);
-                               vga_putc(y, x, c);
+                               c |= (chtype) (ch & 0xff);
+                               video_console_putc(win->_begy + y, win->_begx + x, c);
                        }
                }
        }
@@ -656,7 +816,7 @@ int wsetscrreg(WINDOW *win, int top, int bottom)
 }
 // void wsyncdown (WINDOW *) {}
 // void wsyncup (WINDOW *) {}
-// void wtimeout (WINDOW *,int) {}
+/* D */ void wtimeout(WINDOW *win, int delay) { win->_delay = delay; }
 /* D */ int wtouchln(WINDOW *win, int y, int n, int changed)
 {
        int i;