diff --git a/bochs/gui/wxdialog.cc b/bochs/gui/wxdialog.cc index 9aeec02b2..33ca796d6 100644 --- a/bochs/gui/wxdialog.cc +++ b/bochs/gui/wxdialog.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////// -// $Id: wxdialog.cc,v 1.16 2002-09-01 21:24:14 bdenney Exp $ +// $Id: wxdialog.cc,v 1.17 2002-09-02 17:03:07 bdenney Exp $ ///////////////////////////////////////////////////////////////// // // misc/wxdialog.cc @@ -1000,6 +1000,169 @@ void NetConfigDialog::ShowHelp () } +////////////////////////////////////////////////////////////////////// +// LogOptionsDialog implementation +////////////////////////////////////////////////////////////////////// +// Structure: +// vertSizer: +// prompt +// gridSizer 2 columns: +// "debug" +// action[0] = wxChoice +// "info" +// action[1] = wxChoice +// "error" +// action[2] = wxChoice +// "panic" +// action[3] = wxChoice +// buttonSizer: +// advanced +// help +// cancel +// ok + +// all events go to OnEvent method +BEGIN_EVENT_TABLE(LogOptionsDialog, wxDialog) + EVT_BUTTON(-1, LogOptionsDialog::OnEvent) + EVT_CHECKBOX(-1, LogOptionsDialog::OnEvent) + EVT_TEXT(-1, LogOptionsDialog::OnEvent) +END_EVENT_TABLE() + + +LogOptionsDialog::LogOptionsDialog( + wxWindow* parent, + wxWindowID id) + : wxDialog (parent, id, "", wxDefaultPosition, wxDefaultSize, + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + static char *names[] = LOG_OPTS_NAMES; + static char *choices[] = LOG_OPTS_CHOICES; + static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3}; + SetTitle (LOG_OPTS_TITLE); + vertSizer = new wxBoxSizer (wxVERTICAL); + // top level objects + wxStaticText *text = new wxStaticText (this, -1, LOG_OPTS_PROMPT); + vertSizer->Add (text, 0, wxALL, 20); + gridSizer = new wxFlexGridSizer (2); + vertSizer->Add (gridSizer, 1, wxLEFT, 40); + text = new wxStaticText (this, -1, LOG_OPTS_ADV); + vertSizer->Add (text, 0, wxALL, 20); + buttonSizer = new wxBoxSizer (wxHORIZONTAL); + vertSizer->Add (buttonSizer, 0, wxALIGN_RIGHT); + + // figure out how wide the wxChoice boxes need to be for longest string + int choiceWidth; +#if 1 + // Calculate length of longest choice, to help decide how wide the + // wxChoice controls should be. Otherwise they are sized according to + // the initial choice string, which may not be the longest. + wxString longest (choices[LOG_OPTS_LONGEST_CHOICE]); + wxClientDC dc (this); + wxCoord w, h; + dc.GetTextExtent (longest, &w, &h); + wxLogDebug ("extent of '%s' is %d,%d", longest.c_str (), w, h); + choiceWidth = w * 3 / 2; // 50% wider than longest string +#else + choiceWidth = 150; // hardcoded width, yuck. +#endif + // gridSizer contents + gridSizer->AddGrowableCol (1); + for (int evtype=0; evtypeAdd (new wxStaticText (this, -1, names[evtype]), 0, wxALL, 5); + gridSizer->Add (action[evtype] = new wxChoice (this, -1), 1, wxALL|wxGROW, 5); + // fill in the choices in the wxChoice field + int lastChoice = 0; // remember the index of the last choice + for (int choice=0; choiceAppend (choices[choice], &integers[choice]); + // the client data is an int* that points to the choice number. + // This is what will be returned by GetAction(). + lastChoice++; + } + } + wxSize sizenow = action[evtype]->GetSize (); + action[evtype]->SetSizeHints (choiceWidth, sizenow.GetHeight ()); + action[evtype]->SetSelection (lastChoice-1); + } + + // buttonSizer contents + wxButton *btn; + btn = new wxButton (this, ID_Advanced, BTNLABEL_ADVANCED); + buttonSizer->Add (btn, 0, wxALL, 5); + btn = new wxButton (this, wxHELP, BTNLABEL_HELP); + buttonSizer->Add (btn, 0, wxALL, 5); + // use wxID_CANCEL because pressing ESC produces this same code + btn = new wxButton (this, wxID_CANCEL, BTNLABEL_CANCEL); + buttonSizer->Add (btn, 0, wxALL, 5); + btn = new wxButton (this, wxOK, BTNLABEL_OK); + buttonSizer->Add (btn, 0, wxALL, 5); +} + +void LogOptionsDialog::Init() +{ + // lay it out! + SetAutoLayout(TRUE); + SetSizer(vertSizer); + vertSizer->Fit (this); + wxSize size = vertSizer->GetMinSize (); + printf ("minsize is %d,%d\n", size.GetWidth(), size.GetHeight ()); + int margin = 5; + SetSizeHints (size.GetWidth () + margin, size.GetHeight () + margin); + Center (); +} + +void LogOptionsDialog::SetAction (int evtype, int a) { + // find the choice whose client data matches "a". + int i = 0; + int *ptr; + wxLogDebug ("SetAction type=%d a=%d", evtype, a); + while ((ptr = (int*) action[evtype]->GetClientData (i)) != NULL) { + if (a == *ptr) { // found it! + action[evtype]->SetSelection (i); + return; + } + i++; + } + // this can happen if one of the choices that is excluded by + // LOG_OPTS_EXCLUDE() is used, for example. + wxLogDebug ("SetAction type=%d a=%d not found", evtype, a); +} + +int LogOptionsDialog::GetAction (int evtype) { + int sel = action[evtype]->GetSelection (); + int *ptrToChoice = (int*)action[evtype]->GetClientData (sel); + return *ptrToChoice; +} + +void LogOptionsDialog::OnEvent(wxCommandEvent& event) +{ + int id = event.GetId (); + printf ("you pressed button id=%d\n", id); + switch (id) { + case ID_Advanced: + wxMessageBox ("The advanced dialog is not implemented yet."); + break; + case wxOK: + EndModal (wxOK); + break; + case wxID_CANCEL: + EndModal (wxCANCEL); + break; + case wxHELP: + ShowHelp(); + break; + default: + event.Skip (); + } +} + +void LogOptionsDialog::ShowHelp () +{ + wxMessageBox(MSG_NO_HELP, MSG_NO_HELP_CAPTION, wxOK | wxICON_ERROR ); +} + ///////////////////////////////////////////////////////////////// // utility ///////////////////////////////////////////////////////////////// diff --git a/bochs/gui/wxdialog.h b/bochs/gui/wxdialog.h index 50f5008b0..7be0af929 100644 --- a/bochs/gui/wxdialog.h +++ b/bochs/gui/wxdialog.h @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////// -// $Id: wxdialog.h,v 1.16 2002-09-01 21:24:14 bdenney Exp $ +// $Id: wxdialog.h,v 1.17 2002-09-02 17:03:11 bdenney Exp $ //////////////////////////////////////////////////////////////////// // // wxWindows dialogs for Bochs @@ -16,19 +16,23 @@ #define BTNLABEL_CANCEL "Cancel" #define BTNLABEL_OK "Ok" #define BTNLABEL_CREATE_IMG "Create Image" +#define BTNLABEL_ADVANCED "Advanced" //////////////////////////////////////////////////////////////////// // LogMsgAskDialog is a modal dialog box that shows the user a // simulation error message and asks if they want to continue or // not. It looks something like this: -// ------------------------------------------------------------- -// Context: Hard Drive -// Message: could not open hard drive image file '30M.sample' // -// [ ] Don't ask about future messages like this +// +----- PANIC ---------------------------------------------------+ +// | | +// | Context: Hard Drive | +// | Message: could not open hard drive image file '30M.sample' | +// | | +// | [ ] Don't ask about future messages like this | +// | | +// | [Continue] [Die] [Dump Core] [Debugger] [Help] | +// +---------------------------------------------------------------+ // -// [Continue] [Die] [Dump Core] [Debugger] [Help] -// ------------------------------------------------------------- // To use this dialog: // After constructor, use SetContext, SetMessage, EnableButton to // determine what will be displayed. Then call n = ShowModal(). The return @@ -386,6 +390,126 @@ public: DECLARE_EVENT_TABLE() }; +//////////////////////////////////////////////////////////////////////////// +// ConfigMemoryDialog +//////////////////////////////////////////////////////////////////////////// +// +// +--- Configure Memory ----------------------------------------------+ +// | | +// | +--- Standard Options ------------------------------------------+ | +// | | | | +// | | Memory size (megabytes): [_____] | | +// | | ROM BIOS image: [________________] [Browse] | | +// | | ROM BIOS address: [______] | | +// | | VGA BIOS image: [________________] [Browse] | | +// | | VGA BIOS address: 0xc0000 | | +// | | | | +// | +---------------------------------------------------------------+ | +// | | +// | +--- Optional ROM images ---------------------------------------+ | +// | | | | +// | | Optional ROM image #1: [________________] [Browse] | | +// | | address: [______] | | +// | | | | +// | | Optional ROM image #2: [________________] [Browse] | | +// | | address: [______] | | +// | | | | +// | | Optional ROM image #3: [________________] [Browse] | | +// | | address: [______] | | +// | | | | +// | | Optional ROM image #4: [________________] [Browse] | | +// | | address: [______] | | +// | | | | +// | +---------------------------------------------------------------+ | +// | [ Help ] [ Cancel ] [ Ok ] | +// +-------------------------------------------------------------------+ + +//////////////////////////////////////////////////////////////////////////// +// ConfigSoundDialog +//////////////////////////////////////////////////////////////////////////// +// +// +--- Configure Sound -------------------------------------------+ +// | | +// | Bochs can emulate a Sound Blaster 16. Would you like | +// | to enable it? | +// | | +// | Enable [X] | +// | | +// | DMA timer: [_________] | +// | | +// | Midi mode [ 1 ] Output file [_________________] [Browse] | +// | Wave mode [ 1 ] Output file [_________________] [Browse] | +// | Log mode [ 1 ] Output file [_________________] [Browse] | +// | | +// | [ Help ] [ Cancel ] [ Ok ] | +// +---------------------------------------------------------------+ + +//////////////////////////////////////////////////////////////////////////// +// LogOptionsDialog +//////////////////////////////////////////////////////////////////////////// +// LogOptionsDialog allows the user to decide how Bochs will +// behave for each type of log event. +// +// +---- Configure events -----------------------------------+ +// | | +// | How should Bochs respond to each type of event? | +// | | +// | Debug events: [ignore] | +// | Info events: [ignore] | +// | Error events: [report] | +// | Panic events: [ask ] | +// | | +// | For additional control over how each device responds | +// | to events, press the "Advanced" button. | +// | | +// | [ Advanced ] [ Help ] [ Cancel ] [ Ok ] | +// +---------------------------------------------------------+ +// To use this dialog: +// After constructor, call SetAction(eventtype, action) to set initial +// value for each choice field. The eventtype is 0 to LOG_OPTS_N_TYPES-1, +// representing the types listed in LOG_OPTS_NAMES. The choice field is 0 to +// LOG_OPTS_N_CHOICES-1, representing the actions listed in LOG_OPTS_CHOICES. +// Then call ShowModal(), which will return wxOK or wxCANCEL. Afterward, +// the GetAction(eventtype) method will tell what was selected in each +// choice box. +class LogOptionsDialog: public wxDialog +{ +private: +#define LOG_OPTS_TITLE "Configure Log Events" +#define LOG_OPTS_PROMPT "How should Bochs respond to each type of event?" +#define LOG_OPTS_NAMES { "Debug events: ", "Info events: ", "Error events: ", "Panic events: " } +#define LOG_OPTS_N_TYPES 4 +#define LOG_OPTS_CHOICES { "ignore", "report in log file", "ask user what to do", "end simulation", "no change" } +#define LOG_OPTS_N_CHOICES_NORMAL 4 +#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change" +#define LOG_OPTS_NO_CHANGE 5 // index of "no change" +// LOG_OPTS_CHOICES is the index of the longest string in LOG_OPTS_CHOICES +// array, used to determine dialog geometry +#define LOG_OPTS_LONGEST_CHOICE 2 +// normally all choices are available for all event types. The exclude +// expression allows some choices to be eliminated if they don't make any +// sense. For example, it would be stupid to ignore a panic. +#define LOG_OPTS_EXCLUDE(type,choice) ( \ + /* can't die or ask, on debug or info events */ \ + (type <= 1 && (choice==2 || choice==3)) \ + /* can't ignore panics or errors */ \ + || (type >= 2 && choice==0) \ + ) +#define LOG_OPTS_ADV "For additional control over how each device responds to events, press the \"Advanced\" button." + void Init (); // called automatically by ShowModal() + void ShowHelp (); + wxBoxSizer *vertSizer, *buttonSizer; + wxFlexGridSizer *gridSizer; + wxChoice *action[LOG_OPTS_N_TYPES]; +public: + LogOptionsDialog(wxWindow* parent, wxWindowID id); + void OnEvent (wxCommandEvent& event); + int ShowModal() { Init(); return wxDialog::ShowModal(); } + int GetAction (int evtype); + void SetAction (int evtype, int action); +DECLARE_EVENT_TABLE() +}; + /************************************************************************** Everything else in here is a comment! @@ -497,10 +621,10 @@ Or if you choose the CD-ROM, you get to edit the settings for it. | [Help] [Cancel] [Ok] | +---------------------------------------------------------------------------+ -The CD-ROM media can still be configured. In this context we can just show the -Media section. The same code can be written to serve both purposes. This is -the dialog that would appear when you click the CD-ROM button on the toolbar -at runtime. +The CD-ROM media can still be configured during the simulation. In this +context we can just show the Media section. The same code can be written to +serve both purposes. This is the dialog that would appear when you click the +CD-ROM button on the toolbar at runtime. +-- CD-ROM Media -----------------------------+ | | @@ -590,39 +714,6 @@ let you go right to the configure screen for that disk drive. | [ Help ] [ Cancel ] [ Ok ] | +---------------------------------------------------------------+ -//////////////////////////////////////////////////////////////////////////// -// ConfigMemoryDialog -//////////////////////////////////////////////////////////////////////////// - -This edits options related to RAM and ROM, similar to the text menu -1. Memory size in megabytes: 4 -2. Name of VGA BIOS image: -3. Name of ROM BIOS image: -4. ROM BIOS address: 0x00000 -5. Name of optional ROM image #1 : -6. optional ROM #1 address: 0x00000 -7. Name of optional ROM image #2 : -8. optional ROM #2 address: 0x00000 -9. Name of optional ROM image #3 : -10. optional ROM #3 address: 0x00000 -11. Name of optional ROM image #4 : -12. optional ROM #4 address: 0x00000 - -//////////////////////////////////////////////////////////////////////////// -// ConfigSoundDialog -//////////////////////////////////////////////////////////////////////////// - -This edits options related to sound blaster emulation, similar to the -text menu -1. SB16 is present: yes -2. Midi file: /dev/midi00 -3. Wave file: /dev/dsp -4. Log file: sb16.log -5. Midi mode: 1 -6. Wave mode: 1 -7. Log mode: 2 -8. DMA timer: 600000 - //////////////////////////////////////////////////////////////////////////// // ConfigKeyboardDialog //////////////////////////////////////////////////////////////////////////// @@ -667,21 +758,86 @@ sort of a grid with parameter name, and value(editable) in different columns lets you choose which events you want to write to the log, which you want to ignore, etc. You can do this at a high level, like -Event type Action -panic ask -error report -info ignore -debug ignore ++---- Configure events -----------------------------------+ +| | +| How should Bochs respond to each type of event? | +| | +| Debug events: [ignore] | +| Info events: [ignore] | +| Error events: [report] | +| Panic events: [ask ] | +| | +| For additional control over how each device responds | +| to events, press the "Advanced" button. | +| | +| [ Advanced ] [ Help ] [ Cancel ] [ Ok ] | ++---------------------------------------------------------+ +This sets up the default actions for all devices. The advanced +dialog lets you set different actions per device. I have two +attempts at the advanced dialog. The first creates a large +grid of wxChoice controls which choose between +ignore/report/ask/die. There will be enough rows in this +table that a scrolling subwindow will be needed to fit +all the devices. -Or when you want more control: ++---- Advanced event configuration -----------------------+ +| | +| This table determines how Bochs will respond to each | +| kind of event coming from a particular source. For | +| example if you are having problems with the keyboard, | +| you could ask for debug and info events from the | +| keyboard to be reported. | +| | +| [Apply defaults for all devices] | ++-------------------------------------------------------+-+ +| Device Debug Info Error Panic |^| +| -------- -------- ------- -------- --------- ||| +| Keyboard [ignore] [ignore] [report] [report] ||| +| VGA [ignore] [ignore] [report] [report] ||| +| NE2000 [ignore] [ignore] [report] [report] ||| +| Sound [ignore] [ignore] [report] [report] |v| ++---------------------------------------------------------+ +| [ Help ] [ Cancel ] [ Ok ] | ++-------------------------------------------------------+-+ - panic error info debug - ----- ------ ----- ----- -keyboard ask report report report -vga ask report report report -network ask report report ignore -cpu ask report report ignore -sound ask report report ignore +Try #2 for the advanced event configuration dialog. +It shows the selection of the default actions again +at the top, with some explanation. Then at bottom, you +can select a device in the list box and edit the settings +for that device individually. It would be possible to +allow selection of multiple devices and then edit several +devices at once. + ++---- Advanced event configuration ---------------------+-+ +| | +| +--- Default Actions -------------+ | +| First choose the | | | +| default actions | Debug events: [ignore] | | +| that apply to all | Info events: [ignore] | | +| event sources. | Error events: [report] | | +| | Panic events: [ask ] | | +| | | | +| | [Copy to All Devices] | | +| +---------------------------------+ | +| | +| Then, if you want you can edit the actions for | +| individual devices. For example if you are having | +| problems with the keyboard, you could ask for debug | +| and info events from the keyboard to be reported. | +| | +| Select Device: | +| +-------------+-+ +--- Actions for VGA -------------+ | +| | CPU |^| | | | +| | Interrupts ||| | Debug events: [ignore] | | +| |*VGA*********||| | Info events: [ignore] | | +| | Keyboard ||| | Error events: [report] | | +| | Mouse ||| | Panic events: [ask ] | | +| | Floppy Disk |v| | | | +| +-------------+-+ +---------------------------------+ | +| | +| [ Help ] [ Cancel ] [ Ok ] | ++---------------------------------------------------------+ + //////////////////////////////////////////////////////////////////////////// // CpuRegistersDialog diff --git a/bochs/gui/wxmain.cc b/bochs/gui/wxmain.cc index 2bed1441d..10396c775 100644 --- a/bochs/gui/wxmain.cc +++ b/bochs/gui/wxmain.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////// -// $Id: wxmain.cc,v 1.22 2002-09-01 21:24:14 bdenney Exp $ +// $Id: wxmain.cc,v 1.23 2002-09-02 17:03:13 bdenney Exp $ ///////////////////////////////////////////////////////////////// // // wxmain.cc implements the wxWindows frame, toolbar, menus, and dialogs. @@ -149,6 +149,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(ID_Edit_Cdrom, MyFrame::OnOtherEvent) EVT_MENU(ID_Edit_Boot, MyFrame::OnEditBoot) EVT_MENU(ID_Edit_Network, MyFrame::OnEditNet) + EVT_MENU(ID_Log_Prefs, MyFrame::OnLogPrefs) // toolbar events EVT_TOOL(ID_Edit_FD_0, MyFrame::OnToolbarClick) EVT_TOOL(ID_Edit_FD_1, MyFrame::OnToolbarClick) @@ -427,6 +428,54 @@ void MyFrame::OnEditNet(wxCommandEvent& WXUNUSED(event)) } } +void MyFrame::OnLogPrefs(wxCommandEvent& WXUNUSED(event)) +{ + // Ideally I would use the siminterface methods to fill in the fields + // of the LogOptionsDialog, but in fact several things are hardcoded. + // At least I can verify that the expected numbers are the same. + wxASSERT (SIM->get_max_log_level() == LOG_OPTS_N_TYPES); + LogOptionsDialog dlg (this, -1); + + // The inital values of the dialog are complicated. If the panic action + // for all modules is "ask", then clearly the inital value in the dialog + // for panic action should be "ask". This informs the user what the + // previous value was, and if they click Ok it won't do any harm. But if + // some devices are set to "ask" and others are set to "report", then the + // initial value should be "no change". With "no change", clicking on Ok + // will not destroy the settings for individual devices. You would only + // start to see "no change" if you've been messing around in the advanced + // menu already. + for (int level=0; levelget_max_log_level(); level++) { + int mod = 0; + int first = SIM->get_log_action (mod, level); + bool consensus = true; + // now compare all others to first. If all match, then use "first" as + // the initial value. + for (mod=1; modget_n_log_modules (); mod++) { + if (first != SIM->get_log_action (mod, level)) { + consensus = false; + break; + } + } + if (consensus) + dlg.SetAction (level, first); + else + dlg.SetAction (level, LOG_OPTS_NO_CHANGE); + } + int n = dlg.ShowModal (); // show the dialog! + if (n == wxOK) { + for (int level=0; level < SIM->get_max_log_level (); level++) { + // ask the dialog what action the user chose for this type of event + int action = dlg.GetAction (level); + if (action != LOG_OPTS_NO_CHANGE) { + // apply that action to all modules (devices) + for (int i=0; iget_n_log_modules (); i++) + SIM->set_log_action (i, level, action); + } + } + } +} + void MyFrame::OnQuit(wxCommandEvent& event) { Close( TRUE ); diff --git a/bochs/gui/wxmain.h b/bochs/gui/wxmain.h index bf8c013be..6e8478f9f 100644 --- a/bochs/gui/wxmain.h +++ b/bochs/gui/wxmain.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////// -// $Id: wxmain.h,v 1.14 2002-09-01 19:38:08 bdenney Exp $ +// $Id: wxmain.h,v 1.15 2002-09-02 17:03:14 bdenney Exp $ ///////////////////////////////////////////////////////////////// // This file defines variables and classes that the wxWindows .cc files // share. It should be included only by wx.cc and wxmain.cc. @@ -81,6 +81,8 @@ enum ID_SPT, ID_Megs, ID_ComputeGeometry, + // dialog box: LogOptions + ID_Advanced }; @@ -132,6 +134,7 @@ public: void OnSim2CIEvent(wxCommandEvent& event); void OnEditBoot(wxCommandEvent& event); void OnEditNet(wxCommandEvent& event); + void OnLogPrefs(wxCommandEvent& event); void OnOtherEvent(wxCommandEvent& event); static bool editFloppyValidate (FloppyConfigDialog *dialog); void editFloppyConfig (int drive);