diff options
Diffstat (limited to 'tools/ioemu/gui/term.cc')
-rw-r--r-- | tools/ioemu/gui/term.cc | 843 |
1 files changed, 843 insertions, 0 deletions
diff --git a/tools/ioemu/gui/term.cc b/tools/ioemu/gui/term.cc new file mode 100644 index 0000000000..37bf9c5936 --- /dev/null +++ b/tools/ioemu/gui/term.cc @@ -0,0 +1,843 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: term.cc,v 1.31 2003/08/17 23:40:38 cbothamy Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + +// Define BX_PLUGGABLE in files that can be compiled into plugins. For +// platforms that require a special tag on exported symbols, BX_PLUGGABLE +// is used to know when we are exporting symbols and when we are importing. +#define BX_PLUGGABLE + +#include "bochs.h" +#if BX_WITH_TERM + +#include "icon_bochs.h" + +extern "C" { +#include <curses.h> +#include <signal.h> +}; + +class bx_term_gui_c : public bx_gui_c { +public: + bx_term_gui_c (void) {} + DECLARE_GUI_VIRTUAL_METHODS() + + virtual Bit32u get_sighandler_mask (); + // called when registered signal arrives + virtual void sighandler (int sig); +}; + +// declare one instance of the gui object and call macro to insert the +// plugin code +static bx_term_gui_c *theGui = NULL; +IMPLEMENT_GUI_PLUGIN_CODE(term) + +#define LOG_THIS theGui-> + +bx_bool initialized = 0; +static unsigned int text_cols = 80, text_rows = 25; + +static short curses_color[8] = { + /* 0 */ COLOR_BLACK, + /* 1 */ COLOR_BLUE, + /* 2 */ COLOR_GREEN, + /* 3 */ COLOR_CYAN, + /* 4 */ COLOR_RED, + /* 5 */ COLOR_MAGENTA, + /* 6 */ COLOR_YELLOW, + /* 7 */ COLOR_WHITE +}; + +static chtype vga_to_term[128] = { + 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, + 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, + 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, + 0xff, 0xd6, 0xdc, 0xe7, 0xa3, 0xa5, ' ', ' ', + 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, + 0xbf, ' ', 0xac, ' ', ' ', 0xa1, 0xab, 0xbb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', 0xb5, ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', 0xb1, ' ', ' ', ' ', ' ', 0xf7, ' ', + 0xb0, ' ', ' ', ' ', ' ', 0xb2, ' ', ' ' +}; + +static void +do_scan(int key_event, int shift, int ctrl, int alt) +{ + /* XXX At some point, cache alt/ctrl/shift so only when the state + changes do we simulate a press or release, to cut down on + keyboard input to the simulated machine */ + + BX_DEBUG(("key_event %d/0x%x %s%s%s", + key_event,key_event, + shift?"(shift)":"", + ctrl?"(ctrl)":"", + alt?"(alt)":"")); + if(shift) + DEV_kbd_gen_scancode(BX_KEY_SHIFT_L); + if(ctrl) + DEV_kbd_gen_scancode(BX_KEY_CTRL_L); + if(alt) + DEV_kbd_gen_scancode(BX_KEY_ALT_L); + DEV_kbd_gen_scancode(key_event); + key_event |= BX_KEY_RELEASED; + + DEV_kbd_gen_scancode(key_event); + if(alt) + DEV_kbd_gen_scancode(BX_KEY_ALT_L|BX_KEY_RELEASED); + if(ctrl) + DEV_kbd_gen_scancode(BX_KEY_CTRL_L|BX_KEY_RELEASED); + if(shift) + DEV_kbd_gen_scancode(BX_KEY_SHIFT_L|BX_KEY_RELEASED); +} + +Bit32u +bx_term_gui_c::get_sighandler_mask () +{ + return + (1<<SIGHUP) + | (1<<SIGINT) + | (1<<SIGQUIT) +#ifdef SIGSTOP + | (1<<SIGSTOP) +#endif +#ifdef SIGTSTP + | (1<<SIGTSTP) +#endif + | (1<<SIGTERM); +} + +void +bx_term_gui_c::sighandler(int signo) +{ + switch(signo) { + case SIGINT: + do_scan(BX_KEY_C,0,1,0); + break; +#ifdef SIGSTOP + case SIGSTOP: + do_scan(BX_KEY_S,0,1,0); + break; +#endif +#ifdef SIGTSTP + case SIGTSTP: + do_scan(BX_KEY_Z,0,1,0); + break; +#endif + default: + BX_INFO(("sig %d caught",signo)); + break; + } +} + +// ::SPECIFIC_INIT() +// +// Called from gui.cc, once upon program startup, to allow for the +// specific GUI code (X11, BeOS, ...) to be initialized. +// +// argc, argv: not used right now, but the intention is to pass native GUI +// specific options from the command line. (X11 options, BeOS options,...) +// +// tilewidth, tileheight: for optimization, graphics_tile_update() passes +// only updated regions of the screen to the gui code to be redrawn. +// These define the dimensions of a region (tile). +// headerbar_y: A headerbar (toolbar) is display on the top of the +// VGA window, showing floppy status, and other information. It +// always assumes the width of the current VGA mode width, but +// it's height is defined by this parameter. + + void +bx_term_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight, + unsigned headerbar_y) +{ + put("TGUI"); + UNUSED(argc); + UNUSED(argv); + UNUSED(tilewidth); + UNUSED(tileheight); + UNUSED(headerbar_y); + + UNUSED(bochs_icon_bits); // global variable + + // the ask menu causes trouble + io->set_log_action(LOGLEV_PANIC, ACT_FATAL); + // logfile should be different from stderr, otherwise terminal mode + // really ends up having fun + if (!strcmp(bx_options.log.Ofilename->getptr(), "-")) + BX_PANIC(("cannot log to stderr in term mode")); + + initscr(); + start_color(); + cbreak(); + curs_set(2); + keypad(stdscr,TRUE); + nodelay(stdscr, TRUE); + noecho(); + +#if BX_HAVE_COLOR_SET + if (has_colors()) { + for (int i=0; i<COLORS; i++) { + for (int j=0; j<COLORS; j++) { + if ((i!=0)||(j!=0)) init_pair(i * COLORS + j, j, i); + } + } + } +#endif + + if (bx_options.Oprivate_colormap->get ()) + BX_ERROR(("WARNING: private_colormap option ignored.")); + initialized = 1; +} + + + +void +do_char(int character,int alt) +{ + switch (character) { + // control keys + case 0x9: do_scan(BX_KEY_TAB,0,0,alt); break; + case 0xa: do_scan(BX_KEY_KP_ENTER,0,0,alt); break; + case 0xd: do_scan(BX_KEY_KP_DELETE,0,0,alt); break; + case 0x1: do_scan(BX_KEY_A,0,1,alt); break; + case 0x2: do_scan(BX_KEY_B,0,1,alt); break; + case 0x3: do_scan(BX_KEY_C,0,1,alt); break; + case 0x4: do_scan(BX_KEY_D,0,1,alt); break; + case 0x5: do_scan(BX_KEY_E,0,1,alt); break; + case 0x6: do_scan(BX_KEY_F,0,1,alt); break; + case 0x7: do_scan(BX_KEY_G,0,1,alt); break; + case 0x8: do_scan(BX_KEY_H,0,1,alt); break; + case 0xb: do_scan(BX_KEY_K,0,1,alt); break; + case 0xc: do_scan(BX_KEY_L,0,1,alt); break; + case 0xe: do_scan(BX_KEY_N,0,1,alt); break; + case 0xf: do_scan(BX_KEY_O,0,1,alt); break; + case 0x10: do_scan(BX_KEY_P,0,1,alt); break; + case 0x11: do_scan(BX_KEY_Q,0,1,alt); break; + case 0x12: do_scan(BX_KEY_R,0,1,alt); break; + case 0x13: do_scan(BX_KEY_S,0,1,alt); break; + case 0x14: do_scan(BX_KEY_T,0,1,alt); break; + case 0x15: do_scan(BX_KEY_U,0,1,alt); break; + case 0x16: do_scan(BX_KEY_V,0,1,alt); break; + case 0x17: do_scan(BX_KEY_W,0,1,alt); break; + case 0x18: do_scan(BX_KEY_X,0,1,alt); break; + case 0x19: do_scan(BX_KEY_Y,0,1,alt); break; + case 0x1a: do_scan(BX_KEY_Z,0,1,alt); break; + case 0x20: do_scan(BX_KEY_SPACE,0,0,alt); break; + case 0x107: do_scan(BX_KEY_BACKSPACE,0,0,alt); break; + case 0x102: do_scan(BX_KEY_DOWN,0,0,alt); break; + case 0x103: do_scan(BX_KEY_UP,0,0,alt); break; + case 0x104: do_scan(BX_KEY_LEFT,0,0,alt); break; + case 0x105: do_scan(BX_KEY_RIGHT,0,0,alt); break; + case 0x152: do_scan(BX_KEY_PAGE_DOWN,0,0,alt); break; + case 0x153: do_scan(BX_KEY_PAGE_UP,0,0,alt); break; + case 0x106: do_scan(BX_KEY_HOME,0,0,alt); break; + case 0x168: do_scan(BX_KEY_END,0,0,alt); break; + case 0x14b: do_scan(BX_KEY_INSERT,0,0,alt); break; + case 0x7f: do_scan(BX_KEY_DELETE,0,0,alt); break; + case 0x1b: do_scan(BX_KEY_ESC,0,0,alt); break; + case '!': do_scan(BX_KEY_1,1,0,alt); break; + case '\'': do_scan(BX_KEY_SINGLE_QUOTE,0,0,alt); break; + case '#': do_scan(BX_KEY_3,1,0,alt); break; + case '$': do_scan(BX_KEY_4,1,0,alt); break; + case '%': do_scan(BX_KEY_5,1,0,alt); break; + case '^': do_scan(BX_KEY_6,1,0,alt); break; + case '&': do_scan(BX_KEY_7,1,0,alt); break; + case '"': do_scan(BX_KEY_SINGLE_QUOTE,1,0,alt); break; + + // ()*+,-./ + case '(': do_scan(BX_KEY_9,1,0,alt); break; + case ')': do_scan(BX_KEY_0,1,0,alt); break; + case '*': do_scan(BX_KEY_8,1,0,alt); break; + case '+': do_scan(BX_KEY_EQUALS,1,0,alt); break; + case ',': do_scan(BX_KEY_COMMA,0,0,alt); break; + case '-': do_scan(BX_KEY_MINUS,0,0,alt); break; + case '.': do_scan(BX_KEY_PERIOD,0,0,alt); break; + case '/': do_scan(BX_KEY_SLASH,0,0,alt); break; + + // 01234567 + case '0': do_scan(BX_KEY_0,0,0,alt); break; + case '1': do_scan(BX_KEY_1,0,0,alt); break; + case '2': do_scan(BX_KEY_2,0,0,alt); break; + case '3': do_scan(BX_KEY_3,0,0,alt); break; + case '4': do_scan(BX_KEY_4,0,0,alt); break; + case '5': do_scan(BX_KEY_5,0,0,alt); break; + case '6': do_scan(BX_KEY_6,0,0,alt); break; + case '7': do_scan(BX_KEY_7,0,0,alt); break; + + // 89:;<=>? + case '8': do_scan(BX_KEY_8,0,0,alt); break; + case '9': do_scan(BX_KEY_9,0,0,alt); break; + case ':': do_scan(BX_KEY_SEMICOLON,1,0,alt); break; + case ';': do_scan(BX_KEY_SEMICOLON,0,0,alt); break; + case '<': do_scan(BX_KEY_COMMA,1,0,alt); break; + case '=': do_scan(BX_KEY_EQUALS,0,0,alt); break; + case '>': do_scan(BX_KEY_PERIOD,1,0,alt); break; + case '?': do_scan(BX_KEY_SLASH,1,0,alt); break; + + // @ABCDEFG + case '@': do_scan(BX_KEY_2,1,0,alt); break; + case 'A': do_scan(BX_KEY_A,1,0,alt); break; + case 'B': do_scan(BX_KEY_B,1,0,alt); break; + case 'C': do_scan(BX_KEY_C,1,0,alt); break; + case 'D': do_scan(BX_KEY_D,1,0,alt); break; + case 'E': do_scan(BX_KEY_E,1,0,alt); break; + case 'F': do_scan(BX_KEY_F,1,0,alt); break; + case 'G': do_scan(BX_KEY_G,1,0,alt); break; + + + // HIJKLMNO + case 'H': do_scan(BX_KEY_H,1,0,alt); break; + case 'I': do_scan(BX_KEY_I,1,0,alt); break; + case 'J': do_scan(BX_KEY_J,1,0,alt); break; + case 'K': do_scan(BX_KEY_K,1,0,alt); break; + case 'L': do_scan(BX_KEY_L,1,0,alt); break; + case 'M': do_scan(BX_KEY_M,1,0,alt); break; + case 'N': do_scan(BX_KEY_N,1,0,alt); break; + case 'O': do_scan(BX_KEY_O,1,0,alt); break; + + + // PQRSTUVW + case 'P': do_scan(BX_KEY_P,1,0,alt); break; + case 'Q': do_scan(BX_KEY_Q,1,0,alt); break; + case 'R': do_scan(BX_KEY_R,1,0,alt); break; + case 'S': do_scan(BX_KEY_S,1,0,alt); break; + case 'T': do_scan(BX_KEY_T,1,0,alt); break; + case 'U': do_scan(BX_KEY_U,1,0,alt); break; + case 'V': do_scan(BX_KEY_V,1,0,alt); break; + case 'W': do_scan(BX_KEY_W,1,0,alt); break; + + // XYZ[\]^_ + case 'X': do_scan(BX_KEY_X,1,0,alt); break; + case 'Y': do_scan(BX_KEY_Y,1,0,alt); break; + case 'Z': do_scan(BX_KEY_Z,1,0,alt); break; + case '{': do_scan(BX_KEY_LEFT_BRACKET,1,0,alt); break; + case '|': do_scan(BX_KEY_BACKSLASH,1,0,alt); break; + case '}': do_scan(BX_KEY_RIGHT_BRACKET,1,0,alt); break; + case '_': do_scan(BX_KEY_MINUS,1,0,alt); break; + + // `abcdefg + case '`': do_scan(BX_KEY_GRAVE,0,0,alt); break; + case 'a': do_scan(BX_KEY_A,0,0,alt); break; + case 'b': do_scan(BX_KEY_B,0,0,alt); break; + case 'c': do_scan(BX_KEY_C,0,0,alt); break; + case 'd': do_scan(BX_KEY_D,0,0,alt); break; + case 'e': do_scan(BX_KEY_E,0,0,alt); break; + case 'f': do_scan(BX_KEY_F,0,0,alt); break; + case 'g': do_scan(BX_KEY_G,0,0,alt); break; + + // hijklmno + case 'h': do_scan(BX_KEY_H,0,0,alt); break; + case 'i': do_scan(BX_KEY_I,0,0,alt); break; + case 'j': do_scan(BX_KEY_J,0,0,alt); break; + case 'k': do_scan(BX_KEY_K,0,0,alt); break; + case 'l': do_scan(BX_KEY_L,0,0,alt); break; + case 'm': do_scan(BX_KEY_M,0,0,alt); break; + case 'n': do_scan(BX_KEY_N,0,0,alt); break; + case 'o': do_scan(BX_KEY_O,0,0,alt); break; + + // pqrstuvw + case 'p': do_scan(BX_KEY_P,0,0,alt); break; + case 'q': do_scan(BX_KEY_Q,0,0,alt); break; + case 'r': do_scan(BX_KEY_R,0,0,alt); break; + case 's': do_scan(BX_KEY_S,0,0,alt); break; + case 't': do_scan(BX_KEY_T,0,0,alt); break; + case 'u': do_scan(BX_KEY_U,0,0,alt); break; + case 'v': do_scan(BX_KEY_V,0,0,alt); break; + case 'w': do_scan(BX_KEY_W,0,0,alt); break; + + // xyz{|}~ + case 'x': do_scan(BX_KEY_X,0,0,alt); break; + case 'y': do_scan(BX_KEY_Y,0,0,alt); break; + case 'z': do_scan(BX_KEY_Z,0,0,alt); break; + case '[': do_scan(BX_KEY_LEFT_BRACKET,0,0,alt); break; + case '\\': do_scan(BX_KEY_BACKSLASH,0,0,alt); break; + case ']': do_scan(BX_KEY_RIGHT_BRACKET,0,0,alt); break; + case '~': do_scan(BX_KEY_GRAVE,1,0,alt); break; + + // function keys + case KEY_F(1): do_scan(BX_KEY_F1,0,0,alt); break; + case KEY_F(2): do_scan(BX_KEY_F2,0,0,alt); break; + case KEY_F(3): do_scan(BX_KEY_F3,0,0,alt); break; + case KEY_F(4): do_scan(BX_KEY_F4,0,0,alt); break; + case KEY_F(5): do_scan(BX_KEY_F5,0,0,alt); break; + case KEY_F(6): do_scan(BX_KEY_F6,0,0,alt); break; + case KEY_F(7): do_scan(BX_KEY_F7,0,0,alt); break; + case KEY_F(8): do_scan(BX_KEY_F8,0,0,alt); break; + case KEY_F(9): do_scan(BX_KEY_F9,0,0,alt); break; + case KEY_F(10): do_scan(BX_KEY_F10,0,0,alt); break; + case KEY_F(11): do_scan(BX_KEY_F11,0,0,alt); break; + case KEY_F(12): do_scan(BX_KEY_F12,0,0,alt); break; + + // shifted function keys + case KEY_F(13): do_scan(BX_KEY_F1,1,0,alt); break; + case KEY_F(14): do_scan(BX_KEY_F2,1,0,alt); break; + case KEY_F(15): do_scan(BX_KEY_F3,1,0,alt); break; + case KEY_F(16): do_scan(BX_KEY_F4,1,0,alt); break; + case KEY_F(17): do_scan(BX_KEY_F5,1,0,alt); break; + case KEY_F(18): do_scan(BX_KEY_F6,1,0,alt); break; + case KEY_F(19): do_scan(BX_KEY_F7,1,0,alt); break; + case KEY_F(20): do_scan(BX_KEY_F8,1,0,alt); break; + + default: + if(character > 0x79) { + do_char(character - 0x80,1); + break; + } + + BX_INFO(("character unhandled: 0x%x",character)); + break; + } +} + + +// ::HANDLE_EVENTS() +// +// Called periodically (vga_update_interval in .bochsrc) so the +// the gui code can poll for keyboard, mouse, and other +// relevant events. + + void +bx_term_gui_c::handle_events(void) +{ + int character; + while((character = getch()) != ERR) { + BX_DEBUG(("scancode(0x%x)",character)); + do_char(character,0); + } +} + + + +// ::FLUSH() +// +// Called periodically, requesting that the gui code flush all pending +// screen update requests. + + void +bx_term_gui_c::flush(void) +{ + if (initialized) + refresh(); +} + + +// ::CLEAR_SCREEN() +// +// Called to request that the VGA region is cleared. Don't +// clear the area that defines the headerbar. + + void +bx_term_gui_c::clear_screen(void) +{ + clear(); +#if BX_HAVE_COLOR_SET + color_set(7, NULL); +#endif +#if BX_HAVE_MVHLINE + if (LINES > (int)text_rows) { + mvhline(text_rows, 0, ACS_HLINE, text_cols); + } +#endif +#if BX_HAVE_MVVLINE + if (COLS > (int)text_cols) { + mvvline(0, text_cols, ACS_VLINE, text_rows); + } +#endif + if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) { + mvaddch(text_rows, text_cols, ACS_LRCORNER); + } +} + +int +get_color_pair(Bit8u vga_attr) +{ + int term_attr; + + term_attr = curses_color[vga_attr & 0x07]; + term_attr |= (curses_color[(vga_attr & 0x70) >> 4] << 3); + return term_attr; +} + +chtype +get_term_char(Bit8u vga_char[]) +{ + int term_char; + + if ((vga_char[1] & 0x0f) == ((vga_char[1] >> 4) & 0x0f)) { + return ' '; + } + switch (vga_char[0]) { + case 0x04: term_char = ACS_DIAMOND; break; + case 0x18: term_char = ACS_UARROW; break; + case 0x19: term_char = ACS_DARROW; break; + case 0x1a: term_char = ACS_RARROW; break; + case 0x1b: term_char = ACS_LARROW; break; + case 0xc4: + case 0xcd: term_char = ACS_HLINE; break; + case 0xb3: + case 0xba: term_char = ACS_VLINE; break; + case 0xc9: + case 0xd5: + case 0xd6: + case 0xda: term_char = ACS_ULCORNER; break; + case 0xb7: + case 0xb8: + case 0xbb: + case 0xbf: term_char = ACS_URCORNER; break; + case 0xc0: + case 0xc8: + case 0xd3: + case 0xd4: term_char = ACS_LLCORNER; break; + case 0xbc: + case 0xbd: + case 0xbe: + case 0xd9: term_char = ACS_LRCORNER; break; + case 0xc3: + case 0xc6: + case 0xc7: + case 0xcc: term_char = ACS_LTEE; break; + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb9: term_char = ACS_RTEE; break; + case 0xc2: + case 0xcb: + case 0xd1: + case 0xd2: term_char = ACS_TTEE; break; + case 0xc1: + case 0xca: + case 0xcf: + case 0xd0: term_char = ACS_BTEE; break; + case 0xc5: + case 0xce: + case 0xd7: + case 0xd8: term_char = ACS_PLUS; break; + case 0xb0: + case 0xb1: term_char = ACS_CKBOARD; break; + case 0xb2: term_char = ACS_BOARD; break; + case 0xdb: term_char = ACS_BLOCK; break; + default: + if (vga_char[0] > 0x7f) { + term_char = vga_to_term[vga_char[0]-0x80]; + } else if (vga_char[0] > 0x1f) { + term_char = vga_char[0]; + } else { + term_char = ' '; + } + } + return term_char; +} + +// ::TEXT_UPDATE() +// +// Called in a VGA text mode, to update the screen with +// new content. +// +// old_text: array of character/attributes making up the contents +// of the screen from the last call. See below +// new_text: array of character/attributes making up the current +// contents, which should now be displayed. See below +// +// format of old_text & new_text: each is 4000 bytes long. +// This represents 80 characters wide by 25 high, with +// each character being 2 bytes. The first by is the +// character value, the second is the attribute byte. +// I currently don't handle the attribute byte. +// +// cursor_x: new x location of cursor +// cursor_y: new y location of cursor + + void +bx_term_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, + unsigned long cursor_x, unsigned long cursor_y, + bx_vga_tminfo_t tm_info, unsigned nrows) +{ + unsigned char *old_line, *new_line, *new_start; + unsigned char cAttr; + unsigned int hchars, rows, x, y; + chtype ch; + bx_bool force_update = 0; + + UNUSED(nrows); + + if(charmap_updated) { + force_update = 1; + charmap_updated = 0; + } + + new_start = new_text; + rows = text_rows; + y = 0; + do { + hchars = text_cols; + new_line = new_text; + old_line = old_text; + x = 0; + do { + if (force_update || (old_text[0] != new_text[0]) + || (old_text[1] != new_text[1])) { +#if BX_HAVE_COLOR_SET + if (has_colors()) { + color_set(get_color_pair(new_text[1]), NULL); + } +#endif + ch = get_term_char(&new_text[0]); + if ((new_text[1] & 0x08) > 0) ch |= A_BOLD; + if ((new_text[1] & 0x80) > 0) ch |= A_BLINK; + mvaddch(y, x, ch); + } + x++; + new_text+=2; + old_text+=2; + } while (--hchars); + y++; + new_text = new_line + tm_info.line_offset; + old_text = old_line + tm_info.line_offset; + } while (--rows); + + if ((cursor_x<text_cols) && (cursor_y<text_rows) + && (tm_info.cs_start <= tm_info.cs_end)) { + if(cursor_x>0) + cursor_x--; + else { + cursor_x=COLS-1; + cursor_y--; + } + cAttr = new_start[cursor_y*tm_info.line_offset+cursor_x*2+1]; +#if BX_HAVE_COLOR_SET + if (has_colors()) { + color_set(get_color_pair(cAttr), NULL); + } +#endif + ch = get_term_char(&new_start[cursor_y*tm_info.line_offset+cursor_x*2]); + if ((cAttr & 0x08) > 0) ch |= A_BOLD; + if ((cAttr & 0x80) > 0) ch |= A_REVERSE; + mvaddch(cursor_y, cursor_x, ch); + curs_set(2); + } else { + curs_set(0); + } +} + + int +bx_term_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) +{ + return 0; +} + + int +bx_term_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) +{ + return 0; +} + + +// ::PALETTE_CHANGE() +// +// Allocate a color in the native GUI, for this color, and put +// it in the colormap location 'index'. +// returns: 0=no screen update needed (color map change has direct effect) +// 1=screen updated needed (redraw using current colormap) + + bx_bool +bx_term_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) +{ + BX_DEBUG(("color pallete request (%d,%d,%d,%d) ignored", + index,red,green,blue)); + return(0); +} + + +// ::GRAPHICS_TILE_UPDATE() +// +// Called to request that a tile of graphics be drawn to the +// screen, since info in this region has changed. +// +// tile: array of 8bit values representing a block of pixels with +// dimension equal to the 'tilewidth' & 'tileheight' parameters to +// ::specific_init(). Each value specifies an index into the +// array of colors you allocated for ::palette_change() +// x0: x origin of tile +// y0: y origin of tile +// +// note: origin of tile and of window based on (0,0) being in the upper +// left of the window. + + void +bx_term_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) +{ + UNUSED(tile); + UNUSED(x0); + UNUSED(y0); +} + + + +// ::DIMENSION_UPDATE() +// +// Called when the VGA mode changes it's X,Y dimensions. +// Resize the window to this size, but you need to add on +// the height of the headerbar to the Y value. +// +// x: new VGA x size +// y: new VGA y size (add headerbar_y parameter from ::specific_init(). +// fheight: new VGA character height in text mode +// fwidth : new VGA character width in text mode +// bpp : bits per pixel in graphics mode + + void +bx_term_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp) +{ + if (bpp > 8) { + BX_PANIC(("%d bpp graphics mode not supported", bpp)); + } + if (fheight > 0) { + text_cols = x / fwidth; + text_rows = y / fheight; +#if BX_HAVE_COLOR_SET + color_set(7, NULL); +#endif +#if BX_HAVE_MVHLINE + if (LINES > (int)text_rows) { + mvhline(text_rows, 0, ACS_HLINE, text_cols); + } +#endif +#if BX_HAVE_MVVLINE + if (COLS > (int)text_cols) { + mvvline(0, text_cols, ACS_VLINE, text_rows); + } +#endif + if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) { + mvaddch(text_rows, text_cols, ACS_LRCORNER); + } + } +} + + +// ::CREATE_BITMAP() +// +// Create a monochrome bitmap of size 'xdim' by 'ydim', which will +// be drawn in the headerbar. Return an integer ID to the bitmap, +// with which the bitmap can be referenced later. +// +// bmap: packed 8 pixels-per-byte bitmap. The pixel order is: +// bit0 is the left most pixel, bit7 is the right most pixel. +// xdim: x dimension of bitmap +// ydim: y dimension of bitmap + + unsigned +bx_term_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) +{ + UNUSED(bmap); + UNUSED(xdim); + UNUSED(ydim); + return(0); +} + + +// ::HEADERBAR_BITMAP() +// +// Called to install a bitmap in the bochs headerbar (toolbar). +// +// bmap_id: will correspond to an ID returned from +// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT +// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next +// available leftmost or rightmost space. +// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT, +// meaning install the bitmap in the next +// available leftmost or rightmost space. +// f: a 'C' function pointer to callback when the mouse is clicked in +// the boundaries of this bitmap. + + unsigned +bx_term_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) +{ + UNUSED(bmap_id); + UNUSED(alignment); + UNUSED(f); + return(0); +} + + +// ::SHOW_HEADERBAR() +// +// Show (redraw) the current headerbar, which is composed of +// currently installed bitmaps. + + void +bx_term_gui_c::show_headerbar(void) +{ +} + + +// ::REPLACE_BITMAP() +// +// Replace the bitmap installed in the headerbar ID slot 'hbar_id', +// with the one specified by 'bmap_id'. 'bmap_id' will have +// been generated by ::create_bitmap(). The old and new bitmap +// must be of the same size. This allows the bitmap the user +// sees to change, when some action occurs. For example when +// the user presses on the floppy icon, it then displays +// the ejected status. +// +// hbar_id: headerbar slot ID +// bmap_id: bitmap ID + + void +bx_term_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) +{ + UNUSED(hbar_id); + UNUSED(bmap_id); +} + + +// ::EXIT() +// +// Called before bochs terminates, to allow for a graceful +// exit from the native GUI mechanism. + + void +bx_term_gui_c::exit(void) +{ + if (!initialized) return; + clear(); + flush(); + endwin(); + BX_DEBUG(("exiting")); +} + + void +bx_term_gui_c::mouse_enabled_changed_specific (bx_bool val) +{ +} +#endif /* if BX_WITH_TERM */ |