- added instructions how to update the online documentation
[bochs-mirror.git] / gui / term.cc
bloba44f41a46aea558613d2c6ad244424b26c92cd58
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: term.cc,v 1.41 2008/06/22 08:32:59 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2000 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
30 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
31 // is used to know when we are exporting symbols and when we are importing.
32 #define BX_PLUGGABLE
34 #include "bochs.h"
35 #include "iodev.h"
36 #if BX_WITH_TERM
38 #include "icon_bochs.h"
40 extern "C" {
41 #include <curses.h>
42 #include <signal.h>
45 class bx_term_gui_c : public bx_gui_c {
46 public:
47 bx_term_gui_c(void) {}
48 DECLARE_GUI_VIRTUAL_METHODS()
49 #if BX_USE_IDLE_HACK
50 virtual void sim_is_idle(void);
51 #endif
53 virtual Bit32u get_sighandler_mask();
55 // called when registered signal arrives
56 virtual void sighandler(int sig);
59 // declare one instance of the gui object and call macro to insert the
60 // plugin code
61 static bx_term_gui_c *theGui = NULL;
62 IMPLEMENT_GUI_PLUGIN_CODE(term)
64 #define LOG_THIS theGui->
66 bx_bool initialized = 0;
67 static unsigned int text_rows = 25, text_cols = 80;
69 static short curses_color[8] = {
70 /* 0 */ COLOR_BLACK,
71 /* 1 */ COLOR_BLUE,
72 /* 2 */ COLOR_GREEN,
73 /* 3 */ COLOR_CYAN,
74 /* 4 */ COLOR_RED,
75 /* 5 */ COLOR_MAGENTA,
76 /* 6 */ COLOR_YELLOW,
77 /* 7 */ COLOR_WHITE
80 static chtype vga_to_term[128] = {
81 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7,
82 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5,
83 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9,
84 0xff, 0xd6, 0xdc, 0xe7, 0xa3, 0xa5, ' ', ' ',
85 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba,
86 0xbf, ' ', 0xac, ' ', ' ', 0xa1, 0xab, 0xbb,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, ' ', ' ', ' ', ' ',
93 ' ', ' ', ' ', ' ', ' ', ' ', 0xb5, ' ',
94 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
95 ' ', 0xb1, ' ', ' ', ' ', ' ', 0xf7, ' ',
96 0xb0, ' ', ' ', ' ', ' ', 0xb2, ' ', ' '
99 static void do_scan(int key_event, int shift, int ctrl, int alt)
101 /* At some point, cache alt/ctrl/shift so only when the state
102 changes do we simulate a press or release, to cut down on
103 keyboard input to the simulated machine */
105 BX_DEBUG(("key_event %d/0x%x %s%s%s", key_event, key_event,
106 shift ? "(shift)" : "",
107 ctrl ? "(ctrl)" : "",
108 alt ? "(alt)" : ""));
109 if(shift)
110 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L);
111 if(ctrl)
112 DEV_kbd_gen_scancode(BX_KEY_CTRL_L);
113 if(alt)
114 DEV_kbd_gen_scancode(BX_KEY_ALT_L);
115 DEV_kbd_gen_scancode(key_event);
116 key_event |= BX_KEY_RELEASED;
118 DEV_kbd_gen_scancode(key_event);
119 if(alt)
120 DEV_kbd_gen_scancode(BX_KEY_ALT_L|BX_KEY_RELEASED);
121 if(ctrl)
122 DEV_kbd_gen_scancode(BX_KEY_CTRL_L|BX_KEY_RELEASED);
123 if(shift)
124 DEV_kbd_gen_scancode(BX_KEY_SHIFT_L|BX_KEY_RELEASED);
127 Bit32u bx_term_gui_c::get_sighandler_mask()
129 return 0
130 #ifdef SIGHUP
131 | (1<<SIGHUP)
132 #endif
133 | (1<<SIGINT)
134 #ifdef SIGQUIT
135 | (1<<SIGQUIT)
136 #endif
137 #ifdef SIGSTOP
138 | (1<<SIGSTOP)
139 #endif
140 #ifdef SIGTSTP
141 | (1<<SIGTSTP)
142 #endif
143 | (1<<SIGTERM);
146 void bx_term_gui_c::sighandler(int signo)
148 switch(signo) {
149 case SIGINT:
150 do_scan(BX_KEY_C,0,1,0);
151 break;
152 #ifdef SIGSTOP
153 case SIGSTOP:
154 do_scan(BX_KEY_S,0,1,0);
155 break;
156 #endif
157 #ifdef SIGTSTP
158 case SIGTSTP:
159 do_scan(BX_KEY_Z,0,1,0);
160 break;
161 #endif
162 #ifdef SIGHUP
163 case SIGHUP:
164 BX_PANIC(("Received SIGHUP: quit simulation"));
165 break;
166 #endif
167 default:
168 BX_INFO(("sig %d caught",signo));
169 break;
173 // ::SPECIFIC_INIT()
175 // Called from gui.cc, once upon program startup, to allow for the
176 // specific GUI code (X11, BeOS, ...) to be initialized.
178 // argc, argv: not used right now, but the intention is to pass native GUI
179 // specific options from the command line. (X11 options, BeOS options,...)
181 // tilewidth, tileheight: for optimization, graphics_tile_update() passes
182 // only updated regions of the screen to the gui code to be redrawn.
183 // These define the dimensions of a region (tile).
184 // headerbar_y: A headerbar (toolbar) is display on the top of the
185 // VGA window, showing floppy status, and other information. It
186 // always assumes the width of the current VGA mode width, but
187 // it's height is defined by this parameter.
189 void bx_term_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight, unsigned headerbar_y)
191 put("TGUI");
193 // the ask menu causes trouble
194 io->set_log_action(LOGLEV_PANIC, ACT_FATAL);
195 // logfile should be different from stderr, otherwise terminal mode
196 // really ends up having fun
197 if (!strcmp(SIM->get_param_string(BXPN_LOG_FILENAME)->getptr(), "-"))
198 BX_PANIC(("cannot log to stderr in term mode"));
200 initscr();
201 start_color();
202 cbreak();
203 curs_set(2);
204 keypad(stdscr,TRUE);
205 nodelay(stdscr, TRUE);
206 noecho();
208 #if BX_HAVE_COLOR_SET
209 if (has_colors()) {
210 for (int i=0; i<8; i++) {
211 for (int j=0; j<8; j++) {
212 if ((i!=0)||(j!=0)) init_pair(i * 8 + j, j, i);
216 #endif
218 if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get())
219 BX_ERROR(("WARNING: private_colormap option ignored."));
221 initialized = 1;
224 void do_char(int character, int alt)
226 switch (character) {
227 // control keys
228 case 0x9: do_scan(BX_KEY_TAB,0,0,alt); break;
229 case 0xa: do_scan(BX_KEY_KP_ENTER,0,0,alt); break;
230 case 0xd: do_scan(BX_KEY_KP_DELETE,0,0,alt); break;
231 case 0x1: do_scan(BX_KEY_A,0,1,alt); break;
232 case 0x2: do_scan(BX_KEY_B,0,1,alt); break;
233 case 0x3: do_scan(BX_KEY_C,0,1,alt); break;
234 case 0x4: do_scan(BX_KEY_D,0,1,alt); break;
235 case 0x5: do_scan(BX_KEY_E,0,1,alt); break;
236 case 0x6: do_scan(BX_KEY_F,0,1,alt); break;
237 case 0x7: do_scan(BX_KEY_G,0,1,alt); break;
238 case 0x8: do_scan(BX_KEY_H,0,1,alt); break;
239 case 0xb: do_scan(BX_KEY_K,0,1,alt); break;
240 case 0xc: do_scan(BX_KEY_L,0,1,alt); break;
241 case 0xe: do_scan(BX_KEY_N,0,1,alt); break;
242 case 0xf: do_scan(BX_KEY_O,0,1,alt); break;
243 case 0x10: do_scan(BX_KEY_P,0,1,alt); break;
244 case 0x11: do_scan(BX_KEY_Q,0,1,alt); break;
245 case 0x12: do_scan(BX_KEY_R,0,1,alt); break;
246 case 0x13: do_scan(BX_KEY_S,0,1,alt); break;
247 case 0x14: do_scan(BX_KEY_T,0,1,alt); break;
248 case 0x15: do_scan(BX_KEY_U,0,1,alt); break;
249 case 0x16: do_scan(BX_KEY_V,0,1,alt); break;
250 case 0x17: do_scan(BX_KEY_W,0,1,alt); break;
251 case 0x18: do_scan(BX_KEY_X,0,1,alt); break;
252 case 0x19: do_scan(BX_KEY_Y,0,1,alt); break;
253 case 0x1a: do_scan(BX_KEY_Z,0,1,alt); break;
254 case 0x20: do_scan(BX_KEY_SPACE,0,0,alt); break;
255 case 0x107: do_scan(BX_KEY_BACKSPACE,0,0,alt); break;
256 case 0x102: do_scan(BX_KEY_DOWN,0,0,alt); break;
257 case 0x103: do_scan(BX_KEY_UP,0,0,alt); break;
258 case 0x104: do_scan(BX_KEY_LEFT,0,0,alt); break;
259 case 0x105: do_scan(BX_KEY_RIGHT,0,0,alt); break;
260 case 0x152: do_scan(BX_KEY_PAGE_DOWN,0,0,alt); break;
261 case 0x153: do_scan(BX_KEY_PAGE_UP,0,0,alt); break;
262 case 0x106: do_scan(BX_KEY_HOME,0,0,alt); break;
263 case 0x168: do_scan(BX_KEY_END,0,0,alt); break;
264 case 0x14b: do_scan(BX_KEY_INSERT,0,0,alt); break;
265 case 0x7f: do_scan(BX_KEY_DELETE,0,0,alt); break;
266 case 0x1b: do_scan(BX_KEY_ESC,0,0,alt); break;
267 case '!': do_scan(BX_KEY_1,1,0,alt); break;
268 case '\'': do_scan(BX_KEY_SINGLE_QUOTE,0,0,alt); break;
269 case '#': do_scan(BX_KEY_3,1,0,alt); break;
270 case '$': do_scan(BX_KEY_4,1,0,alt); break;
271 case '%': do_scan(BX_KEY_5,1,0,alt); break;
272 case '^': do_scan(BX_KEY_6,1,0,alt); break;
273 case '&': do_scan(BX_KEY_7,1,0,alt); break;
274 case '"': do_scan(BX_KEY_SINGLE_QUOTE,1,0,alt); break;
276 // ()*+,-./
277 case '(': do_scan(BX_KEY_9,1,0,alt); break;
278 case ')': do_scan(BX_KEY_0,1,0,alt); break;
279 case '*': do_scan(BX_KEY_8,1,0,alt); break;
280 case '+': do_scan(BX_KEY_EQUALS,1,0,alt); break;
281 case ',': do_scan(BX_KEY_COMMA,0,0,alt); break;
282 case '-': do_scan(BX_KEY_MINUS,0,0,alt); break;
283 case '.': do_scan(BX_KEY_PERIOD,0,0,alt); break;
284 case '/': do_scan(BX_KEY_SLASH,0,0,alt); break;
286 // 01234567
287 case '0': do_scan(BX_KEY_0,0,0,alt); break;
288 case '1': do_scan(BX_KEY_1,0,0,alt); break;
289 case '2': do_scan(BX_KEY_2,0,0,alt); break;
290 case '3': do_scan(BX_KEY_3,0,0,alt); break;
291 case '4': do_scan(BX_KEY_4,0,0,alt); break;
292 case '5': do_scan(BX_KEY_5,0,0,alt); break;
293 case '6': do_scan(BX_KEY_6,0,0,alt); break;
294 case '7': do_scan(BX_KEY_7,0,0,alt); break;
296 // 89:;<=>?
297 case '8': do_scan(BX_KEY_8,0,0,alt); break;
298 case '9': do_scan(BX_KEY_9,0,0,alt); break;
299 case ':': do_scan(BX_KEY_SEMICOLON,1,0,alt); break;
300 case ';': do_scan(BX_KEY_SEMICOLON,0,0,alt); break;
301 case '<': do_scan(BX_KEY_COMMA,1,0,alt); break;
302 case '=': do_scan(BX_KEY_EQUALS,0,0,alt); break;
303 case '>': do_scan(BX_KEY_PERIOD,1,0,alt); break;
304 case '?': do_scan(BX_KEY_SLASH,1,0,alt); break;
306 // @ABCDEFG
307 case '@': do_scan(BX_KEY_2,1,0,alt); break;
308 case 'A': do_scan(BX_KEY_A,1,0,alt); break;
309 case 'B': do_scan(BX_KEY_B,1,0,alt); break;
310 case 'C': do_scan(BX_KEY_C,1,0,alt); break;
311 case 'D': do_scan(BX_KEY_D,1,0,alt); break;
312 case 'E': do_scan(BX_KEY_E,1,0,alt); break;
313 case 'F': do_scan(BX_KEY_F,1,0,alt); break;
314 case 'G': do_scan(BX_KEY_G,1,0,alt); break;
316 // HIJKLMNO
317 case 'H': do_scan(BX_KEY_H,1,0,alt); break;
318 case 'I': do_scan(BX_KEY_I,1,0,alt); break;
319 case 'J': do_scan(BX_KEY_J,1,0,alt); break;
320 case 'K': do_scan(BX_KEY_K,1,0,alt); break;
321 case 'L': do_scan(BX_KEY_L,1,0,alt); break;
322 case 'M': do_scan(BX_KEY_M,1,0,alt); break;
323 case 'N': do_scan(BX_KEY_N,1,0,alt); break;
324 case 'O': do_scan(BX_KEY_O,1,0,alt); break;
326 // PQRSTUVW
327 case 'P': do_scan(BX_KEY_P,1,0,alt); break;
328 case 'Q': do_scan(BX_KEY_Q,1,0,alt); break;
329 case 'R': do_scan(BX_KEY_R,1,0,alt); break;
330 case 'S': do_scan(BX_KEY_S,1,0,alt); break;
331 case 'T': do_scan(BX_KEY_T,1,0,alt); break;
332 case 'U': do_scan(BX_KEY_U,1,0,alt); break;
333 case 'V': do_scan(BX_KEY_V,1,0,alt); break;
334 case 'W': do_scan(BX_KEY_W,1,0,alt); break;
336 // XYZ[\]^_
337 case 'X': do_scan(BX_KEY_X,1,0,alt); break;
338 case 'Y': do_scan(BX_KEY_Y,1,0,alt); break;
339 case 'Z': do_scan(BX_KEY_Z,1,0,alt); break;
340 case '{': do_scan(BX_KEY_LEFT_BRACKET,1,0,alt); break;
341 case '|': do_scan(BX_KEY_BACKSLASH,1,0,alt); break;
342 case '}': do_scan(BX_KEY_RIGHT_BRACKET,1,0,alt); break;
343 case '_': do_scan(BX_KEY_MINUS,1,0,alt); break;
345 // `abcdefg
346 case '`': do_scan(BX_KEY_GRAVE,0,0,alt); break;
347 case 'a': do_scan(BX_KEY_A,0,0,alt); break;
348 case 'b': do_scan(BX_KEY_B,0,0,alt); break;
349 case 'c': do_scan(BX_KEY_C,0,0,alt); break;
350 case 'd': do_scan(BX_KEY_D,0,0,alt); break;
351 case 'e': do_scan(BX_KEY_E,0,0,alt); break;
352 case 'f': do_scan(BX_KEY_F,0,0,alt); break;
353 case 'g': do_scan(BX_KEY_G,0,0,alt); break;
355 // hijklmno
356 case 'h': do_scan(BX_KEY_H,0,0,alt); break;
357 case 'i': do_scan(BX_KEY_I,0,0,alt); break;
358 case 'j': do_scan(BX_KEY_J,0,0,alt); break;
359 case 'k': do_scan(BX_KEY_K,0,0,alt); break;
360 case 'l': do_scan(BX_KEY_L,0,0,alt); break;
361 case 'm': do_scan(BX_KEY_M,0,0,alt); break;
362 case 'n': do_scan(BX_KEY_N,0,0,alt); break;
363 case 'o': do_scan(BX_KEY_O,0,0,alt); break;
365 // pqrstuvw
366 case 'p': do_scan(BX_KEY_P,0,0,alt); break;
367 case 'q': do_scan(BX_KEY_Q,0,0,alt); break;
368 case 'r': do_scan(BX_KEY_R,0,0,alt); break;
369 case 's': do_scan(BX_KEY_S,0,0,alt); break;
370 case 't': do_scan(BX_KEY_T,0,0,alt); break;
371 case 'u': do_scan(BX_KEY_U,0,0,alt); break;
372 case 'v': do_scan(BX_KEY_V,0,0,alt); break;
373 case 'w': do_scan(BX_KEY_W,0,0,alt); break;
375 // xyz{|}~
376 case 'x': do_scan(BX_KEY_X,0,0,alt); break;
377 case 'y': do_scan(BX_KEY_Y,0,0,alt); break;
378 case 'z': do_scan(BX_KEY_Z,0,0,alt); break;
379 case '[': do_scan(BX_KEY_LEFT_BRACKET,0,0,alt); break;
380 case '\\': do_scan(BX_KEY_BACKSLASH,0,0,alt); break;
381 case ']': do_scan(BX_KEY_RIGHT_BRACKET,0,0,alt); break;
382 case '~': do_scan(BX_KEY_GRAVE,1,0,alt); break;
384 // function keys
385 case KEY_F(1): do_scan(BX_KEY_F1,0,0,alt); break;
386 case KEY_F(2): do_scan(BX_KEY_F2,0,0,alt); break;
387 case KEY_F(3): do_scan(BX_KEY_F3,0,0,alt); break;
388 case KEY_F(4): do_scan(BX_KEY_F4,0,0,alt); break;
389 case KEY_F(5): do_scan(BX_KEY_F5,0,0,alt); break;
390 case KEY_F(6): do_scan(BX_KEY_F6,0,0,alt); break;
391 case KEY_F(7): do_scan(BX_KEY_F7,0,0,alt); break;
392 case KEY_F(8): do_scan(BX_KEY_F8,0,0,alt); break;
393 case KEY_F(9): do_scan(BX_KEY_F9,0,0,alt); break;
394 case KEY_F(10): do_scan(BX_KEY_F10,0,0,alt); break;
395 case KEY_F(11): do_scan(BX_KEY_F11,0,0,alt); break;
396 case KEY_F(12): do_scan(BX_KEY_F12,0,0,alt); break;
398 // shifted function keys
399 case KEY_F(13): do_scan(BX_KEY_F1,1,0,alt); break;
400 case KEY_F(14): do_scan(BX_KEY_F2,1,0,alt); break;
401 case KEY_F(15): do_scan(BX_KEY_F3,1,0,alt); break;
402 case KEY_F(16): do_scan(BX_KEY_F4,1,0,alt); break;
403 case KEY_F(17): do_scan(BX_KEY_F5,1,0,alt); break;
404 case KEY_F(18): do_scan(BX_KEY_F6,1,0,alt); break;
405 case KEY_F(19): do_scan(BX_KEY_F7,1,0,alt); break;
406 case KEY_F(20): do_scan(BX_KEY_F8,1,0,alt); break;
408 default:
409 if(character > 0x79) {
410 do_char(character - 0x80,1);
411 break;
414 BX_INFO(("character unhandled: 0x%x",character));
415 break;
419 // ::HANDLE_EVENTS()
421 // Called periodically (vga_update_interval in .bochsrc) so the
422 // the gui code can poll for keyboard, mouse, and other
423 // relevant events.
425 void bx_term_gui_c::handle_events(void)
427 int character;
428 while((character = getch()) != ERR) {
429 BX_DEBUG(("scancode(0x%x)",character));
430 do_char(character,0);
434 // ::FLUSH()
436 // Called periodically, requesting that the gui code flush all pending
437 // screen update requests.
439 void bx_term_gui_c::flush(void)
441 if (initialized) refresh();
444 // ::CLEAR_SCREEN()
446 // Called to request that the VGA region is cleared. Don't
447 // clear the area that defines the headerbar.
449 void bx_term_gui_c::clear_screen(void)
451 clear();
452 #if BX_HAVE_COLOR_SET
453 color_set(7, NULL);
454 #endif
455 #if BX_HAVE_MVHLINE
456 if (LINES > (int)text_rows) {
457 mvhline(text_rows, 0, ACS_HLINE, text_cols);
459 #endif
460 #if BX_HAVE_MVVLINE
461 if (COLS > (int)text_cols) {
462 mvvline(0, text_cols, ACS_VLINE, text_rows);
464 #endif
465 if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) {
466 mvaddch(text_rows, text_cols, ACS_LRCORNER);
470 int get_color_pair(Bit8u vga_attr)
472 int term_attr = curses_color[vga_attr & 0x07];
473 term_attr |= (curses_color[(vga_attr & 0x70) >> 4] << 3);
474 return term_attr;
477 chtype get_term_char(Bit8u vga_char[])
479 int term_char;
481 if ((vga_char[1] & 0x0f) == ((vga_char[1] >> 4) & 0x0f)) {
482 return ' ';
484 switch (vga_char[0]) {
485 case 0x04: term_char = ACS_DIAMOND; break;
486 case 0x18: term_char = ACS_UARROW; break;
487 case 0x19: term_char = ACS_DARROW; break;
488 case 0x1a: term_char = ACS_RARROW; break;
489 case 0x1b: term_char = ACS_LARROW; break;
490 case 0xc4:
491 case 0xcd: term_char = ACS_HLINE; break;
492 case 0xb3:
493 case 0xba: term_char = ACS_VLINE; break;
494 case 0xc9:
495 case 0xd5:
496 case 0xd6:
497 case 0xda: term_char = ACS_ULCORNER; break;
498 case 0xb7:
499 case 0xb8:
500 case 0xbb:
501 case 0xbf: term_char = ACS_URCORNER; break;
502 case 0xc0:
503 case 0xc8:
504 case 0xd3:
505 case 0xd4: term_char = ACS_LLCORNER; break;
506 case 0xbc:
507 case 0xbd:
508 case 0xbe:
509 case 0xd9: term_char = ACS_LRCORNER; break;
510 case 0xc3:
511 case 0xc6:
512 case 0xc7:
513 case 0xcc: term_char = ACS_LTEE; break;
514 case 0xb4:
515 case 0xb5:
516 case 0xb6:
517 case 0xb9: term_char = ACS_RTEE; break;
518 case 0xc2:
519 case 0xcb:
520 case 0xd1:
521 case 0xd2: term_char = ACS_TTEE; break;
522 case 0xc1:
523 case 0xca:
524 case 0xcf:
525 case 0xd0: term_char = ACS_BTEE; break;
526 case 0xc5:
527 case 0xce:
528 case 0xd7:
529 case 0xd8: term_char = ACS_PLUS; break;
530 case 0xb0:
531 case 0xb1: term_char = ACS_CKBOARD; break;
532 case 0xb2: term_char = ACS_BOARD; break;
533 case 0xdb: term_char = ACS_BLOCK; break;
534 default:
535 if (vga_char[0] > 0x7f) {
536 term_char = vga_to_term[vga_char[0]-0x80];
537 } else if (vga_char[0] > 0x1f) {
538 term_char = vga_char[0];
539 } else {
540 term_char = ' ';
544 return term_char;
547 // ::TEXT_UPDATE()
549 // Called in a VGA text mode, to update the screen with
550 // new content.
552 // old_text: array of character/attributes making up the contents
553 // of the screen from the last call. See below
554 // new_text: array of character/attributes making up the current
555 // contents, which should now be displayed. See below
557 // format of old_text & new_text: each is tm_info.line_offset*text_rows
558 // bytes long. Each character consists of 2 bytes. The first by is
559 // the character value, the second is the attribute byte.
561 // cursor_x: new x location of cursor
562 // cursor_y: new y location of cursor
563 // tm_info: this structure contains information for additional
564 // features in text mode (cursor shape, line offset,...)
566 void bx_term_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
567 unsigned long cursor_x, unsigned long cursor_y,
568 bx_vga_tminfo_t tm_info)
570 unsigned char *old_line, *new_line, *new_start;
571 unsigned char cAttr;
572 unsigned int hchars, rows, x, y;
573 chtype ch;
574 bx_bool force_update = 0;
576 if(charmap_updated) {
577 force_update = 1;
578 charmap_updated = 0;
581 new_start = new_text;
582 rows = text_rows;
583 y = 0;
584 do {
585 hchars = text_cols;
586 new_line = new_text;
587 old_line = old_text;
588 x = 0;
589 do {
590 if (force_update || (old_text[0] != new_text[0])
591 || (old_text[1] != new_text[1])) {
592 #if BX_HAVE_COLOR_SET
593 if (has_colors()) {
594 color_set(get_color_pair(new_text[1]), NULL);
596 #endif
597 ch = get_term_char(&new_text[0]);
598 if ((new_text[1] & 0x08) > 0) ch |= A_BOLD;
599 if ((new_text[1] & 0x80) > 0) ch |= A_BLINK;
600 mvaddch(y, x, ch);
602 x++;
603 new_text+=2;
604 old_text+=2;
605 } while (--hchars);
606 y++;
607 new_text = new_line + tm_info.line_offset;
608 old_text = old_line + tm_info.line_offset;
609 } while (--rows);
611 if ((cursor_x<text_cols) && (cursor_y<text_rows)
612 && (tm_info.cs_start <= tm_info.cs_end)) {
613 if(cursor_x>0)
614 cursor_x--;
615 else {
616 cursor_x=COLS-1;
617 cursor_y--;
619 cAttr = new_start[cursor_y*tm_info.line_offset+cursor_x*2+1];
620 #if BX_HAVE_COLOR_SET
621 if (has_colors()) {
622 color_set(get_color_pair(cAttr), NULL);
624 #endif
625 ch = get_term_char(&new_start[cursor_y*tm_info.line_offset+cursor_x*2]);
626 if ((cAttr & 0x08) > 0) ch |= A_BOLD;
627 if ((cAttr & 0x80) > 0) ch |= A_REVERSE;
628 mvaddch(cursor_y, cursor_x, ch);
629 curs_set(2);
630 } else {
631 curs_set(0);
635 int bx_term_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
637 return 0;
640 int bx_term_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
642 return 0;
645 // ::PALETTE_CHANGE()
647 // Allocate a color in the native GUI, for this color, and put
648 // it in the colormap location 'index'.
649 // returns: 0=no screen update needed (color map change has direct effect)
650 // 1=screen updated needed (redraw using current colormap)
652 bx_bool bx_term_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
654 BX_DEBUG(("color pallete request (%d,%d,%d,%d) ignored", index,red,green,blue));
655 return(0);
659 // ::GRAPHICS_TILE_UPDATE()
661 // Called to request that a tile of graphics be drawn to the
662 // screen, since info in this region has changed.
664 // tile: array of 8bit values representing a block of pixels with
665 // dimension equal to the 'tilewidth' & 'tileheight' parameters to
666 // ::specific_init(). Each value specifies an index into the
667 // array of colors you allocated for ::palette_change()
668 // x0: x origin of tile
669 // y0: y origin of tile
671 // note: origin of tile and of window based on (0,0) being in the upper
672 // left of the window.
674 void bx_term_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
678 // ::DIMENSION_UPDATE()
680 // Called when the VGA mode changes it's X,Y dimensions.
681 // Resize the window to this size, but you need to add on
682 // the height of the headerbar to the Y value.
684 // x: new VGA x size
685 // y: new VGA y size (add headerbar_y parameter from ::specific_init().
686 // fheight: new VGA character height in text mode
687 // fwidth : new VGA character width in text mode
688 // bpp : bits per pixel in graphics mode
690 void bx_term_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
692 if (bpp > 8) {
693 BX_PANIC(("%d bpp graphics mode not supported", bpp));
695 if (fheight > 0) {
696 text_cols = x / fwidth;
697 text_rows = y / fheight;
698 #if BX_HAVE_COLOR_SET
699 color_set(7, NULL);
700 #endif
701 #if BX_HAVE_MVHLINE
702 if (LINES > (int)text_rows) {
703 mvhline(text_rows, 0, ACS_HLINE, text_cols);
705 #endif
706 #if BX_HAVE_MVVLINE
707 if (COLS > (int)text_cols) {
708 mvvline(0, text_cols, ACS_VLINE, text_rows);
710 #endif
711 if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) {
712 mvaddch(text_rows, text_cols, ACS_LRCORNER);
717 // ::CREATE_BITMAP()
719 // Create a monochrome bitmap of size 'xdim' by 'ydim', which will
720 // be drawn in the headerbar. Return an integer ID to the bitmap,
721 // with which the bitmap can be referenced later.
723 // bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
724 // bit0 is the left most pixel, bit7 is the right most pixel.
725 // xdim: x dimension of bitmap
726 // ydim: y dimension of bitmap
728 unsigned bx_term_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
730 return(0);
733 // ::HEADERBAR_BITMAP()
735 // Called to install a bitmap in the bochs headerbar (toolbar).
737 // bmap_id: will correspond to an ID returned from
738 // ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
739 // or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
740 // available leftmost or rightmost space.
741 // alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
742 // meaning install the bitmap in the next
743 // available leftmost or rightmost space.
744 // f: a 'C' function pointer to callback when the mouse is clicked in
745 // the boundaries of this bitmap.
747 unsigned bx_term_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
749 return(0);
752 // ::SHOW_HEADERBAR()
754 // Show (redraw) the current headerbar, which is composed of
755 // currently installed bitmaps.
757 void bx_term_gui_c::show_headerbar(void)
761 // ::REPLACE_BITMAP()
763 // Replace the bitmap installed in the headerbar ID slot 'hbar_id',
764 // with the one specified by 'bmap_id'. 'bmap_id' will have
765 // been generated by ::create_bitmap(). The old and new bitmap
766 // must be of the same size. This allows the bitmap the user
767 // sees to change, when some action occurs. For example when
768 // the user presses on the floppy icon, it then displays
769 // the ejected status.
771 // hbar_id: headerbar slot ID
772 // bmap_id: bitmap ID
774 void bx_term_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
778 // ::EXIT()
780 // Called before bochs terminates, to allow for a graceful
781 // exit from the native GUI mechanism.
783 void bx_term_gui_c::exit(void)
785 if (!initialized) return;
786 clear();
787 flush();
788 endwin();
789 BX_DEBUG(("exiting"));
792 void bx_term_gui_c::mouse_enabled_changed_specific(bx_bool val)
796 #if BX_USE_IDLE_HACK
797 void bx_term_gui_c::sim_is_idle()
799 int res;
800 fd_set readfds;
802 struct timeval timeout;
803 timeout.tv_sec = 0;
804 timeout.tv_usec = 1000; /* 1/1000 s */
806 FD_ZERO(&readfds);
807 FD_SET(0, &readfds); // Wait for input
809 res = select(1, &readfds, NULL, NULL, &timeout);
811 switch(res)
813 case -1: /* select() error - should not happen */
814 // This can happen when we have a alarm running, lets return
815 // perror("sim_is_idle: select() failure\n");
816 //handle_events();
817 return;
818 case 0: /* timeout */
819 //handle_events();
820 return;
822 //handle_events();
824 #endif
826 #endif /* if BX_WITH_TERM */