diff options
Diffstat (limited to 'tools/ioemu/gui/gui.cc')
-rw-r--r-- | tools/ioemu/gui/gui.cc | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/tools/ioemu/gui/gui.cc b/tools/ioemu/gui/gui.cc new file mode 100644 index 0000000000..a6cd30732a --- /dev/null +++ b/tools/ioemu/gui/gui.cc @@ -0,0 +1,592 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: gui.cc,v 1.73 2003/12/18 20:04:48 vruppert Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2002 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 + + +#include <signal.h> +#include "bochs.h" +#include "gui/bitmaps/floppya.h" +#include "gui/bitmaps/floppyb.h" +#include "gui/bitmaps/mouse.h" +#include "gui/bitmaps/reset.h" +#include "gui/bitmaps/power.h" +#include "gui/bitmaps/snapshot.h" +#include "gui/bitmaps/copy.h" +#include "gui/bitmaps/paste.h" +#include "gui/bitmaps/configbutton.h" +#include "gui/bitmaps/cdromd.h" +#include "gui/bitmaps/userbutton.h" +#if BX_WITH_MACOS +# include <Disks.h> +#endif + +bx_gui_c *bx_gui = NULL; + +#define BX_GUI_THIS bx_gui-> +#define LOG_THIS BX_GUI_THIS + +bx_gui_c::bx_gui_c(void) +{ + put("GUI"); // Init in specific_init + settype(GUILOG); +} + +bx_gui_c::~bx_gui_c() +{ +} + + void +bx_gui_c::init(int argc, char **argv, unsigned tilewidth, unsigned tileheight) +{ + specific_init(argc, argv, tilewidth, tileheight, BX_HEADER_BAR_Y); + + // Define some bitmaps to use in the headerbar + BX_GUI_THIS floppyA_bmap_id = create_bitmap(bx_floppya_bmap, + BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y); + BX_GUI_THIS floppyA_eject_bmap_id = create_bitmap(bx_floppya_eject_bmap, + BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y); + BX_GUI_THIS floppyB_bmap_id = create_bitmap(bx_floppyb_bmap, + BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); + BX_GUI_THIS floppyB_eject_bmap_id = create_bitmap(bx_floppyb_eject_bmap, + BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); + BX_GUI_THIS cdromD_bmap_id = create_bitmap(bx_cdromd_bmap, + BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); + BX_GUI_THIS cdromD_eject_bmap_id = create_bitmap(bx_cdromd_eject_bmap, + BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); + BX_GUI_THIS mouse_bmap_id = create_bitmap(bx_mouse_bmap, + BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); + BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap, + BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); + + + BX_GUI_THIS power_bmap_id = create_bitmap(bx_power_bmap, BX_POWER_BMAP_X, BX_POWER_BMAP_Y); + BX_GUI_THIS reset_bmap_id = create_bitmap(bx_reset_bmap, BX_RESET_BMAP_X, BX_RESET_BMAP_Y); + BX_GUI_THIS snapshot_bmap_id = create_bitmap(bx_snapshot_bmap, BX_SNAPSHOT_BMAP_X, BX_SNAPSHOT_BMAP_Y); + BX_GUI_THIS copy_bmap_id = create_bitmap(bx_copy_bmap, BX_COPY_BMAP_X, BX_COPY_BMAP_Y); + BX_GUI_THIS paste_bmap_id = create_bitmap(bx_paste_bmap, BX_PASTE_BMAP_X, BX_PASTE_BMAP_Y); + BX_GUI_THIS config_bmap_id = create_bitmap(bx_config_bmap, BX_CONFIG_BMAP_X, BX_CONFIG_BMAP_Y); + BX_GUI_THIS user_bmap_id = create_bitmap(bx_user_bmap, BX_USER_BMAP_X, BX_USER_BMAP_Y); + + + // Add the initial bitmaps to the headerbar, and enable callback routine, for use + // when that bitmap is clicked on + + // Floppy A: + BX_GUI_THIS floppyA_status = DEV_floppy_get_media_status(0); + if (BX_GUI_THIS floppyA_status) + BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_bmap_id, + BX_GRAVITY_LEFT, floppyA_handler); + else + BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_eject_bmap_id, + BX_GRAVITY_LEFT, floppyA_handler); + + // Floppy B: + BX_GUI_THIS floppyB_status = DEV_floppy_get_media_status(1); + if (BX_GUI_THIS floppyB_status) + BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_bmap_id, + BX_GRAVITY_LEFT, floppyB_handler); + else + BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_eject_bmap_id, + BX_GRAVITY_LEFT, floppyB_handler); + + // CDROM, + // valgrinds says that the harddrive object is not be initialised yet, + // so we just set the bitmap to ejected for now +#if 0 + if (DEV_hd_present()) { + Bit32u handle = DEV_hd_get_first_cd_handle(); + BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle); + } + + if (BX_GUI_THIS cdromD_status) + BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_bmap_id, + BX_GRAVITY_LEFT, cdromD_handler); + else +#endif + BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_eject_bmap_id, + BX_GRAVITY_LEFT, cdromD_handler); + + // Mouse button + if (bx_options.Omouse_enabled->get ()) + BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS mouse_bmap_id, + BX_GRAVITY_LEFT, toggle_mouse_enable); + else + BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS nomouse_bmap_id, + BX_GRAVITY_LEFT, toggle_mouse_enable); + + // These are the buttons on the right side. They are created in order + // of right to left. + + // Power button + BX_GUI_THIS power_hbar_id = headerbar_bitmap(BX_GUI_THIS power_bmap_id, + BX_GRAVITY_RIGHT, power_handler); + // Reset button + BX_GUI_THIS reset_hbar_id = headerbar_bitmap(BX_GUI_THIS reset_bmap_id, + BX_GRAVITY_RIGHT, reset_handler); + // Configure button + BX_GUI_THIS config_hbar_id = headerbar_bitmap(BX_GUI_THIS config_bmap_id, + BX_GRAVITY_RIGHT, config_handler); + // Snapshot button + BX_GUI_THIS snapshot_hbar_id = headerbar_bitmap(BX_GUI_THIS snapshot_bmap_id, + BX_GRAVITY_RIGHT, snapshot_handler); + // Paste button + BX_GUI_THIS paste_hbar_id = headerbar_bitmap(BX_GUI_THIS paste_bmap_id, + BX_GRAVITY_RIGHT, paste_handler); + // Copy button + BX_GUI_THIS copy_hbar_id = headerbar_bitmap(BX_GUI_THIS copy_bmap_id, + BX_GRAVITY_RIGHT, copy_handler); + // User button + BX_GUI_THIS user_hbar_id = headerbar_bitmap(BX_GUI_THIS user_bmap_id, + BX_GRAVITY_RIGHT, userbutton_handler); + + if(bx_options.Otext_snapshot_check->get()) { + bx_pc_system.register_timer(this, bx_gui_c::snapshot_checker, (unsigned) 1000000, 1, 1, "snap_chk"); + } + + BX_GUI_THIS charmap_updated = 0; + + show_headerbar(); +} + +void +bx_gui_c::update_drive_status_buttons (void) { + BX_GUI_THIS floppyA_status = + DEV_floppy_get_media_status(0) + && bx_options.floppya.Ostatus->get (); + BX_GUI_THIS floppyB_status = + DEV_floppy_get_media_status(1) + && bx_options.floppyb.Ostatus->get (); + Bit32u handle = DEV_hd_get_first_cd_handle(); + BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle); + if (BX_GUI_THIS floppyA_status) + replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_bmap_id); + else { +#if BX_WITH_MACOS + // If we are using the Mac floppy driver, eject the disk + // from the floppy drive. This doesn't work in MacOS X. + if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) + DiskEject(1); +#endif + replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_eject_bmap_id); + } + if (BX_GUI_THIS floppyB_status) + replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_bmap_id); + else { +#if BX_WITH_MACOS + // If we are using the Mac floppy driver, eject the disk + // from the floppy drive. This doesn't work in MacOS X. + if (!strcmp(bx_options.floppyb.Opath->getptr (), SuperDrive)) + DiskEject(1); +#endif + replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_eject_bmap_id); + } + if (BX_GUI_THIS cdromD_status) + replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_bmap_id); + else { + replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_eject_bmap_id); + } +} + + void +bx_gui_c::floppyA_handler(void) +{ + if (bx_options.floppya.Odevtype->get() == BX_FLOPPY_NONE) + return; // no primary floppy device present +#ifdef WIN32 + if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), + "rfb")) { + // instead of just toggling the status, call win32dialog to bring up + // a dialog asking what disk image you want to switch to. + int ret = SIM->ask_param (BXP_FLOPPYA_PATH); + if (ret > 0) { + BX_GUI_THIS update_drive_status_buttons (); + } + return; + } +#endif + BX_GUI_THIS floppyA_status = !BX_GUI_THIS floppyA_status; + DEV_floppy_set_media_status(0, BX_GUI_THIS floppyA_status); + BX_GUI_THIS update_drive_status_buttons (); +} + + void +bx_gui_c::floppyB_handler(void) +{ + if (bx_options.floppyb.Odevtype->get() == BX_FLOPPY_NONE) + return; // no secondary floppy device present +#ifdef WIN32 + if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), + "rfb")) { + // instead of just toggling the status, call win32dialog to bring up + // a dialog asking what disk image you want to switch to. + int ret = SIM->ask_param (BXP_FLOPPYB_PATH); + if (ret > 0) { + BX_GUI_THIS update_drive_status_buttons (); + } + return; + } +#endif + BX_GUI_THIS floppyB_status = !BX_GUI_THIS floppyB_status; + DEV_floppy_set_media_status(1, BX_GUI_THIS floppyB_status); + BX_GUI_THIS update_drive_status_buttons (); +} + + void +bx_gui_c::cdromD_handler(void) +{ + Bit32u handle = DEV_hd_get_first_cd_handle(); + if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), + "wx")) { + // instead of just toggling the status, call wxWindows to bring up + // a dialog asking what disk image you want to switch to. + // BBD: for now, find the first cdrom and call ask_param on that. + // Since we could have multiple cdroms now, maybe we should be adding + // one cdrom button for each? + bx_param_c *cdrom = SIM->get_first_cdrom (); + if (cdrom == NULL) + return; // no cdrom found + int ret = SIM->ask_param (cdrom->get_id ()); + if (ret < 0) return; // cancelled + // eject and then insert the disk. If the new path is invalid, + // the status will return 0. + unsigned status = DEV_hd_set_cd_media_status(handle, 0); + printf ("eject disk, new_status is %d\n", status); + status = DEV_hd_set_cd_media_status(handle, 1); + printf ("insert disk, new_status is %d\n", status); + fflush (stdout); + BX_GUI_THIS cdromD_status = status; + } else { + BX_GUI_THIS cdromD_status = + DEV_hd_set_cd_media_status(handle, !BX_GUI_THIS cdromD_status); + } + BX_GUI_THIS update_drive_status_buttons (); +} + + void +bx_gui_c::reset_handler(void) +{ + BX_INFO(( "system RESET callback." )); + bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */ + for (int i=0; i<BX_SMP_PROCESSORS; i++) + BX_CPU(i)->reset(BX_RESET_HARDWARE); +} + + void +bx_gui_c::power_handler(void) +{ + // the user pressed power button, so there's no doubt they want bochs + // to quit. Change panics to fatal for the GUI and then do a panic. + bx_user_quit = 1; + LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); + BX_PANIC (("POWER button turned off.")); + // shouldn't reach this point, but if you do, QUIT!!! + fprintf (stderr, "Bochs is exiting because you pressed the power button.\n"); + BX_EXIT (1); +} + +Bit32s +bx_gui_c::make_text_snapshot (char **snapshot, Bit32u *length) +{ + Bit8u* raw_snap = NULL; + char *clean_snap; + unsigned line_addr, txt_addr, txHeight, txWidth; + + DEV_vga_get_text_snapshot(&raw_snap, &txHeight, &txWidth); + if (txHeight <= 0) return -1; + clean_snap = (char*) malloc(txHeight*(txWidth+2)+1); + txt_addr = 0; + for (unsigned i=0; i<txHeight; i++) { + line_addr = i * txWidth * 2; + for (unsigned j=0; j<(txWidth*2); j+=2) { + clean_snap[txt_addr++] = raw_snap[line_addr+j]; + } + while ((txt_addr > 0) && (clean_snap[txt_addr-1] == ' ')) txt_addr--; +#ifdef WIN32 + if(!(bx_options.Otext_snapshot_check->get())) { + clean_snap[txt_addr++] = 13; + } +#endif + clean_snap[txt_addr++] = 10; + } + clean_snap[txt_addr] = 0; + *snapshot = clean_snap; + *length = txt_addr; + return 0; +} + +// create a text snapshot and copy to the system clipboard. On guis that +// we haven't figured out how to support yet, dump to a file instead. + void +bx_gui_c::copy_handler(void) +{ + Bit32u len; + char *text_snapshot; + if (make_text_snapshot (&text_snapshot, &len) < 0) { + BX_INFO(( "copy button failed, mode not implemented")); + return; + } + if (!BX_GUI_THIS set_clipboard_text(text_snapshot, len)) { + // platform specific code failed, use portable code instead + FILE *fp = fopen("copy.txt", "w"); + fwrite(text_snapshot, 1, len, fp); + fclose(fp); + } + free(text_snapshot); +} + +// Check the current text snapshot against file snapchk.txt. + void +bx_gui_c::snapshot_checker(void * this_ptr) +{ + char filename[BX_PATHNAME_LEN]; + strcpy(filename,"snapchk.txt"); + FILE *fp = fopen(filename, "rb"); + if(fp) { + char *text_snapshot; + Bit32u len; + if (make_text_snapshot (&text_snapshot, &len) < 0) { + return; + } + char *compare_snapshot = (char *) malloc((len+1) * sizeof(char)); + fread(compare_snapshot, 1, len, fp); + fclose(fp); + strcpy(filename,"snapmask.txt"); + fp=fopen(filename, "rb"); + if(fp) { + char *mask_snapshot = (char *) malloc((len+1) * sizeof(char)); + unsigned i; + bx_bool flag = 1; + fread(mask_snapshot, 1, len, fp); + fclose(fp); + for(i=0;i<len;i++) { + if((text_snapshot[i] != compare_snapshot[i]) && + (compare_snapshot[i] == mask_snapshot[i])) { + flag = 0; + break; + } + } + if(flag) { + if(!memcmp(text_snapshot,compare_snapshot,len)) { + BX_PASS(("Test Passed.")); + } else { + BX_PASS(("Test Passed with Mask.")); + } + } + } else { + if(!memcmp(text_snapshot,compare_snapshot,len)) { + BX_PASS(("Test Passed.")); + } + } + free(compare_snapshot); + free(text_snapshot); + } +} + +// create a text snapshot and dump it to a file + void +bx_gui_c::snapshot_handler(void) +{ + char *text_snapshot; + Bit32u len; + if (make_text_snapshot (&text_snapshot, &len) < 0) { + BX_ERROR(( "snapshot button failed, mode not implemented")); + return; + } + //FIXME + char filename[BX_PATHNAME_LEN]; +#ifdef WIN32 + if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), + "rfb")) { +#else + if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), + "wx")) { +#endif + int ret = SIM->ask_filename (filename, sizeof(filename), + "Save snapshot as...", "snapshot.txt", + bx_param_string_c::SAVE_FILE_DIALOG); + if (ret < 0) { // cancelled + free(text_snapshot); + return; + } + } else { + strcpy (filename, "snapshot.txt"); + } + FILE *fp = fopen(filename, "wb"); + fwrite(text_snapshot, 1, len, fp); + fclose(fp); + free(text_snapshot); +} + +// Read ASCII chars from the system clipboard and paste them into bochs. +// Note that paste cannot work with the key mapping tables loaded. + void +bx_gui_c::paste_handler(void) +{ + Bit32s nbytes; + Bit8u *bytes; + if (!bx_keymap.isKeymapLoaded ()) { + BX_ERROR (("keyboard_mapping disabled, so paste cannot work")); + return; + } + if (!BX_GUI_THIS get_clipboard_text(&bytes, &nbytes)) { + BX_ERROR (("paste not implemented on this platform")); + return; + } + BX_INFO (("pasting %d bytes", nbytes)); + DEV_kbd_paste_bytes (bytes, nbytes); +} + + + void +bx_gui_c::config_handler(void) +{ + if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), + "rfb")) { + SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG); + } +} + + void +bx_gui_c::toggle_mouse_enable(void) +{ + int old = bx_options.Omouse_enabled->get (); + BX_DEBUG (("toggle mouse_enabled, now %d", !old)); + bx_options.Omouse_enabled->set (!old); +} + + void +bx_gui_c::userbutton_handler(void) +{ + unsigned shortcut[4]; + unsigned p; + char *user_shortcut; + int i, len, ret = 1; + + len = 0; +#ifdef WIN32 + if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), + "rfb")) { +#else + if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), + "wx")) { +#endif + ret = SIM->ask_param (BXP_USER_SHORTCUT); + } + user_shortcut = bx_options.Ouser_shortcut->getptr(); + if ((ret > 0) && user_shortcut[0] && (strcmp(user_shortcut, "none"))) { + len = 0; + p = 0; + while ((p < strlen(user_shortcut)) && (len < 3)) { + if (!strncmp(user_shortcut+p, "alt", 3)) { + shortcut[len++] = BX_KEY_ALT_L; + p += 3; + } else if (!strncmp(user_shortcut+p, "ctrl", 4)) { + shortcut[len++] = BX_KEY_CTRL_L; + p += 4; + } else if (!strncmp(user_shortcut+p, "del", 3)) { + shortcut[len++] = BX_KEY_DELETE; + p += 3; + } else if (!strncmp(user_shortcut+p, "esc", 3)) { + shortcut[len++] = BX_KEY_ESC; + p += 3; + } else if (!strncmp(user_shortcut+p, "f1", 2)) { + shortcut[len++] = BX_KEY_F1; + p += 2; + } else if (!strncmp(user_shortcut+p, "f4", 2)) { + shortcut[len++] = BX_KEY_F4; + p += 2; + } else if (!strncmp(user_shortcut+p, "tab", 3)) { + shortcut[len++] = BX_KEY_TAB; + p += 3; + } else if (!strncmp(user_shortcut+p, "win", 3)) { + shortcut[len++] = BX_KEY_WIN_L; + p += 3; + } else if (!strncmp(user_shortcut+p, "bksp", 4)) { + shortcut[len++] = BX_KEY_BACKSPACE; + p += 4; + } else { + BX_ERROR(("Unknown shortcut %s ignored", user_shortcut)); + return; + } + } + i = 0; + while (i < len) { + DEV_kbd_gen_scancode(shortcut[i++]); + } + i--; + while (i >= 0) { + DEV_kbd_gen_scancode(shortcut[i--] | BX_KEY_RELEASED); + } + } +} + + void +bx_gui_c::mouse_enabled_changed (bx_bool val) +{ + // This is only called when SIM->get_init_done is 1. Note that VAL + // is the new value of mouse_enabled, which may not match the old + // value which is still in bx_options.Omouse_enabled->get (). + BX_DEBUG (("replacing the mouse bitmaps")); + if (val) + BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS mouse_bmap_id); + else + BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS nomouse_bmap_id); + // give the GUI a chance to respond to the event. Most guis will hide + // the native mouse cursor and do something to trap the mouse inside the + // bochs VGA display window. + BX_GUI_THIS mouse_enabled_changed_specific (val); +} + +void +bx_gui_c::init_signal_handlers () +{ +#if BX_GUI_SIGHANDLER + if (bx_gui_sighandler) + { + Bit32u mask = bx_gui->get_sighandler_mask (); + for (Bit32u sig=0; sig<32; sig++) + { + if (mask & (1<<sig)) + signal (sig, bx_signal_handler); + } + } +#endif +} + + void +bx_gui_c::set_text_charmap(Bit8u *fbuffer) +{ + memcpy(& BX_GUI_THIS vga_charmap, fbuffer, 0x2000); + for (unsigned i=0; i<256; i++) BX_GUI_THIS char_changed[i] = 1; + BX_GUI_THIS charmap_updated = 1; +} + + void +bx_gui_c::set_text_charbyte(Bit16u address, Bit8u data) +{ + BX_GUI_THIS vga_charmap[address] = data; + BX_GUI_THIS char_changed[address >> 5] = 1; + BX_GUI_THIS charmap_updated = 1; +} |