From b4d4bac1c49d7e19dac6f29ea278df8be6e6dcd2 Mon Sep 17 00:00:00 2001 From: Ulf Jordan Date: Mon, 11 Aug 2008 20:34:28 +0000 Subject: Add support for line drawing characters and the alternate character set. This enables using the ACS_ curses macros with libpayload. The translation from ACS_ macros (or characters with attribute A_ALTCHARSET) is done using one acs map for the video console, one for serial console (xterm/vt100/vt220), and one fallback, from which an ASCII substitute is taken if the device specific map doesn't contain an entry (ie NUL). Signed-off-by: Ulf Jordan Acked-by: Jordan Crouse git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3499 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- payloads/libpayload/curses/tinycurses.c | 110 +++++++++++++++++++++++++++++-- payloads/libpayload/drivers/serial.c | 15 +++++ payloads/libpayload/include/libpayload.h | 2 + 3 files changed, 120 insertions(+), 7 deletions(-) (limited to 'payloads/libpayload') diff --git a/payloads/libpayload/curses/tinycurses.c b/payloads/libpayload/curses/tinycurses.c index 9e9b3cdec0..86f07818df 100644 --- a/payloads/libpayload/curses/tinycurses.c +++ b/payloads/libpayload/curses/tinycurses.c @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2007 Uwe Hermann + * Copyright (C) 2008 Ulf Jordan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -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]; @@ -213,11 +277,14 @@ 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(); } @@ -409,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)) { @@ -595,10 +662,14 @@ 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++) { @@ -614,6 +685,7 @@ int wnoutrefresh(WINDOW *win) ((int)color_pairs[PAIR_NUMBER(attr)]) << 8; if (curses_flags & F_ENABLE_SERIAL) { + ch = win->_line[y].text[x].chars[0]; if (attr & A_BOLD) { if (!serial_is_bold) { @@ -628,10 +700,28 @@ int wnoutrefresh(WINDOW *win) } } - serial_putchar(win->_line[y].text[x].chars[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) { + ch = win->_line[y].text[x].chars[0]; /* Handle some of the attributes. */ if (attr & A_BOLD) @@ -643,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 @@ -650,7 +746,7 @@ 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); + c |= (chtype) (ch & 0xff); video_console_putc(win->_begy + y, win->_begx + x, c); } } diff --git a/payloads/libpayload/drivers/serial.c b/payloads/libpayload/drivers/serial.c index edd031083e..6e46e06581 100644 --- a/payloads/libpayload/drivers/serial.c +++ b/payloads/libpayload/drivers/serial.c @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 Ulf Jordan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -105,6 +106,10 @@ int serial_getchar(void) #define VT100_SBOLD "\e[1m" #define VT100_EBOLD "\e[m" #define VT100_CURSOR_ADDR "\e[%d;%dH" +/* The following smacs/rmacs are actually for xterm; a real vt100 has + enacs=\E(B\E)0, smacs=^N, rmacs=^O. */ +#define VT100_SMACS "\e(0" +#define VT100_RMACS "\e(B" static void serial_putcmd(char *str) { @@ -127,6 +132,16 @@ void serial_end_bold(void) serial_putcmd(VT100_EBOLD); } +void serial_start_altcharset(void) +{ + serial_putcmd(VT100_SMACS); +} + +void serial_end_altcharset(void) +{ + serial_putcmd(VT100_RMACS); +} + void serial_set_cursor(int y, int x) { char buffer[32]; diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h index 9e95291bc4..6f07ffa4a4 100644 --- a/payloads/libpayload/include/libpayload.h +++ b/payloads/libpayload/include/libpayload.h @@ -105,6 +105,8 @@ int serial_getchar(void); void serial_clear(void); void serial_start_bold(void); void serial_end_bold(void); +void serial_start_altcharset(void); +void serial_end_altcharset(void); void serial_set_cursor(int y, int x); /* drivers/speaker.c */ -- cgit v1.2.3