libpayload: Support curses for serial
[coreboot.git] / payloads / libpayload / curses / tinycurses.c
index dc6b77818bf2fed14de40e5d531ec0bce4ff5daa..9e9b3cdec00796bd2b949762c1d4056f9868a794 100644 (file)
@@ -49,7 +49,7 @@
  *  - Only implements a small subset of the (n)curses functions.
  *  - Only implements very few sanity checks (for smaller code).
  *     - Thus: Don't do obviously stupid things in your code.
- *  - Doesn't implement the 'form', 'panel', and 'menu' extentions.
+ *  - Doesn't implement the 'form', 'panel', and 'menu' extensions.
  *  - Only implements C bindings (no C++, Ada95, or others).
  *  - Doesn't include wide character support.
  */
@@ -66,7 +66,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 +79,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[];
@@ -111,7 +111,7 @@ NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch)
 }
 
 /*
- * Implementations of most functions marked 'implemented' in tinycurses.h:
+ * Implementations of most functions marked 'implemented' in include/curses.h:
  */
 
 // int baudrate(void) {}
@@ -145,26 +145,29 @@ int delwin(WINDOW *win)
 }
 WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
 {
-       WINDOW *win;
+       WINDOW *win = NULL;
        int i;
        int flags = _SUBWIN;
 
        /* Make sure window fits inside the original one. */
-       if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0 || num_columns < 0)
-           return NULL;
+       if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0
+           || num_columns < 0)
+               return NULL;
+
        if (begy + num_lines > orig->_maxy + 1
            || begx + num_columns > orig->_maxx + 1)
-           return NULL;
+               return NULL;
 
        if (num_lines == 0)
-           num_lines = orig->_maxy + 1 - begy;
+               num_lines = orig->_maxy + 1 - begy;
 
        if (num_columns == 0)
-           num_columns = orig->_maxx + 1 - begx;
+               num_columns = orig->_maxx + 1 - begx;
 
        if (orig->_flags & _ISPAD)
-           flags |= _ISPAD;
+               flags |= _ISPAD;
 
+       // FIXME
        //// if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy,
        ////                        orig->_begx + begx, flags)) == 0)
        ////     return NULL;
@@ -175,7 +178,7 @@ WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
        win->_nc_bkgd = orig->_nc_bkgd;
 
        for (i = 0; i < num_lines; i++)
-           win->_line[i].text = &orig->_line[begy++].text[begx];
+               win->_line[i].text = &orig->_line[begy++].text[begx];
 
        win->_parent = orig;
 
@@ -199,9 +202,8 @@ 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) {}
 // bool has_il (void) {}
@@ -216,12 +218,15 @@ WINDOW *initscr(void)
        // newterm(name, stdout, stdin);
        // def_prog_mode();
 
-       if (curses_flags & F_ENABLE_CONSOLE) {
+       if (curses_flags & F_ENABLE_SERIAL) {
+               serial_clear();
+       }
 
-         /* Clear the screen and kill the cursor */
+       if (curses_flags & F_ENABLE_CONSOLE) {
+               /* Clear the screen and kill the cursor */
 
-         vga_clear();
-         vga_cursor_enable(0);
+               video_console_clear();
+               video_console_cursor_enable(0);
        }
 
        // Speaker init?
@@ -238,7 +243,6 @@ WINDOW *initscr(void)
 
        return stdscr;
 }
-
 // int intrflush (WINDOW *,bool) {}
 /* D */ bool isendwin(void) { return ((SP == NULL) ? FALSE : SP->_endwin); }
 // bool is_linetouched (WINDOW *,int) {}
@@ -306,25 +310,24 @@ 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);
+       /* FIXME: Is this right? Should the window attributes be normal? */
+       win->_color = PAIR_NUMBER(0);
        win->_attrs = A_NORMAL;
 
        for (i = 0; i < num_lines; i++)
-               win->_line[i].text = (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
+               win->_line[i].text =
+                    (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
 
        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*) {}
@@ -465,7 +468,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)
 {
@@ -479,7 +514,7 @@ int wclrtoeol(WINDOW *win) { /* TODO */ return(*(int *)0); }
 int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
 {
        if (!opts && (color_pair_number >= 0)
-               && (color_pair_number < COLOR_PAIRS)) {
+           && (color_pair_number < COLOR_PAIRS)) {
                SET_WINDOW_PAIR(win, color_pair_number);
                if_EXT_COLORS(win->_color = color_pair_number);
                return OK;
@@ -492,15 +527,14 @@ 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);
                }
        }
        return OK;
 }
-
 // int wgetnstr (WINDOW *,char *,int) {}
 int whline(WINDOW *win, chtype ch, int n)
 {
@@ -511,7 +545,7 @@ int whline(WINDOW *win, chtype ch, int n)
        start = win->_curx;
        end = start + n - 1;
        if (end > win->_maxx)
-           end = win->_maxx;
+               end = win->_maxx;
 
        CHANGED_RANGE(line, start, end);
 
@@ -526,8 +560,8 @@ int whline(WINDOW *win, chtype ch, int n)
        wch = _nc_render(win, wch);
 
        while (end >= start) {
-           line->text[end] = wch;
-           end--;
+               line->text[end] = wch;
+               end--;
        }
 
        //// _nc_synchook(win);
@@ -557,46 +591,73 @@ int whline(WINDOW *win, chtype ch, int n)
        return OK;
 }
 
-
 int wnoutrefresh(WINDOW *win)
 {
        // FIXME.
+       int serial_is_bold = 0;
+
        int x, y;
 
-       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]);
+       serial_end_bold();
 
-                       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;
+       for (y = 0; y <= win->_maxy; y++) {
 
-                               /* Handle some of the attributes */
+               /* 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;
+
+                       if (curses_flags & F_ENABLE_SERIAL) {
 
                                if (attr & A_BOLD) {
-                                       c |= 0x0800;
+                                       if (!serial_is_bold) {
+                                               serial_start_bold();
+                                               serial_is_bold = 1;
+                                       }
                                }
-                               if (attr & A_DIM) {
-                                       c &= ~0x800;
+                               else {
+                                       if (serial_is_bold) {
+                                               serial_end_bold();
+                                               serial_is_bold = 0;
+                                       }
                                }
+
+                               serial_putchar(win->_line[y].text[x].chars[0]);
+                       }
+
+                       if (curses_flags & F_ENABLE_CONSOLE) {
+
+                               /* Handle some of the attributes. */
+                               if (attr & A_BOLD)
+                                       c |= 0x0800;
+                               if (attr & A_DIM)
+                                       c &= ~0x800;
                                if (attr & A_REVERSE) {
-                                       unsigned char tmp = (c >> 8) & 0xF;
-                                       c = (c >> 4) & 0xF00;
+                                       unsigned char tmp = (c >> 8) & 0xf;
+                                       c = (c >> 4) & 0xf00;
                                        c |= tmp << 12;
                                }
 
-                               c |= win->_line[y].text[x].chars[0];
-
-
-                               vga_putc(y, x, c);
+                               /*
+                                * FIXME: Somewhere along the line, the
+                                * character value is getting sign-extented.
+                                * For now grab just the 8 bit character,
+                                * but this will break wide characters!
+                                */
+                               c |= (chtype) (win->_line[y].text[x].chars[0] & 0xff);
+                               video_console_putc(win->_begy + y, win->_begx + x, c);
                        }
                }
        }
 
        return OK;
 }
-
 int wprintw(WINDOW *win, const char *fmt, ...)
 {
        va_list argp;
@@ -659,7 +720,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;