1 /////////////////////////////////////////////////////////////////
2 // $Id: wxdialog.cc,v 1.105 2008/02/15 22:05:40 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////
5 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
6 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
7 // is used to know when we are exporting symbols and when we are importing.
10 #include "config.h" // definitions based on configure script
13 // For compilers that support precompilation, includes <wx/wx.h>.
14 #include <wx/wxprec.h>
21 #include <wx/spinctrl.h>
22 #include <wx/config.h>
23 #include <wx/confbase.h>
24 #include <wx/notebook.h>
26 #include "osdep.h" // workarounds for missing stuff
27 #include "gui/siminterface.h" // interface to the simulator
28 #include "bxversion.h" // get version string
29 #include "wxdialog.h" // custom dialog boxes
30 #include "wxmain.h" // wxwidgets shared stuff
32 //////////////////////////////////////////////////////////////////////
33 // constants, prototypes
34 //////////////////////////////////////////////////////////////////////
45 wxSize
longTextSize (300, -1); // width=300, height=default
46 wxSize
normalTextSize (180, -1); // width=200, height=default
48 //////////////////////////////////////////////////////////////////////
49 // LogMsgAskDialog implementation
50 //////////////////////////////////////////////////////////////////////
53 // context text field,
64 // all events go to OnEvent method
65 BEGIN_EVENT_TABLE(LogMsgAskDialog
, wxDialog
)
66 EVT_BUTTON(ID_Continue
, LogMsgAskDialog::OnEvent
)
67 EVT_BUTTON(ID_Die
, LogMsgAskDialog::OnEvent
)
68 EVT_BUTTON(ID_DumpCore
, LogMsgAskDialog::OnEvent
)
69 EVT_BUTTON(ID_Debugger
, LogMsgAskDialog::OnEvent
)
70 EVT_BUTTON(wxID_HELP
, LogMsgAskDialog::OnEvent
)
74 LogMsgAskDialog::LogMsgAskDialog(
77 const wxString
& title
)
78 : wxDialog (parent
, id
, title
, wxDefaultPosition
, wxDefaultSize
,
79 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
81 for (int i
=0; i
<N_BUTTONS
; i
++) enabled
[i
] = TRUE
;
82 vertSizer
= new wxBoxSizer(wxVERTICAL
);
83 context
= new wxStaticText (this, -1, wxT(""));
84 wxFont font
= context
->GetFont ();
85 font
.SetWeight (wxBOLD
);
86 font
.SetPointSize (2 + font
.GetPointSize ());
87 context
->SetFont (font
);
88 message
= new wxStaticText (this, -1, wxT(""));
89 message
->SetFont (font
);
90 dontAsk
= new wxCheckBox (this, -1, LOG_MSG_DONT_ASK_STRING
);
91 btnSizer
= new wxBoxSizer(wxHORIZONTAL
);
92 // fill vertical sizer
93 vertSizer
->Add (context
, 0, wxGROW
|wxALIGN_LEFT
|wxLEFT
|wxTOP
, 30);
94 vertSizer
->Add (message
, 0, wxGROW
|wxALIGN_LEFT
|wxLEFT
, 30);
95 vertSizer
->Add (dontAsk
, 0, wxALIGN_CENTER
|wxTOP
, 30);
96 vertSizer
->Add (btnSizer
, 0, wxALIGN_CENTER
|wxTOP
, 30);
97 // Some object creation and layout is postponed until Init()
98 // so that caller has time to configure the dialog.
101 void LogMsgAskDialog::SetContext(wxString s
)
103 ChangeStaticText(vertSizer
, context
, wxString(LOG_MSG_CONTEXT
) + s
);
106 void LogMsgAskDialog::SetMessage(wxString s
)
108 ChangeStaticText(vertSizer
, message
, wxString(LOG_MSG_MSG
) + s
);
111 void LogMsgAskDialog::Init()
113 static const int ids
[N_BUTTONS
] = LOG_MSG_ASK_IDS
;
114 static const wxString names
[N_BUTTONS
] = LOG_MSG_ASK_NAMES
;
115 for (int i
=0; i
<N_BUTTONS
; i
++) {
116 if (!enabled
[i
]) continue;
117 wxButton
*btn
= new wxButton(this, ids
[i
], names
[i
]);
118 btnSizer
->Add(btn
, 1, wxALL
, 5);
120 wxSize ms
= message
->GetSize();
123 vertSizer
->Fit(this);
124 wxSize size
= vertSizer
->GetMinSize();
126 SetSizeHints (size
.GetWidth () + margin
, size
.GetHeight () + margin
);
130 // Event handler for dialog buttons. Just translate the wx ids into
131 // enum values and return them with EndModal() to make the dialog
133 void LogMsgAskDialog::OnEvent(wxCommandEvent
& event
)
135 int id
= event
.GetId();
138 case ID_Continue
: ret
= BX_LOG_ASK_CHOICE_CONTINUE
; break;
139 case ID_Die
: ret
= BX_LOG_ASK_CHOICE_DIE
; break;
140 case ID_DumpCore
: ret
= BX_LOG_ASK_CHOICE_DUMP_CORE
; break;
141 case ID_Debugger
: ret
= BX_LOG_ASK_CHOICE_ENTER_DEBUG
; break;
142 case wxID_HELP
: ShowHelp(); return;
144 return; // without EndModal
149 void LogMsgAskDialog::ShowHelp()
151 wxMessageBox(MSG_NO_HELP
, MSG_NO_HELP_CAPTION
, wxOK
| wxICON_ERROR
, this);
154 //////////////////////////////////////////////////////////////////////
155 // FloppyConfigDialog implementation
156 //////////////////////////////////////////////////////////////////////
160 // radioSizer (vert):
163 // diskImageSizer (horiz):
168 // capacitySizer (horizontal):
170 // capacity choice box
178 // all events go to OnEvent method
179 BEGIN_EVENT_TABLE(FloppyConfigDialog
, wxDialog
)
180 EVT_BUTTON(-1, FloppyConfigDialog::OnEvent
)
181 EVT_TEXT(-1, FloppyConfigDialog::OnEvent
)
182 EVT_CHOICE(-1, FloppyConfigDialog::OnEvent
)
186 FloppyConfigDialog::FloppyConfigDialog(
189 : wxDialog (parent
, id
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
190 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
195 vertSizer
= new wxBoxSizer (wxVERTICAL
);
196 instr
= new wxStaticText (this, -1, FLOPPY_CONFIG_INSTRS
);
197 radioSizer
= new wxBoxSizer (wxVERTICAL
);
198 diskImageSizer
= new wxBoxSizer (wxHORIZONTAL
);
199 capacitySizer
= new wxBoxSizer (wxHORIZONTAL
);
200 wxStaticText
*hint
= new wxStaticText (this, -1, FLOPPY_CONFIG_HINT
);
201 buttonSizer
= new wxBoxSizer (wxHORIZONTAL
);
202 // add top level components to vertSizer
203 vertSizer
->Add (instr
, 0, wxTOP
|wxLEFT
, 30);
204 vertSizer
->Add (radioSizer
, 0, wxLEFT
, 50);
205 vertSizer
->Add (capacitySizer
, 0, wxTOP
|wxLEFT
, 30);
206 vertSizer
->Add (hint
, 0, wxTOP
|wxLEFT
, 30);
207 vertSizer
->Add (buttonSizer
, 0, wxALIGN_RIGHT
|wxTOP
, 30);
208 // contents of capacitySizer
209 wxStaticText
*captext
= new wxStaticText(this, -1, FLOPPY_CONFIG_CAP
);
210 capacity
= new wxChoice(this, ID_Capacity
);
211 capacitySizer
->Add(captext
, 0, wxALL
, 5);
212 capacitySizer
->Add(capacity
, 0, wxALL
|wxADJUST_MINSIZE
, 5);
213 // contents of buttonSizer
214 btn
= new wxButton(this, wxID_HELP
, wxT("Help"));
215 buttonSizer
->Add(btn
, 0, wxALL
, 5);
216 // use wxID_CANCEL because pressing ESC produces this same code
217 btn
= new wxButton(this, wxID_CANCEL
, wxT("Cancel"));
218 buttonSizer
->Add(btn
, 0, wxALL
, 5);
219 CreateBtn
= new wxButton(this, ID_Create
, wxT("Create Image"));
220 buttonSizer
->Add(CreateBtn
, 0, wxALL
, 5);
221 btn
= new wxButton(this, wxID_OK
, wxT("Ok"));
222 buttonSizer
->Add(btn
, 0, wxALL
, 5);
223 // create filename and diskImageRadioBtn so that we can tweak them before
224 // Init comes. However don't add it to any sizer yet because it needs to go
225 // in after the last radio button.
226 filename
= new wxTextCtrl (this, ID_FilenameText
, wxT(""), wxDefaultPosition
, longTextSize
);
227 diskImageRadioBtn
= new wxRadioButton (this, ID_Filename
, FLOPPY_CONFIG_DISKIMG
);
229 // the radioSizer contents will be added by successive calls to
230 // AddRadio(). The diskImageSizer will be added last, in Init().
233 void FloppyConfigDialog::AddRadio (
234 const wxString
& description
,
235 const wxString
& filename
)
237 if (n_rbtns
>= FLOPPY_MAX_RBTNS
) {
238 wxLogError(wxT("AddRadio failed: increase FLOPPY_MAX_RBTNS in wxdialog.h"));
241 rbtn
[n_rbtns
] = new wxRadioButton(this, -1, description
);
242 equivalentFilename
[n_rbtns
] = filename
;
243 radioSizer
->Add(rbtn
[n_rbtns
]);
247 void FloppyConfigDialog::SetDriveName(wxString name
)
249 SetTitle(wxString(FLOPPY_CONFIG_TITLE
) + name
);
250 ChangeStaticText(vertSizer
, instr
, wxString(FLOPPY_CONFIG_INSTRS
) + name
+
254 void FloppyConfigDialog::SetCapacityChoices(const char *choices
[])
257 while (choices
[i
] != NULL
) {
258 capacity
->Append(wxString(choices
[i
], wxConvUTF8
));
263 void FloppyConfigDialog::SetCapacity(int cap
)
265 capacity
->SetSelection(cap
);
266 CreateBtn
->Enable(floppy_type_n_sectors
[cap
] > 0);
269 void FloppyConfigDialog::Init()
271 // add contents of diskImageSizer
272 diskImageSizer
->Add(diskImageRadioBtn
);
273 diskImageSizer
->Add(filename
, 1, wxGROW
);
274 wxButton
*btn
= new wxButton (this, ID_Browse
, BTNLABEL_BROWSE
);
275 diskImageSizer
->Add(btn
, 0, wxALL
, 5);
276 radioSizer
->Add(diskImageSizer
);
280 vertSizer
->Fit(this);
281 wxSize size
= vertSizer
->GetMinSize();
283 SetSizeHints (size
.GetWidth() + margin
, size
.GetHeight() + margin
);
288 FloppyConfigDialog::GetRadio () {
290 for (i
=0; i
<n_rbtns
; i
++) {
291 if (rbtn
[i
]->GetValue())
294 if (diskImageRadioBtn
->GetValue()) {
297 wxLogError(wxT("GetRadio() found nothing selected"));
302 FloppyConfigDialog::SetRadio (int n
) {
304 rbtn
[n
]->SetValue (TRUE
);
306 diskImageRadioBtn
->SetValue (TRUE
);
310 void FloppyConfigDialog::SetFilename (wxString f
) {
311 // search equivalentFilename[] for matches. if it matches, select the
312 // radio button instead.
313 for (int i
=0; i
<n_rbtns
; i
++) {
314 if (!f
.Cmp(equivalentFilename
[i
])) {
315 rbtn
[i
]->SetValue(TRUE
);
316 return; // leaving filename text field unchanged
319 filename
->SetValue(f
);
320 diskImageRadioBtn
->SetValue(TRUE
);
324 FloppyConfigDialog::GetFilename()
328 return equivalentFilename
[n
];
330 return filename
->GetValue();
334 void FloppyConfigDialog::OnEvent(wxCommandEvent
& event
)
336 int id
= event
.GetId ();
338 case ID_FilenameText
:
339 // when you type into the filename field, ensure that the radio
340 // button associated with that field is chosen.
341 diskImageRadioBtn
->SetValue (TRUE
);
344 // probably should validate before allowing ok
345 if (validate
!=NULL
&& !(*validate
)(this))
346 return; // validation failed, don't leave yet
350 if (BrowseTextCtrl(filename
)) {
351 capacity
->SetSelection(capacity
->FindString(wxT("auto")));
356 int cap
= capacity
->GetSelection();
357 CreateBtn
->Enable(floppy_type_n_sectors
[cap
] > 0);
362 int cap
= capacity
->GetSelection();
364 strncpy(name
, filename
->GetValue().mb_str(wxConvUTF8
), sizeof(name
));
365 if (CreateImage (0, floppy_type_n_sectors
[cap
], name
)) {
366 wxString
msg(wxT("Created a "));
367 msg
+= capacity
->GetString(cap
);
368 msg
+= wxT(" disk image called '");
369 msg
+= filename
->GetValue();
371 wxMessageBox(msg
, wxT("Image Created"), wxOK
| wxICON_INFORMATION
, this);
376 EndModal(wxID_CANCEL
);
384 void FloppyConfigDialog::ShowHelp()
386 wxMessageBox(MSG_NO_HELP
, MSG_NO_HELP_CAPTION
, wxOK
| wxICON_ERROR
, this);
389 //////////////////////////////////////////////////////////////////////
390 // AdvancedLogOptionsDialog implementation
391 //////////////////////////////////////////////////////////////////////
398 // prompt (multiline)
399 // applyDefault button
402 // gridSizer 5 columns
414 // all events go to OnEvent method
415 BEGIN_EVENT_TABLE(AdvancedLogOptionsDialog
, wxDialog
)
416 EVT_BUTTON(-1, AdvancedLogOptionsDialog::OnEvent
)
417 EVT_CHECKBOX(-1, AdvancedLogOptionsDialog::OnEvent
)
418 EVT_TEXT(-1, AdvancedLogOptionsDialog::OnEvent
)
421 AdvancedLogOptionsDialog::AdvancedLogOptionsDialog(
424 : wxDialog(parent
, id
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
425 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
427 //static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3};
428 static wxString names
[] = ADVLOG_OPTS_TYPE_NAMES
;
429 SetTitle(ADVLOG_OPTS_TITLE
);
430 vertSizer
= new wxBoxSizer(wxVERTICAL
);
432 logfileSizer
= new wxBoxSizer(wxHORIZONTAL
);
433 vertSizer
->Add(logfileSizer
, 0, wxTOP
|wxLEFT
, 20);
434 wxStaticText
*text
= new wxStaticText(this, -1, ADVLOG_OPTS_PROMPT
);
435 vertSizer
->Add(text
, 0, wxALL
, 10);
436 applyDefault
= new wxButton(this, ID_ApplyDefault
, ADVLOG_DEFAULTS
);
437 vertSizer
->Add(applyDefault
, 0, wxALL
|wxALIGN_RIGHT
, 10);
438 headerSizer
= new wxGridSizer(ADVLOG_OPTS_N_TYPES
+ 1);
439 vertSizer
->Add(headerSizer
, 0, wxALL
|wxGROW
, 10);
440 scrollWin
= new wxScrolledWindow(this, -1);
441 vertSizer
->Add(scrollWin
, 1, wxALL
|wxGROW
, 10);
442 buttonSizer
= new wxBoxSizer(wxHORIZONTAL
);
443 vertSizer
->Add(buttonSizer
, 0, wxALIGN_RIGHT
);
445 // logfileSizer contents
446 text
= new wxStaticText(this, -1, ADVLOG_OPTS_LOGFILE
);
447 logfileSizer
->Add(text
);
448 logfile
= new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition
, longTextSize
);
449 logfileSizer
->Add(logfile
);
450 wxButton
*btn
= new wxButton(this, ID_Browse
, BTNLABEL_BROWSE
);
451 logfileSizer
->Add(btn
, 0, wxALL
, 5);
453 // to get the scrollWin geometry right, first build everything on a wxPanel,
454 // with gridSizer as the main sizer.
455 scrollPanel
= new wxPanel(scrollWin
, -1);
456 gridSizer
= new wxGridSizer(ADVLOG_OPTS_N_TYPES
+ 1);
458 int typemax
= ADVLOG_OPTS_N_TYPES
;
459 text
= new wxStaticText(this, -1, wxT("Device"));
460 headerSizer
->Add(text
, 0, wxALIGN_LEFT
);
462 for (type
=0; type
< typemax
; type
++) {
463 text
= new wxStaticText(this, -1, names
[type
]);
464 headerSizer
->Add(text
, 0, wxALIGN_LEFT
);
466 // add rows of choice boxes, one for each device
467 int devmax
= SIM
->get_n_log_modules();
468 action
= new wxChoice
** [devmax
]; // array of pointers
469 for (int dev
=0; dev
<devmax
; dev
++) {
470 if (strcmp(SIM
->get_prefix(dev
), "[ ]")) {
471 action
[dev
] = new wxChoice
* [ADVLOG_OPTS_N_TYPES
];
472 // name of device in first column
473 gridSizer
->Add(new wxStaticText(scrollPanel
, -1, wxString(SIM
->get_prefix(dev
), wxConvUTF8
)));
474 // wxChoice in every other column
475 for (type
=0; type
< typemax
; type
++) {
476 action
[dev
][type
] = makeLogOptionChoiceBox(scrollPanel
, -1, type
);
477 gridSizer
->Add(action
[dev
][type
], 1, wxALL
|wxGROW
|wxADJUST_MINSIZE
, 2);
483 headerSizer
->Fit(this);
484 headerSizer
->SetSizeHints(this);
485 scrollPanel
->SetAutoLayout(TRUE
);
486 scrollPanel
->SetSizer(gridSizer
);
487 gridSizer
->Fit(scrollPanel
);
488 gridSizer
->SetSizeHints(scrollPanel
);
489 wxSize size
= scrollPanel
->GetBestSize();
490 // now we know how big the panel wants to be, and we can set the scrollbar
491 // and scrollWin size accordingly
493 // finally set up the scroll window outside
494 scrollWin
->SetScrollbars(1, 1, size
.GetWidth(), size
.GetHeight());
496 // now that we know the desired width of the panel, use it to set the
497 // width of the scrollWin. I tried several things before arriving at
498 // a solution, and I'll list them for educational purposes.
500 // failure #1: this had no effect at all. sizer took precedence.
501 // scrollWin->SetSize(500, 500);
502 // failure #2: this changed scrollWin size but sizer was not notified so
503 // the overall window didn't expand to make space for it.
504 // scrollWin->SetSizeHints(500, 500);
505 // success: tell the sizer to change the scrollWin's size, and it works
506 vertSizer
->SetItemMinSize(scrollWin
, size
.GetWidth()+30, 400);
508 // buttonSizer contents
509 btn
= new wxButton(this, wxID_HELP
, BTNLABEL_HELP
);
510 buttonSizer
->Add(btn
, 0, wxALL
, 5);
511 // use wxID_CANCEL because pressing ESC produces this same code
512 btn
= new wxButton(this, wxID_CANCEL
, BTNLABEL_CANCEL
);
513 buttonSizer
->Add(btn
, 0, wxALL
, 5);
514 btn
= new wxButton(this, wxID_OK
, BTNLABEL_OK
);
515 buttonSizer
->Add(btn
, 0, wxALL
, 5);
518 AdvancedLogOptionsDialog::~AdvancedLogOptionsDialog()
520 int dev
, ndev
= SIM
->get_n_log_modules();
521 for (dev
=0; dev
<ndev
; dev
++) {
522 delete [] action
[dev
];
527 void AdvancedLogOptionsDialog::Init()
533 vertSizer
->Fit(this);
534 wxSize size
= vertSizer
->GetMinSize();
536 SetSizeHints(size
.GetWidth() + margin
, size
.GetHeight() + margin
);
540 void AdvancedLogOptionsDialog::CopyParamToGui() {
541 bx_param_string_c
*logfile
= SIM
->get_param_string(BXPN_LOG_FILENAME
);
542 SetLogfile(wxString(logfile
->getptr(), wxConvUTF8
));
543 // copy log action settings from siminterface to gui
544 int dev
, ndev
= SIM
->get_n_log_modules();
545 int type
, ntype
= SIM
->get_max_log_level();
546 for (dev
=0; dev
<ndev
; dev
++) {
547 for (type
=0; type
<ntype
; type
++) {
548 SetAction(dev
, type
, SIM
->get_log_action(dev
, type
));
553 void AdvancedLogOptionsDialog::CopyGuiToParam() {
555 safeWxStrcpy(buf
, GetLogfile(), sizeof(buf
));
556 bx_param_string_c
*logfile
= SIM
->get_param_string(BXPN_LOG_FILENAME
);
558 // copy log action settings from gui to siminterface
559 int dev
, ndev
= SIM
->get_n_log_modules();
560 int type
, ntype
= SIM
->get_max_log_level();
561 for (dev
=0; dev
<ndev
; dev
++) {
562 for (type
=0; type
<ntype
; type
++) {
563 SIM
->set_log_action(dev
, type
, GetAction(dev
, type
));
568 void AdvancedLogOptionsDialog::SetAction(int dev
, int evtype
, int act
) {
569 if (action
[dev
] == NULL
) return;
570 // find the choice whose client data matches "act".
572 // wxLogDebug(wxT("SetAction dev=%d type=%d act=%d"), dev, evtype, act);
573 wxChoice
*control
= action
[dev
][evtype
];
574 for (int i
=0; i
< control
->GetCount(); i
++) {
575 // wxLogDebug(wxT("reading action[%d][%d]->GetClientData(%d)"), dev, evtype, i);
576 ptr
= (int*) control
->GetClientData(i
);
577 if (ptr
== NULL
) continue;
578 if (act
== *ptr
) { // found it!
579 control
->SetSelection(i
);
583 // this can happen if one of the choices that is excluded by
584 // ADVLOG_OPTS_EXCLUDE() is used, for example.
585 wxLogDebug(wxT("warning: SetAction type=%d act=%d not found"), evtype
, act
);
588 int AdvancedLogOptionsDialog::GetAction(int dev
, int evtype
) {
589 if (action
[dev
] == NULL
) return LOG_OPTS_NO_CHANGE
;
590 int sel
= action
[dev
][evtype
]->GetSelection();
591 int *ptrToChoice
= (int*)action
[dev
][evtype
]->GetClientData(sel
);
592 wxASSERT(ptrToChoice
!= NULL
);
596 void AdvancedLogOptionsDialog::OnEvent(wxCommandEvent
& event
)
598 int id
= event
.GetId();
601 BrowseTextCtrl(logfile
);
603 case ID_ApplyDefault
: {
604 int lev
, nlev
= SIM
->get_max_log_level();
605 // copy default settings to every device
606 for (lev
=0; lev
<nlev
; lev
++) {
607 int action
= SIM
->get_default_log_action(lev
);
608 int dev
, ndev
= SIM
->get_n_log_modules();
609 for (dev
=0; dev
<ndev
; dev
++)
610 SetAction(dev
, lev
, action
);
619 EndModal(wxID_CANCEL
);
629 void AdvancedLogOptionsDialog::ShowHelp()
631 wxMessageBox(MSG_NO_HELP
, MSG_NO_HELP_CAPTION
, wxOK
| wxICON_ERROR
, this);
635 //////////////////////////////////////////////////////////////////////
636 // DebugLogDialog implementation
637 //////////////////////////////////////////////////////////////////////
640 // wxTextCtrl log (multiline with vert scrollbar)
641 // "Type a debugger command"
643 // wxTextCtrl command
651 // all events go to OnEvent method
652 BEGIN_EVENT_TABLE(DebugLogDialog
, wxDialog
)
653 EVT_BUTTON(-1, DebugLogDialog::OnEvent
)
654 EVT_CHECKBOX(-1, DebugLogDialog::OnEvent
)
655 EVT_KEY_DOWN(DebugLogDialog::OnKeyEvent
)
656 EVT_KEY_UP(DebugLogDialog::OnKeyEvent
)
657 EVT_CHAR(DebugLogDialog::OnKeyEvent
)
658 EVT_TEXT(-1, DebugLogDialog::OnEvent
)
659 EVT_TEXT_ENTER(-1, DebugLogDialog::OnEnterEvent
)
663 DebugLogDialog::DebugLogDialog(
666 : wxDialog (parent
, id
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
667 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
669 lengthMax
= DEBUG_LOG_DEFAULT_LENGTH_MAX
;
670 lengthTolerance
= DEBUG_LOG_DEFAULT_TOLERANCE
;
671 SetTitle (DEBUG_LOG_TITLE
);
672 mainSizer
= new wxBoxSizer (wxVERTICAL
);
673 log
= new wxTextCtrl (this, -1, wxT(""),
674 wxDefaultPosition
, wxSize(400, 300),
675 wxTE_MULTILINE
| wxTE_RICH
| wxTE_READONLY
);
676 mainSizer
->Add (log
, 1, wxALL
|wxGROW
, 10);
677 wxStaticText
*text
= new wxStaticText (this, -1, DEBUG_CMD_PROMPT
);
678 mainSizer
->Add (text
, 0, wxTOP
|wxLEFT
, 10);
679 commandSizer
= new wxBoxSizer (wxHORIZONTAL
);
680 mainSizer
->Add (commandSizer
, 0, wxALL
|wxGROW
, 5);
681 buttonSizer
= new wxBoxSizer (wxHORIZONTAL
);
682 mainSizer
->Add (buttonSizer
, 0, wxALIGN_RIGHT
);
684 // commandSizer contents
685 command
= new wxTextCtrl (this, ID_DebugCommand
, wxT(""),
686 wxDefaultPosition
, wxDefaultSize
,
688 commandSizer
->Add (command
, 1, wxGROW
);
690 btn
= new wxButton (this, ID_Execute
, BTNLABEL_EXECUTE
);
691 commandSizer
->Add (btn
, 0, wxALL
, 5);
693 // buttonSizer contents
694 btn
= new wxButton (this, wxID_OK
, BTNLABEL_CLOSE
);
695 buttonSizer
->Add (btn
, 0, wxALL
, 5);
698 void DebugLogDialog::Init()
703 mainSizer
->Fit(this);
704 wxSize size
= mainSizer
->GetMinSize();
706 SetSizeHints(size
.GetWidth() + margin
, size
.GetHeight() + margin
);
710 void DebugLogDialog::Execute(bool clear
)
713 theFrame
->DebugCommand (command
->GetValue ());
714 // display what they typed on the log screen
715 if (clear
) command
->Clear ();
718 void DebugLogDialog::CheckLogLength ()
720 // truncate the text control periodically to avoid a
721 // serious memory leak.
722 wxString str
= log
->GetValue ();
723 Bit32u len
= str
.Length ();
724 if (len
> lengthMax
+ lengthTolerance
) {
725 // Truncate the string. Start from length - lengthMax, search
726 // forward until we find the first \n.
727 for (int i
= len
- lengthMax
; i
<(int)(len
-1); i
++) {
728 if (str
.GetChar (i
) == '\n') {
729 // remove the \n and everything before it. Done.
730 //printf ("truncating from 0 to %d\n", i+1);
732 log
->Remove (0, i
+1);
736 // no newline found?!
737 //printf ("no newline found! truncating from 0 to %d", len - lengthMax);
739 log
->Remove (0, len
- lengthMax
);
741 //printf ("log length is %d, no truncation yet", len);
746 void DebugLogDialog::AppendCommand (const char *cmd
)
748 log
->AppendText(wxT(">>> "));
749 log
->AppendText(wxString(cmd
, wxConvUTF8
));
750 log
->AppendText(wxT("\n"));
751 int n
= log
->GetLastPosition();
753 log
->ShowPosition(n
);
757 void DebugLogDialog::AppendText (wxString text
) {
758 log
->AppendText (text
);
759 int n
= log
->GetLastPosition ();
761 log
->ShowPosition (n
);
765 void DebugLogDialog::OnEvent(wxCommandEvent
& event
)
767 int id
= event
.GetId();
772 case ID_Execute
: // pressed execute button
780 void DebugLogDialog::OnKeyEvent(wxKeyEvent
& event
)
782 wxLogDebug(wxT("key event"));
786 /////////////////////////////////////////////////////////////////
788 /////////////////////////////////////////////////////////////////
790 // all events go to OnEvent method
791 BEGIN_EVENT_TABLE(ParamDialog
, wxDialog
)
792 EVT_BUTTON(-1, ParamDialog::OnEvent
)
793 EVT_CHECKBOX(-1, ParamDialog::OnEvent
)
794 EVT_CHOICE(-1, ParamDialog::OnEvent
)
795 EVT_TEXT(-1, ParamDialog::OnEvent
)
798 ParamDialog::ParamDialog(
801 : wxDialog (parent
, id
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
802 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
804 idHash
= new wxHashTable (wxKEY_INTEGER
);
805 paramHash
= new wxHashTable (wxKEY_INTEGER
);
810 mainSizer
= new wxBoxSizer (wxVERTICAL
);
812 // create buttonSizer, which will hold all the buttons.
813 buttonSizer
= new wxBoxSizer (wxHORIZONTAL
);
816 ParamDialog::~ParamDialog()
818 paramHash
->BeginFind();
820 while ((node
= paramHash
->Next()) != NULL
) {
821 // assume that no ParamStruct appears in the hash table under multiple
822 // keys. If so, we will delete it twice and corrupt memory.
823 ParamStruct
*pstr
= (ParamStruct
*) node
->GetData();
824 // wxLogDebug(wxT("deleting ParamStruct id=%d for param %s"), pstr->id, pstr->param->get_name());
832 ParamDialog::AddButton (int id
, wxString label
)
834 wxButton
*btn
= new wxButton (this, id
, label
);
835 buttonSizer
->Add (btn
, 0, wxALL
, 5);
840 // add the standard HELP, CANCEL, OK buttons.
841 void ParamDialog::AddDefaultButtons ()
843 AddButton (wxID_HELP
, BTNLABEL_HELP
);
844 AddButton (wxID_CANCEL
, BTNLABEL_CANCEL
);
845 AddButton (wxID_OK
, BTNLABEL_OK
);
848 void ParamDialog::Init()
850 // if nobody has made any buttons, then create some now
851 if (nbuttons
==0) AddDefaultButtons();
852 mainSizer
->Add(buttonSizer
, 0, wxALIGN_RIGHT
);
857 mainSizer
->Fit(this);
858 wxSize size
= mainSizer
->GetMinSize();
860 SetSizeHints(size
.GetWidth() + margin
, size
.GetHeight() + margin
);
864 static int _next_id
= ID_LAST_USER_DEFINED
;
866 int ParamDialog::genId () {
870 bool ParamDialog::isGeneratedId (int id
) {
871 return (id
>= ID_LAST_USER_DEFINED
&& id
< _next_id
);
874 void ParamDialog::AddParamList(char *nameList
[], bx_param_c
*base
, wxFlexGridSizer
*sizer
, bool plain
)
877 while (nameList
[i
] != NULL
) {
878 bx_param_c
*param
= SIM
->get_param(nameList
[i
], base
);
880 AddParam(param
, sizer
, plain
);
886 // support "legacy" addparam functions. Easier than changing them.
887 void ParamDialog::AddParam (bx_param_c
*param
, wxFlexGridSizer
*sizer
, bool plain
)
889 AddParamContext context
;
891 context
.parent
= this;
892 context
.vertSizer
= mainSizer
;
893 context
.gridSizer
= sizer
;
894 AddParam (param
, plain
, &context
);
897 void ParamDialog::AddParam (
898 bx_param_c
*param_generic
,
900 AddParamContext
*context
)
902 AddParamContext defaultContext
;
903 if (context
== NULL
) {
904 context
= &defaultContext
;
906 context
->parent
= this;
907 context
->vertSizer
= mainSizer
;
908 context
->gridSizer
= NULL
;
910 wxASSERT (context
->parent
!= NULL
);
911 wxASSERT (context
->vertSizer
!= NULL
);
912 if (param_generic
== NULL
)
913 return; // param not registered, probably this option was not compiled in
914 wxLogDebug(wxT("AddParam for param '%s'"), param_generic
->get_name());
915 if (context
->gridSizer
== NULL
) {
916 // create a gridSizer if none exists yet. add it to default vertSizer.
917 context
->gridSizer
= new wxFlexGridSizer (3);
918 context
->vertSizer
->Add (context
->gridSizer
);
920 wxFlexGridSizer
*sizer
= context
->gridSizer
;
922 ParamStruct
*pstr
= new ParamStruct ();
923 pstr
->param
= param_generic
;
926 pstr
->u
.window
= NULL
;
927 pstr
->browseButton
= NULL
;
928 int type
= param_generic
->get_type();
930 if (type
== BXT_LIST
) {
931 bx_list_c
*list
= (bx_list_c
*)pstr
->param
;
932 prompt
= list
->get_title()->getptr();
934 prompt
= pstr
->param
->get_label();
936 if (!prompt
) prompt
= pstr
->param
->get_name();
937 const char *description
= pstr
->param
->get_description();
938 wxASSERT (prompt
!= NULL
);
939 #define ADD_LABEL(x) sizer->Add(pstr->label = new wxStaticText(context->parent, -1, wxString(x, wxConvUTF8)), 0, wxALIGN_RIGHT|wxALL, 3)
941 case BXT_PARAM_BOOL
: {
942 bx_param_bool_c
*param
= (bx_param_bool_c
*) param_generic
;
943 if (!plain
) ADD_LABEL(prompt
);
944 wxCheckBox
*ckbx
= new wxCheckBox (context
->parent
, pstr
->id
, wxT(""));
945 ckbx
->SetValue (param
->get ());
946 if (description
) ckbx
->SetToolTip(wxString(description
, wxConvUTF8
));
947 sizer
->Add (ckbx
, 0, wxALL
, 2);
948 if (!plain
) sizer
->Add (1, 1); // spacer
949 pstr
->u
.checkbox
= ckbx
;
950 idHash
->Put (pstr
->id
, pstr
);
951 paramHash
->Put (pstr
->param
->get_id (), pstr
);
954 case BXT_PARAM_NUM
: {
955 bx_param_num_c
*param
= (bx_param_num_c
*) param_generic
;
956 if (!plain
) ADD_LABEL (prompt
);
957 if (param
->get_options () & param
->USE_SPIN_CONTROL
) {
958 wxSpinCtrl
*spinctrl
= new wxSpinCtrl (context
->parent
, pstr
->id
);
959 spinctrl
->SetValue (param
->get ());
960 int max
= (param
->get_max () < (1<<24))?param
->get_max ():(1<<24)-1;
961 spinctrl
->SetRange (param
->get_min (), SPINCTRL_FIX_MAX (max
));
962 if (description
) spinctrl
->SetToolTip(wxString(description
, wxConvUTF8
));
963 sizer
->Add (spinctrl
, 0, wxALL
, 2);
964 if (!plain
) sizer
->Add (1, 1); // spacer
965 pstr
->u
.spin
= spinctrl
;
967 wxTextCtrl
*textctrl
= new wxTextCtrl (context
->parent
, pstr
->id
, wxT(""), wxDefaultPosition
, normalTextSize
);
968 const char *format
= param
->get_format ();
970 format
= strdup(param
->get_base () == 16 ? "0x%X" : "%d");
971 SetTextCtrl (textctrl
, format
, param
->get ());
972 if (description
) textctrl
->SetToolTip(wxString(description
, wxConvUTF8
));
973 sizer
->Add (textctrl
, 0, wxALL
, 2);
974 if (!plain
) sizer
->Add (1, 1); // spacer
975 pstr
->u
.text
= textctrl
;
977 idHash
->Put (pstr
->id
, pstr
);
978 paramHash
->Put (pstr
->param
->get_id (), pstr
);
981 case BXT_PARAM_ENUM
: {
982 bx_param_enum_c
*param
= (bx_param_enum_c
*) param_generic
;
983 if (!plain
) ADD_LABEL (prompt
);
984 wxChoice
*choice
= new wxChoice (context
->parent
, pstr
->id
);
985 if (description
) choice
->SetToolTip(wxString(description
, wxConvUTF8
));
986 sizer
->Add (choice
, 0, wxADJUST_MINSIZE
, 2);
987 if (!plain
) sizer
->Add (1, 1); // spacer
988 // fill in the choices
991 while (NULL
!= (ptr
= param
->get_choice(i
++)))
992 choice
->Append(wxString(ptr
, wxConvUTF8
));
993 choice
->SetSelection (param
->get() - param
->get_min());
994 pstr
->u
.choice
= choice
;
995 idHash
->Put(pstr
->id
, pstr
);
996 paramHash
->Put(pstr
->param
->get_id(), pstr
);
999 case BXT_PARAM_STRING
: {
1000 bx_param_string_c
*param
= (bx_param_string_c
*) param_generic
;
1001 if (!plain
) ADD_LABEL (prompt
);
1002 bool isFilename
= param
->get_options ()->get () & param
->IS_FILENAME
;
1003 wxTextCtrl
*txtctrl
= new wxTextCtrl (context
->parent
, pstr
->id
, wxT(""), wxDefaultPosition
, isFilename
? longTextSize
: normalTextSize
);
1004 if (description
) txtctrl
->SetToolTip(wxString(description
, wxConvUTF8
));
1005 if (param
->get_options()->get() & param
->RAW_BYTES
) {
1006 char *value
= param
->getptr();
1009 sep_string
[0] = param
->get_separator();
1011 for (int i
=0; i
<param
->get_maxsize(); i
++) {
1013 eachbyte
.Printf(wxT("%02x"), (unsigned int)0xff&value
[i
]);
1015 buffer
+= wxString(sep_string
, wxConvUTF8
);
1018 txtctrl
->SetValue(buffer
);
1020 txtctrl
->SetValue(wxString(param
->getptr(), wxConvUTF8
));
1021 txtctrl
->SetMaxLength(param
->get_maxsize());
1023 sizer
->Add (txtctrl
, 0, wxALL
, 2);
1026 // create Browse button
1027 pstr
->browseButtonId
= genId ();
1028 pstr
->browseButton
= new wxButton (context
->parent
,
1029 pstr
->browseButtonId
, BTNLABEL_BROWSE
);
1030 sizer
->Add (pstr
->browseButton
, 0, wxALL
, 2);
1031 idHash
->Put (pstr
->browseButtonId
, pstr
); // register under button id
1033 sizer
->Add (1, 1); // spacer
1036 pstr
->u
.text
= txtctrl
;
1037 idHash
->Put (pstr
->id
, pstr
);
1038 paramHash
->Put (pstr
->param
->get_id (), pstr
);
1042 bx_list_c
*list
= (bx_list_c
*) param_generic
;
1043 if (list
->get_options()->get() & bx_list_c::USE_TAB_WINDOW
) {
1044 // put each item in a separate tab of a tabbed window
1045 wxNotebook
*notebook
= new wxNotebook(context
->parent
, -1);
1046 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION < 6
1047 wxNotebookSizer
*nbsizer
= new wxNotebookSizer(notebook
);
1049 // put all items in the list into a separate page of the notebook.
1050 for (int i
=0; i
<list
->get_size (); i
++) {
1051 bx_list_c
*child
= (bx_list_c
*)list
->get(i
);
1052 wxASSERT (child
->get_type() == BXT_LIST
);
1053 // the child must be a list! I could support other things but
1054 // I don't see any reason to. It wouldn't make sense to devote
1055 // a whole tab to a single parameter.
1056 wxPanel
*panel
= new wxPanel(notebook
);
1057 wxBoxSizer
*boxsz
= new wxBoxSizer(wxVERTICAL
);
1058 AddParamContext newcontext
;
1059 newcontext
.depth
= 1 + context
->depth
;
1060 newcontext
.parent
= panel
;
1061 newcontext
.vertSizer
= boxsz
;
1062 newcontext
.gridSizer
= NULL
; // will be created if needed
1063 // the child itself is a list. Add the child's children in
1064 // this new context.
1065 bx_list_c
*childl
= (bx_list_c
*)child
;
1066 for (int j
=0; j
<childl
->get_size(); j
++)
1067 AddParam (childl
->get(j
), plain
, &newcontext
);
1068 const char *pagename
= child
->get_title()->getptr();
1069 if (!pagename
) pagename
= child
->get_name();
1070 panel
->SetAutoLayout(TRUE
);
1071 panel
->SetSizer(boxsz
);
1072 notebook
->AddPage(panel
, wxString(pagename
, wxConvUTF8
));
1074 #if wxMAJOR_VERSION == 2 && wxMINOR_VERSION < 6
1075 context
->vertSizer
->Add(nbsizer
, 0, wxALL
|wxGROW
, 10);
1077 context
->vertSizer
->Add(notebook
, 0, wxALL
|wxGROW
, 10);
1079 // clear gridSizer variable so that any future parameters force
1080 // creation of a new one.
1081 context
->gridSizer
= NULL
;
1083 pstr
->u
.notebook
= notebook
;
1084 idHash
->Put(pstr
->id
, pstr
);
1085 paramHash
->Put(pstr
->param
->get_id(), pstr
);
1088 if (list
->get_options()->get() & bx_list_c::USE_BOX_TITLE
) {
1089 boxTitle
= wxString(prompt
, wxConvUTF8
);
1093 wxStaticBox
*box
= new wxStaticBox(context
->parent
, -1, boxTitle
);
1094 wxStaticBoxSizer
*boxsz
= new wxStaticBoxSizer(box
, wxVERTICAL
);
1095 AddParamContext newcontext
;
1096 newcontext
.depth
= 1 + context
->depth
;
1097 newcontext
.parent
= context
->parent
;
1098 newcontext
.gridSizer
= NULL
; // it will be created if necessary
1099 newcontext
.vertSizer
= boxsz
;
1100 // put all items in the list inside the boxsz sizer.
1101 for (int i
=0; i
<list
->get_size (); i
++) {
1102 bx_param_c
*child
= list
->get (i
);
1103 AddParam (child
, plain
, &newcontext
);
1105 // add the boxsz to vertSizer
1106 context
->vertSizer
->Add (boxsz
, 0, wxALL
|wxGROW
, 10);
1107 // clear gridSizer variable so that any future parameters force
1108 // creation of a new one.
1109 context
->gridSizer
= NULL
;
1111 pstr
->u
.staticbox
= box
;
1112 idHash
->Put (pstr
->id
, pstr
);
1113 paramHash
->Put (pstr
->param
->get_id (), pstr
);
1118 wxLogError(wxT("ParamDialog::AddParam called with unsupported param type id=%d"), (int)type
);
1120 if (pstr
->label
) pstr
->label
->Enable(pstr
->param
->get_enabled());
1121 if (pstr
->u
.window
) pstr
->u
.window
->Enable(pstr
->param
->get_enabled());
1122 if (pstr
->browseButton
) pstr
->browseButton
->Enable(pstr
->param
->get_enabled());
1125 bool ParamDialog::CopyGuiToParam()
1127 // loop through all the parameters
1128 idHash
->BeginFind();
1130 while ((node
= idHash
->Next()) != NULL
) {
1131 ParamStruct
*pstr
= (ParamStruct
*) node
->GetData();
1132 wxLogDebug(wxT("commit changes for param %s"), pstr
->param
->get_name());
1133 int type
= pstr
->param
->get_type();
1135 case BXT_PARAM_BOOL
: {
1136 bx_param_bool_c
*boolp
= (bx_param_bool_c
*) pstr
->param
;
1137 bool val
= pstr
->u
.checkbox
->GetValue ();
1138 if (val
!= boolp
->get ()) boolp
->set (val
);
1141 case BXT_PARAM_NUM
: {
1142 bx_param_num_c
*nump
= (bx_param_num_c
*) pstr
->param
;
1145 wxString
complaint(wxT("Invalid integer for '"));
1146 complaint
+= wxString(pstr
->param
->get_name(), wxConvUTF8
);
1147 complaint
+= wxT("'.");
1148 if (nump
->get_options() & nump
->USE_SPIN_CONTROL
) {
1149 n
= pstr
->u
.spin
->GetValue();
1151 n
= GetTextCtrlInt(pstr
->u
.text
, &valid
, true, complaint
);
1153 if ((n
< nump
->get_min()) || (n
> nump
->get_max())) {
1154 wxMessageBox(wxT("Numerical parameter out of range"), wxT("Error"), wxOK
| wxICON_ERROR
, this);
1157 if (n
!= nump
->get()) nump
->set(n
);
1160 case BXT_PARAM_ENUM
: {
1161 bx_param_enum_c
*enump
= (bx_param_enum_c
*) pstr
->param
;
1162 int value
= pstr
->u
.choice
->GetSelection () + enump
->get_min();
1163 if (value
!= enump
->get ()) enump
->set (value
);
1166 case BXT_PARAM_STRING
: {
1167 bx_param_string_c
*stringp
= (bx_param_string_c
*) pstr
->param
;
1169 wxString
tmp(pstr
->u
.text
->GetValue ());
1170 if (stringp
->get_options()->get () & stringp
->RAW_BYTES
) {
1174 strcpy(src
, tmp
.mb_str(wxConvUTF8
));
1175 for (i
=0; i
<stringp
->get_maxsize(); i
++)
1177 for (i
=0; i
<stringp
->get_maxsize (); i
++) {
1178 while (src
[p
] == stringp
->get_separator ())
1180 if (src
[p
] == 0) break;
1181 // try to read a byte of hex
1182 if (sscanf (src
+p
, "%02x", &n
) == 1) {
1186 wxMessageBox(wxT("Illegal raw byte format"), wxT("Error"), wxOK
| wxICON_ERROR
, this);
1191 strncpy(buf
, tmp
.mb_str(wxConvUTF8
), sizeof(buf
));
1193 buf
[sizeof(buf
)-1] = 0;
1194 if (!stringp
->equals (buf
)) stringp
->set (buf
);
1200 wxLogError(wxT("ParamDialog::CopyGuiToParam: unsupported param type id=%d"), (int)type
);
1206 void ParamDialog::EnableChanged()
1208 idHash
->BeginFind();
1210 while ((node
= idHash
->Next ()) != NULL
) {
1211 ParamStruct
*pstr
= (ParamStruct
*) node
->GetData();
1212 if (pstr
->param
->get_type() == BXT_PARAM_BOOL
)
1213 EnableChanged(pstr
);
1214 if (pstr
->param
->get_type() == BXT_PARAM_ENUM
)
1217 if ((pstr
->param
->get_type() != BXT_LIST
) && !pstr
->param
->get_runtime_param())
1218 EnableParam(pstr
->param
->get_id(), false);
1220 // special cases that can't be handled in the usual way
1224 void ParamDialog::EnableChanged(ParamStruct
*pstrOfCheckbox
)
1226 wxLogDebug(wxT("EnableChanged on checkbox %s"), pstrOfCheckbox
->param
->get_name());
1227 bx_param_bool_c
*enableParam
= (bx_param_bool_c
*) pstrOfCheckbox
->param
;
1228 wxASSERT(enableParam
->get_type() == BXT_PARAM_BOOL
); // or we wouldn't be here
1229 bool en
= pstrOfCheckbox
->u
.checkbox
->GetValue();
1230 EnableChangedRecursive(enableParam
->get_dependent_list(), en
, pstrOfCheckbox
);
1233 void ParamDialog::EnableChangedRecursive(
1236 ParamStruct
*pstrOfCheckbox
)
1238 if (list
==NULL
) return;
1240 for (i
=0; i
<list
->get_size(); i
++) {
1241 bx_param_c
*param
= list
->get(i
);
1242 ParamStruct
*pstr
= (ParamStruct
*) paramHash
->Get(param
->get_id());
1244 if (param
== pstrOfCheckbox
->param
) {
1245 wxLogDebug(wxT("not setting enable on checkbox '%s' that triggered the enable change"), pstrOfCheckbox
->param
->get_name());
1248 wxLogDebug(wxT("setting enable for param '%s' to %d"), pstr
->param
->get_name(), en
?1:0);
1249 if (en
!= pstr
->u
.window
->IsEnabled()) {
1250 EnableParam(pstr
->param
->get_id(), en
);
1251 bx_list_c
*deps
= pstr
->param
->get_dependent_list();
1253 wxLogDebug(wxT("recursing on dependent list of %s"), list
->get_name());
1254 if (pstr
->param
->get_type() == BXT_PARAM_BOOL
) {
1255 bool dep_en
= pstr
->u
.window
->IsEnabled() && pstr
->u
.checkbox
->GetValue();
1256 EnableChangedRecursive(deps
, dep_en
, pstr
);
1262 // if any enums changed, give them a chance to update
1263 for (i
=0; i
<list
->get_size (); i
++) {
1264 bx_param_c
*param
= list
->get(i
);
1265 ParamStruct
*pstr
= (ParamStruct
*) paramHash
->Get(param
->get_id());
1267 if (pstr
->param
->get_type () == BXT_PARAM_ENUM
)
1273 void ParamDialog::EnableParam(int param_id
, bool enabled
)
1275 ParamStruct
*pstr
= (ParamStruct
*) paramHash
->Get(param_id
);
1277 if (pstr
->label
) pstr
->label
->Enable(enabled
);
1278 if (pstr
->browseButton
) pstr
->browseButton
->Enable(enabled
);
1279 if (pstr
->u
.window
) pstr
->u
.window
->Enable(enabled
);
1282 void ParamDialog::EnableParam(const char *pname
, bool enabled
)
1284 int param_id
= SIM
->get_param(pname
)->get_id();
1285 ParamStruct
*pstr
= (ParamStruct
*) paramHash
->Get(param_id
);
1287 if (pstr
->label
) pstr
->label
->Enable(enabled
);
1288 if (pstr
->browseButton
) pstr
->browseButton
->Enable(enabled
);
1289 if (pstr
->u
.window
) pstr
->u
.window
->Enable(enabled
);
1292 void ParamDialog::EnableParam(const char *pname
, bx_list_c
*base
, bool enabled
)
1294 int param_id
= SIM
->get_param(pname
, base
)->get_id();
1295 ParamStruct
*pstr
= (ParamStruct
*) paramHash
->Get(param_id
);
1297 if (pstr
->label
) pstr
->label
->Enable(enabled
);
1298 if (pstr
->browseButton
) pstr
->browseButton
->Enable(enabled
);
1299 if (pstr
->u
.window
) pstr
->u
.window
->Enable(enabled
);
1302 void ParamDialog::EnumChanged(ParamStruct
*pstr
)
1304 wxLogDebug(wxT("EnumChanged"));
1306 Bit8u channel
, device
;
1308 bx_list_c
*base
= (bx_list_c
*) pstr
->param
->get_parent();
1310 base
->get_param_path(pname
, 512);
1314 if (!strncmp(pname
, "ata.", 4)) {
1315 channel
= pname
[4] - '0';
1316 if (!strcmp(base
->get_name(), "master")) {
1321 if (!strcmp(pstr
->param
->get_name(), "type")) {
1322 // find out if "present" checkbox is checked
1323 int present_id
= SIM
->get_param_bool("present", base
)->get_id();
1324 ParamStruct
*present
= (ParamStruct
*) paramHash
->Get(present_id
);
1325 wxASSERT(present
&& present
->param
->get_type() == BXT_PARAM_BOOL
);
1326 if (!present
->u
.checkbox
->GetValue())
1327 return; // device not enabled, leave it alone
1328 if (!present
->u
.checkbox
->IsEnabled())
1329 return; // enable button for the device is not enabled
1330 wxASSERT(pstr
->param
->get_type() == BXT_PARAM_ENUM
);
1331 int type
= pstr
->u
.choice
->GetSelection();
1332 if (type
== BX_ATA_DEVICE_DISK
) {
1333 // enable cylinders, heads, spt
1334 wxLogDebug(wxT("enabling disk parameters"));
1335 EnableParam("mode", base
, 1);
1336 EnableParam("cylinders", base
, 1);
1337 EnableParam("heads", base
, 1);
1338 EnableParam("spt", base
, 1);
1339 EnableParam("status", base
, 0);
1340 EnableParam("translation", base
, 1);
1342 int mode_id
= SIM
->get_param_enum("mode", base
)->get_id();
1343 ParamStruct
*mode_param
= (ParamStruct
*) paramHash
->Get(mode_id
);
1344 int mode
= BX_ATA_MODE_FLAT
;
1345 if(mode_param
) mode
=mode_param
->u
.choice
->GetSelection();
1347 case BX_ATA_MODE_UNDOABLE
:
1348 case BX_ATA_MODE_VOLATILE
:
1349 EnableParam("journal", base
, 1);
1352 EnableParam("journal", base
, 0);
1358 wxLogDebug(wxT("enabling cdrom parameters"));
1359 EnableParam("mode", base
, 0);
1360 EnableParam("cylinders", base
, 0);
1361 EnableParam("heads", base
, 0);
1362 EnableParam("spt", base
, 0);
1363 EnableParam("status", base
, 1);
1364 EnableParam("translation", base
, 0);
1365 EnableParam("journal", base
, 0);
1367 } else if (!strcmp(pstr
->param
->get_name(), "mode")) {
1368 // find out if "present" checkbox is checked
1369 int present_id
= SIM
->get_param_bool("present", base
)->get_id();
1370 ParamStruct
*present
= (ParamStruct
*) paramHash
->Get(present_id
);
1371 wxASSERT (present
&& present
->param
->get_type() == BXT_PARAM_BOOL
);
1372 if (!present
->u
.checkbox
->GetValue ())
1373 return; // device not enabled, leave it alone
1374 if (!present
->u
.checkbox
->IsEnabled ())
1375 return; // enable button for the device is not enabled
1376 wxASSERT(pstr
->param
->get_type() == BXT_PARAM_ENUM
);
1377 int mode
= pstr
->u
.choice
->GetSelection();
1379 case BX_ATA_MODE_UNDOABLE
:
1380 case BX_ATA_MODE_VOLATILE
:
1381 EnableParam("journal", base
, 1);
1384 EnableParam("journal", base
, 0);
1389 pstr
->param
->get_param_path(pname
, 512);
1390 if (!strcmp(pname
, BXPN_LOAD32BITOS_WHICH
)) {
1391 int os
= pstr
->u
.choice
->GetSelection();
1392 if (os
!= Load32bitOSNone
) {
1393 EnableParam(BXPN_LOAD32BITOS_PATH
, 1);
1394 EnableParam(BXPN_LOAD32BITOS_IOLOG
, 1);
1395 EnableParam(BXPN_LOAD32BITOS_INITRD
, 1);
1397 EnableParam(BXPN_LOAD32BITOS_PATH
, 0);
1398 EnableParam(BXPN_LOAD32BITOS_IOLOG
, 0);
1399 EnableParam(BXPN_LOAD32BITOS_INITRD
, 0);
1405 // if any parameters changed, update the associated control
1406 void ParamDialog::CopyParamToGui ()
1408 // loop through all the parameters
1409 idHash
->BeginFind ();
1411 while ((node
= idHash
->Next ()) != NULL
) {
1412 ParamStruct
*pstr
= (ParamStruct
*) node
->GetData ();
1413 IFDBG_DLG(wxLogDebug(wxT("refresh param %s"), pstr
->param
->get_name()));
1414 int type
= pstr
->param
->get_type ();
1416 case BXT_PARAM_BOOL
: {
1417 bx_param_bool_c
*boolp
= (bx_param_bool_c
*) pstr
->param
;
1418 pstr
->u
.checkbox
->SetValue (boolp
->get ());
1421 case BXT_PARAM_NUM
: {
1422 bx_param_num_c
*nump
= (bx_param_num_c
*) pstr
->param
;
1423 const char *format
= nump
->get_format ();
1425 format
= strdup(nump
->get_base () == 16 ? "0x%X" : "%d");
1426 SetTextCtrl (pstr
->u
.text
, format
, nump
->get ());
1429 case BXT_PARAM_ENUM
: {
1430 bx_param_enum_c
*enump
= (bx_param_enum_c
*) pstr
->param
;
1431 pstr
->u
.choice
->SetSelection (enump
->get () - enump
->get_min ());
1434 case BXT_PARAM_STRING
: {
1435 bx_param_string_c
*stringp
= (bx_param_string_c
*) pstr
->param
;
1436 pstr
->u
.text
->SetValue (wxString(stringp
->getptr (), wxConvUTF8
));
1442 wxLogError(wxT("ParamDialog::CopyParamToGui(): unsupported param type id=%d"), (int)type
);
1447 void ParamDialog::OnEvent(wxCommandEvent
& event
)
1449 int id
= event
.GetId();
1450 if (isGeneratedId(id
)) {
1451 ParamStruct
*pstr
= (ParamStruct
*) idHash
->Get(id
);
1453 wxLogDebug(wxT("ParamStruct not found for id=%d"), id
);
1456 if (id
== pstr
->id
) {
1457 IFDBG_DLG(wxLogDebug(wxT("event came from window %p (id=%d) controlled by parameter '%s'"), pstr
->u
.window
, id
, pstr
->param
->get_name()));
1458 switch (pstr
->param
->get_type ()) {
1459 case BXT_PARAM_BOOL
:
1460 EnableChanged(pstr
);
1462 case BXT_PARAM_ENUM
:
1468 if (id
== pstr
->browseButtonId
) {
1469 wxLogDebug(wxT("browse button id=%d attached to wxTextCtrl %p"), id
, pstr
->u
.text
);
1470 BrowseTextCtrl(pstr
->u
.text
);
1473 wxLogDebug(wxT("id was key to ParamStruct but doesn't match either id inside"));
1478 if (CopyGuiToParam ())
1486 EndModal (wxID_CANCEL
);
1498 void ParamDialog::ShowHelp()
1500 wxMessageBox(MSG_NO_HELP
, MSG_NO_HELP_CAPTION
, wxOK
| wxICON_ERROR
, this);
1503 /////////////////////////////////////////////////////////////////
1504 // CpuRegistersDialog
1505 /////////////////////////////////////////////////////////////////
1508 // - mainRegsSizer (grid or flexgrid)
1510 // - params from EAX to ESP
1512 // - params from EIP to EFLAGS
1514 // - params from LDTR to IDTR limit
1524 // all events go to OnEvent method
1525 BEGIN_EVENT_TABLE(CpuRegistersDialog
, wxDialog
)
1526 EVT_BUTTON(-1, CpuRegistersDialog::OnEvent
)
1527 EVT_CHECKBOX(-1, CpuRegistersDialog::OnEvent
)
1528 EVT_TEXT(-1, CpuRegistersDialog::OnEvent
)
1531 CpuRegistersDialog::CpuRegistersDialog(
1534 : ParamDialog(parent
, id
)
1536 wxFlexGridSizer
*column
;
1538 char *mainRegList1
[] = CPU_REGS_MAIN_REGS1
;
1539 char *mainRegList2
[] = CPU_REGS_MAIN_REGS2
;
1540 char *mainRegList3
[] = CPU_REGS_MAIN_REGS3
;
1541 char *flagList
[] = CPU_REGS_FLAGS
;
1542 char *controlList
[] = CPU_REGS_CONTROL_REGS
;
1543 char *debugList
[] = CPU_REGS_DEBUG_REGS
;
1544 char *testList
[] = CPU_REGS_TEST_REGS
;
1545 bx_list_c
*base
= (bx_list_c
*)SIM
->get_param(BXPN_WX_CPU0_STATE
);
1547 // top level objects
1548 wxStaticBox
*mainRegsBox
= new wxStaticBox(this, -1, wxT("Basic Registers"));
1549 wxStaticBoxSizer
*mainRegsBoxSizer
=
1550 new wxStaticBoxSizer(mainRegsBox
, wxVERTICAL
);
1551 mainSizer
->Add(mainRegsBoxSizer
, 0, wxALL
|wxGROW
, 10);
1553 wxStaticBox
*flagsBox
= new wxStaticBox(this, -1, wxT("EFLAGS Bits"));
1554 wxStaticBoxSizer
*flagsBoxSizer
=
1555 new wxStaticBoxSizer(flagsBox
, wxVERTICAL
);
1556 mainSizer
->Add(flagsBoxSizer
, 0, wxALL
|wxGROW
, 10);
1558 wxStaticBox
*otherBox
= new wxStaticBox(this, -1, wxT("Other Registers"));
1559 wxStaticBoxSizer
*otherBoxSizer
=
1560 new wxStaticBoxSizer(otherBox
, wxVERTICAL
);
1561 mainSizer
->Add(otherBoxSizer
, 0, wxALL
|wxGROW
, 10);
1563 // mainRegsSizer contents
1564 mainRegsSizer
= new wxFlexGridSizer(3);
1565 mainRegsBoxSizer
->Add(mainRegsSizer
, 0, wxALL
, 3);
1566 column
= new wxFlexGridSizer(3);
1567 mainRegsSizer
->Add(column
, 0, wxALL
, 10);
1568 AddParamList(mainRegList1
, base
, column
);
1570 column
= new wxFlexGridSizer(3);
1571 mainRegsSizer
->Add(column
, 0, wxALL
, 10);
1572 AddParamList(mainRegList2
, base
, column
);
1574 column
= new wxFlexGridSizer(3);
1575 mainRegsSizer
->Add(column
, 0, wxALL
, 10);
1576 AddParamList(mainRegList3
, base
, column
);
1578 // add flag parameters
1579 flagsSizer
= new wxFlexGridSizer(CPU_REGS_MAX_FLAGS
);
1580 flagsBoxSizer
->Add(flagsSizer
, 0, wxALL
| wxALIGN_CENTER
, 3);
1582 while (flagList
[i
] != NULL
) {
1583 bx_param_c
*param
= SIM
->get_param(flagList
[i
], base
);
1584 if (param
!= NULL
) {
1590 // extRegsSizer contents
1591 extRegsSizer
= new wxFlexGridSizer(3);
1592 otherBoxSizer
->Add(extRegsSizer
, 0, wxALL
, 3);
1594 column
= new wxFlexGridSizer(3);
1595 extRegsSizer
->Add(column
, 0, wxALL
, 10);
1596 AddParamList(controlList
, base
, column
);
1598 column
= new wxFlexGridSizer(3);
1599 extRegsSizer
->Add(column
, 0, wxALL
, 10);
1600 AddParamList(debugList
, base
, column
);
1602 column
= new wxFlexGridSizer(3);
1603 extRegsSizer
->Add(column
, 0, wxALL
, 10);
1604 AddParamList(testList
, base
, column
);
1608 // only show these if debugger is enabled
1609 contButton
= AddButton(ID_Debug_Continue
, BTNLABEL_DEBUG_CONTINUE
);
1610 stopButton
= AddButton(ID_Debug_Stop
, BTNLABEL_DEBUG_STOP
);
1611 stepButton
= AddButton(ID_Debug_Step
, BTNLABEL_DEBUG_STEP
);
1612 //commitButton = AddButton(ID_Debug_Commit, BTNLABEL_DEBUG_COMMIT);
1614 AddButton(ID_Close
, BTNLABEL_CLOSE
);
1617 void CpuRegistersDialog::AddFlag(bx_param_c
*param
)
1619 if (param
== NULL
) {
1620 wxLogDebug(wxT("AddFlag on undefined param"));
1623 wxASSERT(nflags
< CPU_REGS_MAX_FLAGS
);
1624 flagptr
[nflags
++] = param
;
1627 void CpuRegistersDialog::Init()
1630 for (i
=0; i
<CPU_REGS_MAX_FLAGS
; i
++) {
1632 bx_param_c
*param
= flagptr
[i
];
1633 flagsSizer
->Add(new wxStaticText(this, -1, wxString(param
->get_label(), wxConvUTF8
)), 0, wxALL
|wxALIGN_LEFT
, 4);
1635 flagsSizer
->Add(0, 0); // spacer
1638 for (i
=0; i
<nflags
; i
++) {
1639 bx_param_c
*param
= flagptr
[i
];
1640 AddParam(param
, flagsSizer
, true);
1642 // special case: make IOPL text field small
1643 ParamStruct
*pstr
= (ParamStruct
*)paramHash
->Get(SIM
->get_param(BXPN_WX_CPU0_EFLAGS_IOPL
)->get_id());
1645 wxSize size
= pstr
->u
.text
->GetSize();
1646 size
.SetWidth (size
.GetWidth() / 2);
1647 pstr
->u
.text
->SetSize(size
);
1648 flagsSizer
->SetItemMinSize(pstr
->u
.text
, size
.GetWidth(), size
.GetHeight());
1650 ParamDialog::Init();
1651 stateChanged(false);
1654 void CpuRegistersDialog::stateChanged (bool simRunning
)
1657 contButton
->Enable (!simRunning
);
1658 stepButton
->Enable (!simRunning
);
1659 stopButton
->Enable (simRunning
);
1663 void CpuRegistersDialog::CopyParamToGui ()
1665 ParamDialog::CopyParamToGui ();
1667 stateChanged (SIM
->get_param_bool(BXPN_DEBUG_RUNNING
)->get());
1671 // How am I going to communicate with the debugger?
1673 // The current model is that the debugger asks you for a command, and
1674 // blocks forever until you press return. Then it interprets the command,
1675 // however long it takes, and returns to the input loop when the command
1676 // is done. A control-C can stop a command prematurely.
1678 // To extend this into wxWidgets multithreaded space, I will create a
1679 // synchronous event called BX_SYNC_GET_DBG_COMMAND which is sent from
1680 // the simulation thread to wxWidgets. When the user chooses a debugger
1681 // action (step, continue, breakpoint, etc.) the simulation awakens and
1682 // interprets the event by calling a function in bx_debug/dbg_main.cc.
1684 // The equivalent of a control-C is pressing the "Stop" button during
1685 // a long step or continue command. This can be implemented by setting
1686 // bx_guard.interrupt_requested = 1, just like the SIGINT handler in
1687 // bx_debug/dbg_main.cc does.
1689 // input loop model is good. Create a debugger input loop, possibly in
1691 // in the simulation thread. This loop waits for a command from the
1692 // wxWidgets debugger
1694 // For example, if you press the "Step" button 5
1695 // times, with each click it should call bx_dbg_stepN_command(1) in the
1696 // simulator thread. When it returns, it goes back to
1698 void CpuRegistersDialog::OnEvent(wxCommandEvent
& event
)
1700 int id
= event
.GetId ();
1707 wxLogDebug(wxT("wxWidgets triggered a break"));
1708 theFrame
->DebugBreak();
1710 case ID_Debug_Continue
:
1711 wxLogDebug(wxT("before calling DebugCommand"));
1712 theFrame
->DebugCommand("continue");
1713 wxLogDebug(wxT("after calling DebugCommand"));
1716 theFrame
->DebugCommand("step 1");
1718 case ID_Debug_Commit
:
1723 ParamDialog::OnEvent(event
);
1727 //////////////////////////////////////////////////////////////////////
1728 // LogOptionsDialog implementation
1729 //////////////////////////////////////////////////////////////////////
1731 // all events go to OnEvent method
1732 BEGIN_EVENT_TABLE(LogOptionsDialog
, wxDialog
)
1733 EVT_BUTTON(-1, LogOptionsDialog::OnEvent
)
1734 EVT_CHECKBOX(-1, LogOptionsDialog::OnEvent
)
1735 EVT_TEXT(-1, LogOptionsDialog::OnEvent
)
1738 LogOptionsDialog::LogOptionsDialog(
1741 : ParamDialog(parent
, id
)
1743 static wxString names
[] = LOG_OPTS_TYPE_NAMES
;
1744 SetTitle(LOG_OPTS_TITLE
);
1745 AddParam(SIM
->get_param("log"));
1746 wxStaticText
*text
= new wxStaticText(this, -1, LOG_OPTS_PROMPT
);
1747 mainSizer
->Add(text
, 0, wxALL
, 10);
1748 gridSizer
= new wxFlexGridSizer (2);
1749 mainSizer
->Add(gridSizer
, 1, wxLEFT
, 40);
1750 text
= new wxStaticText (this, -1, LOG_OPTS_ADV
);
1751 mainSizer
->Add(text
, 0, wxTOP
|wxLEFT
, 20);
1753 // gridSizer contents
1754 gridSizer
->AddGrowableCol(1);
1755 for (int evtype
=0; evtype
<LOG_OPTS_N_TYPES
; evtype
++) {
1756 gridSizer
->Add(new wxStaticText (this, -1, names
[evtype
]), 0, wxALL
, 5);
1757 action
[evtype
] = makeLogOptionChoiceBox(this, -1, evtype
, true);
1758 gridSizer
->Add(action
[evtype
], 1, wxALL
|wxGROW
|wxADJUST_MINSIZE
, 5);
1762 void LogOptionsDialog::SetAction(int evtype
, int a
)
1764 // find the choice whose client data matches "a".
1766 //wxLogDebug ("SetAction type=%d a=%d", evtype, a);
1767 for (int i
=0; i
< action
[evtype
]->GetCount(); i
++) {
1768 //wxLogDebug ("reading action[%d]->GetClientData(%d)", evtype, i);
1769 ptr
= (int*) action
[evtype
]->GetClientData(i
);
1770 if (ptr
== NULL
) continue;
1771 if (a
== *ptr
) { // found it!
1772 action
[evtype
]->SetSelection(i
);
1776 // this can happen if one of the choices that is excluded by
1777 // LOG_OPTS_EXCLUDE() is used, for example.
1778 wxLogDebug(wxT("SetAction type=%d a=%d not found"), evtype
, a
);
1781 int LogOptionsDialog::GetAction(int evtype
)
1783 int sel
= action
[evtype
]->GetSelection();
1784 int *ptrToChoice
= (int*)action
[evtype
]->GetClientData(sel
);
1785 wxASSERT(ptrToChoice
!= NULL
);
1786 return *ptrToChoice
;
1790 /////////////////////////////////////////////////////////////////
1792 /////////////////////////////////////////////////////////////////
1794 // Unfortunately this step is necessary if you change the text of
1795 // a wxStaticText. Otherwise the sizer that contains the text never realizes
1796 // that the size has changed, and the layout is never updated. The
1797 // SetItemMinSize trick was reported on comp.soft-sys.wxwindows by
1799 void ChangeStaticText (wxSizer
*sizer
, wxStaticText
*win
, wxString newtext
)
1801 win
->SetLabel(newtext
);
1802 wxSize sz
= win
->GetSize();
1803 sizer
->SetItemMinSize(win
, sz
.GetWidth(), sz
.GetHeight());
1806 // CreateImage produces a disk image. It's in the utility function
1807 // area because it's used by both floppy and hard disk image creation.
1808 bool CreateImage (int harddisk
, int sectors
, const char *filename
)
1811 wxMessageBox(wxT("The disk size is invalid."), wxT("Invalid Size"), wxOK
| wxICON_ERROR
);
1814 wxLogDebug(wxT("filename = '%s'\n"), filename
);
1815 if (strlen (filename
) < 1) {
1816 wxMessageBox(wxT("You must type a file name for the new disk image."), wxT("Bad Filename"), wxOK
| wxICON_ERROR
);
1819 // create disk image with name and capacity determined by the filename
1820 // and sector args. Call SIM->create_image (filename, sectors, overwrite=0)
1821 // first which will create the file if it doesn't already exist. If it
1822 // exists, it will instead return -1, and we can ask the user "are you sure
1823 // you want to overwrite?". If yes, call again with overwrite=1.
1824 int ret
= SIM
->create_disk_image (filename
, sectors
, 0);
1825 if (ret
== -1) { // already exists
1826 int answer
= wxMessageBox(wxT("File exists. Do you want to overwrite it?"),
1827 wxT("File exists"), wxYES_NO
| wxCENTER
);
1828 if (answer
== wxYES
)
1829 ret
= SIM
->create_disk_image (filename
, sectors
, 1);
1831 return false; // wxNO
1834 wxMessageBox(wxT("I could not create the disk image. Check for permission problems or available disk space."), wxT("Failed"), wxOK
| wxICON_ERROR
);
1841 void SetTextCtrl(wxTextCtrl
*ctrl
, const char *format
, int val
)
1844 tmp
.Printf(wxString(format
, wxConvUTF8
), val
);
1845 ctrl
->SetValue(tmp
);
1848 int GetTextCtrlInt (wxTextCtrl
*ctrl
,
1853 wxString
tmp (ctrl
->GetValue());
1855 strncpy(buf
, tmp
.mb_str(wxConvUTF8
), sizeof(buf
));
1856 int n
= strtol(buf
, NULL
, 0);
1857 if (n
!= LONG_MIN
&& n
!= LONG_MAX
) {
1858 if (valid
) *valid
= true;
1861 if (valid
) *valid
= false;
1863 wxMessageBox(complaint
, wxT("Invalid"), wxOK
| wxICON_ERROR
);
1869 bool BrowseTextCtrl(wxTextCtrl
*text
, wxString prompt
, long style
)
1871 // try to configure the dialog to show hidden files
1872 wxConfigBase::Get() ->Write(wxT("/wxWidgets/wxFileDialog/ShowHidden"), true);
1873 wxFileDialog
*fdialog
= new wxFileDialog (text
->GetParent(), prompt
, wxT(""), text
->GetValue(), wxT("*.*"), style
);
1874 int result
= fdialog
->ShowModal();
1875 if (result
== wxID_OK
)
1876 text
->SetValue(fdialog
->GetPath());
1878 return (result
== wxID_OK
);
1881 wxChoice
*makeLogOptionChoiceBox (wxWindow
*parent
,
1884 bool includeNoChange
)
1886 static wxString choices
[] = LOG_OPTS_CHOICES
;
1887 static int integers
[LOG_OPTS_N_CHOICES
] = {0, 1, 2, 3, 4};
1888 wxChoice
*control
= new wxChoice(parent
, id
, wxDefaultPosition
, wxDefaultSize
);
1889 int lastChoice
= 0; // remember index of last choice
1890 int nchoice
= includeNoChange
? LOG_OPTS_N_CHOICES
: LOG_OPTS_N_CHOICES_NORMAL
;
1891 for (int choice
=0; choice
<nchoice
; choice
++) {
1892 // the exclude expression allows some choices to not be available
1893 // for some times. For example, it would be stupid to ignore a panic.
1894 if (!LOG_OPTS_EXCLUDE(evtype
, choice
)) {
1895 control
->Append(choices
[choice
], &integers
[choice
]);
1896 // the client data is an int* that points to the choice number.
1897 // This is what will be returned by GetAction().
1901 control
->SetSelection (lastChoice
-1);
1905 #endif /* if BX_WITH_WX */