X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=payloads%2Flibpayload%2Fcurses%2Ftinycurses.c;h=fb492b6cea73889eed5004c3e7bc7dd74b1d3db9;hb=23b6c8f7caa09ed714bce9b6572b6067ae0498c6;hp=776ff1604285dd2a4757b52258a2eefb2304804a;hpb=661e380a75ebc4fa355dc647ed06bd0a2d100b1c;p=coreboot.git diff --git a/payloads/libpayload/curses/tinycurses.c b/payloads/libpayload/curses/tinycurses.c index 776ff1604..fb492b6ce 100644 --- a/payloads/libpayload/curses/tinycurses.c +++ b/payloads/libpayload/curses/tinycurses.c @@ -2,6 +2,8 @@ * This file is part of the libpayload project. * * Copyright (C) 2007 Uwe Hermann + * Copyright (C) 2008 Ulf Jordan + * Copyright (C) 2008-2009 coresystems GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,21 +68,21 @@ 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. */ +/* One item bigger than SCREEN_X to reserve space for a NUL byte. */ static NCURSES_CH_T linebuf_list[SCREEN_Y * MAX_WINDOWS][SCREEN_X + 1]; static int linebuf_count = 0; /* Globals */ int COLORS; /* Currently unused? */ -int COLOR_PAIRS; +int COLOR_PAIRS = 255; WINDOW *stdscr; WINDOW *curscr; WINDOW *newscr; -int LINES; -int COLS; +int LINES = 25; +int COLS = 80; int TABSIZE; int ESCDELAY; // char ttytype[]; @@ -88,6 +90,77 @@ int ESCDELAY; SCREEN *SP; chtype acs_map[128]; +/* See terminfo(5). */ +chtype fallback_acs_map[128] = + { + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', '>', '<', '^', 'v', ' ', + '#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + '+', ':', ' ', ' ', ' ', ' ', '\\', '#', + '#', '#', '+', '+', '+', '+', '+', '~', + '-', '-', '-', '_', '+', '+', '+', '+', + '|', '<', '>', '*', '!', 'f', 'o', ' ', + }; + +#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_ACS_FALLBACK +chtype serial_acs_map[128]; +#else +/* 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, + }; +#endif +#endif + +#ifdef CONFIG_VIDEO_CONSOLE +/* 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', '\343', '\330', '\234', '\376', 0, + }; +#endif + // FIXME: Ugly (and insecure!) hack! char sprintf_tmp[1024]; @@ -118,14 +191,30 @@ NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch) int beep(void) { /* TODO: Flash the screen if beeping fails? */ +#ifdef CONFIG_SPEAKER speaker_tone(1760, 500); /* 1760 == note A6 */ +#endif return OK; } // bool can_change_color(void) {} int cbreak(void) { /* TODO */ return 0; } /* D */ int clearok(WINDOW *win, bool flag) { win->_clear = flag; return OK; } // int color_content(short color, short *r, short *g, short *b) {} -// int curs_set(int) {} +int curs_set(int on) +{ +#ifdef CONFIG_SERIAL_CONSOLE + if (curses_flags & F_ENABLE_SERIAL) { + serial_cursor_enable(on); + } +#endif +#ifdef CONFIG_VIDEO_CONSOLE + if (curses_flags & F_ENABLE_CONSOLE) { + video_console_cursor_enable(on); + } +#endif + + return OK; +} // int def_prog_mode(void) {} // int def_shell_mode(void) {} // int delay_output(int) {} @@ -145,6 +234,7 @@ int delwin(WINDOW *win) } WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) { +#if 0 WINDOW *win = NULL; int i; int flags = _SUBWIN; @@ -168,9 +258,9 @@ WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) flags |= _ISPAD; // FIXME - //// if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy, - //// orig->_begx + begx, flags)) == 0) - //// return NULL; + if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy, + orig->_begx + begx, flags)) == 0) + return NULL; win->_pary = begy; win->_parx = begx; @@ -183,8 +273,11 @@ WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) win->_parent = orig; return win; +#else + return NULL; +#endif } -int doupdate(void) { /* TODO */ return(*(int *)0); } +int doupdate(void) { /* TODO */ return(0); } // WINDOW * dupwin (WINDOW *) {} /* D */ int echo(void) { SP->_echo = TRUE; return OK; } int endwin(void) @@ -202,9 +295,9 @@ 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_colors (void) { return(TRUE); } // bool has_ic (void) {} // bool has_il (void) {} // void idcok (WINDOW *, bool) {} @@ -213,28 +306,33 @@ void immedok(WINDOW *win, bool flag) { win->_immed = flag; } /** Note: Must _not_ be called twice! */ WINDOW *initscr(void) { - int x, y; + int i; // newterm(name, stdout, stdin); // def_prog_mode(); + for (i = 0; i < 128; i++) + acs_map[i] = (chtype) i | A_ALTCHARSET; +#ifdef CONFIG_SERIAL_CONSOLE + if (curses_flags & F_ENABLE_SERIAL) { + serial_clear(); + } +#endif +#ifdef CONFIG_VIDEO_CONSOLE 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); } +#endif // Speaker init? - stdscr = newwin(SCREEN_Y, SCREEN_X + 1, 0, 0); + stdscr = newwin(SCREEN_Y, SCREEN_X, 0, 0); // TODO: curscr, newscr? - for (y = 0; y < stdscr->_maxy; y++) { - for (x = 0; x < stdscr->_maxx; x++) { - stdscr->_line[y].text[x].chars[0] = ' '; - stdscr->_line[y].text[x].attr = A_NORMAL; - } - } + werase(stdscr); return stdscr; } @@ -305,7 +403,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 +416,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*) {} @@ -398,19 +495,27 @@ int vwprintw(WINDOW *win, const char *fmt, va_list argp) return waddstr(win, (char *)&sprintf_tmp); } // int vwscanw (WINDOW *, NCURSES_CONST char *,va_list) {} -// int waddch (WINDOW *, const chtype) {} int waddch(WINDOW *win, const chtype ch) { int code = ERR; // NCURSES_CH_T wch; // SetChar2(wch, ch); - win->_line[win->_cury].text[win->_curx].chars[0] = ch; + if (win->_line[win->_cury].firstchar == _NOCHANGE || + win->_line[win->_cury].firstchar > win->_curx) + win->_line[win->_cury].firstchar = win->_curx; - /* 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); + + if (win->_line[win->_cury].lastchar == _NOCHANGE || + win->_line[win->_cury].lastchar < win->_curx) + win->_line[win->_cury].lastchar = win->_curx; + win->_curx++; // FIXME // if (win && (waddch_nosync(win, wch) != ERR)) { @@ -432,6 +537,10 @@ int waddnstr(WINDOW *win, const char *astr, int n) if (n < 0) n = strlen(astr); + if (win->_line[win->_cury].firstchar == _NOCHANGE || + win->_line[win->_cury].firstchar > win->_curx) + win->_line[win->_cury].firstchar = win->_curx; + while ((n-- > 0) && (*str != '\0')) { // while (*str != '\0') { win->_line[win->_cury].text[win->_curx].chars[0] = *str++; @@ -446,6 +555,11 @@ int waddnstr(WINDOW *win, const char *astr, int n) // break; // } } + + if (win->_line[win->_cury].lastchar == _NOCHANGE || + win->_line[win->_cury].lastchar < win->_curx) + win->_line[win->_cury].lastchar = win->_curx; + return code; } int wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED) @@ -464,7 +578,48 @@ 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; + + if (ls == 0) ls = ACS_VLINE; + if (rs == 0) rs = ACS_VLINE; + if (ts == 0) ts = ACS_HLINE; + if (bs == 0) bs = ACS_HLINE; + if (tl == 0) tl = ACS_ULCORNER; + if (tr == 0) tr = ACS_URCORNER; + if (bl == 0) bl = ACS_LLCORNER; + if (br == 0) br = ACS_LRCORNER; + + 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) { @@ -474,7 +629,7 @@ void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ } return OK; } // int wclrtobot (WINDOW *) {} -int wclrtoeol(WINDOW *win) { /* TODO */ return(*(int *)0); } +int wclrtoeol(WINDOW *win) { /* TODO */ return ERR; } int wcolor_set(WINDOW *win, short color_pair_number, void *opts) { if (!opts && (color_pair_number >= 0) @@ -491,11 +646,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); } + // Should we check instead? + win->_line[y].firstchar = 0; + win->_line[y].lastchar = win->_maxx; } return OK; } @@ -554,20 +712,119 @@ int whline(WINDOW *win, chtype ch, int n) win->_flags |= _HASMOVED; return OK; } + +#define SWAP_RED_BLUE(c) \ + (((c) & 0x4400) >> 2) | ((c) & 0xAA00) | (((c) & 0x1100) << 2) int wnoutrefresh(WINDOW *win) { +#ifdef CONFIG_SERIAL_CONSOLE // FIXME. + int serial_is_bold = 0; + int serial_is_reverse = 0; + int serial_is_altcharset = 0; + int serial_cur_pair = 0; + + int need_altcharset; + short fg, bg; +#endif int x, y; + chtype ch; + +#ifdef CONFIG_SERIAL_CONSOLE + serial_end_bold(); + serial_end_altcharset(); +#endif + + for (y = 0; y <= win->_maxy; y++) { + + if (win->_line[y].firstchar == _NOCHANGE) + continue; + + /* Position the serial cursor */ + +#ifdef CONFIG_SERIAL_CONSOLE + if (curses_flags & F_ENABLE_SERIAL) + serial_set_cursor(win->_begy + y, win->_begx + + win->_line[y].firstchar); +#endif + + for (x = win->_line[y].firstchar; x <= win->_line[y].lastchar; x++) { + attr_t attr = win->_line[y].text[x].attr; + +#ifdef CONFIG_SERIAL_CONSOLE + 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; + /* work around serial.c + * shortcoming: + */ + serial_is_reverse = 0; + serial_cur_pair = 0; + } + } - 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 (attr & A_REVERSE) { + if (!serial_is_reverse) { + serial_start_reverse(); + serial_is_reverse = 1; + } + } else { + if (serial_is_reverse) { + serial_end_reverse(); + serial_is_reverse = 0; + /* work around serial.c + * shortcoming: + */ + serial_is_bold = 0; + serial_cur_pair = 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; + } + + if (serial_cur_pair != PAIR_NUMBER(attr)) { + pair_content(PAIR_NUMBER(attr), + &fg, &bg); + serial_set_color(fg, bg); + serial_cur_pair = PAIR_NUMBER(attr); + } + + serial_putchar(ch); + + } +#endif +#ifdef CONFIG_VIDEO_CONSOLE + unsigned int c = + ((int)color_pairs[PAIR_NUMBER(attr)]) << 8; + + c = SWAP_RED_BLUE(c); 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,13 +836,38 @@ 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]; + } - 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) (ch & 0xff); + video_console_putc(win->_begy + y, win->_begx + x, c); } +#endif } + win->_line[y].firstchar = _NOCHANGE; + win->_line[y].lastchar = _NOCHANGE; } +#ifdef CONFIG_SERIAL_CONSOLE + if (curses_flags & F_ENABLE_SERIAL) + serial_set_cursor(win->_begy + win->_cury, win->_begx + win->_curx); +#endif + +#ifdef CONFIG_VIDEO_CONSOLE + if (curses_flags & F_ENABLE_CONSOLE) + video_console_set_cursor(win->_begx + win->_curx, win->_begy + win->_cury); +#endif + return OK; } int wprintw(WINDOW *win, const char *fmt, ...) @@ -599,7 +881,19 @@ int wprintw(WINDOW *win, const char *fmt, ...) return code; } -// int wredrawln (WINDOW *,int,int) {} + +int wredrawln (WINDOW *win, int beg_line, int num_lines) +{ + int i; + + for (i = beg_line; i < beg_line + num_lines; i++) { + win->_line[i].firstchar = 0; + win->_line[i].lastchar = win->_maxx; + } + + return OK; +} + int wrefresh(WINDOW *win) { // FIXME @@ -629,13 +923,49 @@ int wrefresh(WINDOW *win) // int wscanw (WINDOW *, NCURSES_CONST char *,...) {} int wscrl(WINDOW *win, int n) { + int x, y; + if (!win->_scroll) return ERR; - if (n != 0) { - // _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd); - // _nc_synchook(win); + if (n == 0) + return OK; + + for (y = 0; y <= (win->_maxy - n); y++) { + win->_line[y].firstchar = win->_line[y + n].firstchar; + win->_line[y].lastchar = win->_line[y + n].lastchar; + for (x = 0; x <= win->_maxx; x++) { + if ((win->_line[y].text[x].chars[0] != win->_line[y + n].text[x].chars[0]) || + (win->_line[y].text[x].attr != win->_line[y + n].text[x].attr)) { + if (win->_line[y].firstchar == _NOCHANGE) + win->_line[y].firstchar = x; + + win->_line[y].lastchar = x; + + win->_line[y].text[x].chars[0] = win->_line[y + n].text[x].chars[0]; + win->_line[y].text[x].attr = win->_line[y + n].text[x].attr; + } + } } + + for (y = (win->_maxy+1 - n); y <= win->_maxy; y++) { + for (x = 0; x <= win->_maxx; x++) { + if ((win->_line[y].text[x].chars[0] != ' ') || + (win->_line[y].text[x].attr != A_NORMAL)) { + if (win->_line[y].firstchar == _NOCHANGE) + win->_line[y].firstchar = x; + + win->_line[y].lastchar = x; + + win->_line[y].text[x].chars[0] = ' '; + win->_line[y].text[x].attr = A_NORMAL; + } + } + } + + // _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd); + // _nc_synchook(win); + return OK; } int wsetscrreg(WINDOW *win, int top, int bottom) @@ -650,7 +980,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;