- move read configuration and save configuration behavior out of wx.cc

and into wxmain.cc, like other actions.
- set a default siminterface callback for the whole application, which is used
  whenever the simulator is not running.  This is important when the wx code
  calls simulator or param code and triggers a BX_PANIC or something.
  The default callback is responsible for displaying error messages which
  appear while reading the bochsrc, for example.
- move the implementation of BX_SYNC_EVT_LOG_ASK and BX_ASYNC_EVT_LOG_MSG
  into a separate function OnLogMsg().  In the future, OnLogMsg() may be called
  from the application default callback on errors.
- modified: gui/wx.cc gui/wxmain.cc gui/wxmain.h
This commit is contained in:
Bryce Denney 2002-09-25 18:40:15 +00:00
parent e3760bedc8
commit a4f0c5b53e
3 changed files with 115 additions and 67 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wx.cc,v 1.29 2002-09-25 07:21:38 bdenney Exp $
// $Id: wx.cc,v 1.30 2002-09-25 18:40:15 bdenney Exp $
/////////////////////////////////////////////////////////////////
//
// wxWindows VGA display for Bochs. wx.cc implements a custom
@ -222,32 +222,6 @@ MyPanel::MyRefresh ()
needRefresh = true;
}
void
MyPanel::ReadConfiguration ()
{
char *bochsrc;
long style = wxOPEN;
wxFileDialog *fdialog = new wxFileDialog (this, "Read configuration", "", "", "*.*", style);
if (fdialog->ShowModal() == wxID_OK) {
bochsrc = (char *)fdialog->GetPath().c_str ();
bx_read_configuration(bochsrc);
}
delete fdialog;
}
void
MyPanel::SaveConfiguration ()
{
char *bochsrc;
long style = wxSAVE | wxOVERWRITE_PROMPT;
wxFileDialog *fdialog = new wxFileDialog (this, "Save configuration", "", "", "*.*", style);
if (fdialog->ShowModal() == wxID_OK) {
bochsrc = (char *)fdialog->GetPath().c_str ();
bx_write_configuration(bochsrc, 1);
}
delete fdialog;
}
void MyPanel::OnKeyDown(wxKeyEvent& event)
{
if(event.GetKeyCode() == WXK_F12) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wxmain.cc,v 1.56 2002-09-22 20:56:12 cbothamy Exp $
// $Id: wxmain.cc,v 1.57 2002-09-25 18:40:15 bdenney Exp $
/////////////////////////////////////////////////////////////////
//
// wxmain.cc implements the wxWindows frame, toolbar, menus, and dialogs.
@ -91,6 +91,12 @@ class MyApp: public wxApp
{
virtual bool OnInit();
virtual int OnExit();
public:
// This default callback is installed when the simthread is NOT running,
// so that events coming from the simulator code can be handled.
// The primary culprit is panics which cause an BX_SYNC_EVT_LOG_ASK.
static BxEvent *DefaultCallback (void *thisptr, BxEvent *event);
BxEvent *DefaultCallback2 (BxEvent *event);
};
// SimThread is the thread in which the Bochs simulator runs. It is created
@ -135,6 +141,9 @@ bool MyApp::OnInit()
//wxLog::AddTraceMask (_T("mime"));
wxLog::SetActiveTarget (new wxLogStderr ());
bx_init_siminterface ();
// install callback function to handle anything that occurs before the
// simulation begins.
SIM->set_notify_callback (&MyApp::DefaultCallback, this);
bx_init_main (argc, argv);
MyFrame *frame = new MyFrame( "Bochs x86 Emulator", wxPoint(50,50), wxSize(450,340), wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION );
theFrame = frame; // hack alert
@ -154,6 +163,46 @@ int MyApp::OnExit ()
return 0;
}
// these are only called when the simthread is not running.
BxEvent *
MyApp::DefaultCallback (void *thisptr, BxEvent *event)
{
MyApp *me = (MyApp *)thisptr;
// call the normal non-static method now that we know the this pointer.
return me->DefaultCallback2 (event);
}
BxEvent *
MyApp::DefaultCallback2 (BxEvent *event)
{
wxLogDebug ("DefaultCallback2: event type %d", event->type);
event->retcode = -1; // default return code
switch (event->type)
{
case BX_ASYNC_EVT_LOG_MSG:
case BX_SYNC_EVT_LOG_ASK: {
wxLogDebug ("DefaultCallback2: log ask event");
wxString text;
text.Printf ("Error: %s", event->u.logmsg.msg);
wxMessageBox (text, "Error", wxOK | wxICON_ERROR );
//theFrame->OnLogMsg (event);
event->retcode = BX_LOG_ASK_CHOICE_CONTINUE;
// There is only one thread at this point. if I choose DIE here, it will
// call fatal() and kill the whole app.
break;
}
case BX_ASYNC_EVT_REFRESH:
case BX_SYNC_EVT_ASK_PARAM:
case BX_ASYNC_EVT_DBG_MSG:
case BX_SYNC_EVT_GET_DBG_COMMAND:
break;
default:
wxLogDebug ("unknown event type %d", event->type);
}
return event;
}
//////////////////////////////////////////////////////////////////////
// MyFrame: the top level frame for the Bochs application
//////////////////////////////////////////////////////////////////////
@ -390,12 +439,27 @@ void MyFrame::OnConfigNew(wxCommandEvent& WXUNUSED(event))
void MyFrame::OnConfigRead(wxCommandEvent& WXUNUSED(event))
{
panel->ReadConfiguration ();
char *bochsrc;
long style = wxOPEN;
wxFileDialog *fdialog = new wxFileDialog (this, "Read configuration", "", "", "*.*", style);
if (fdialog->ShowModal() == wxID_OK) {
bochsrc = (char *)fdialog->GetPath().c_str ();
SIM->reset_all_param ();
SIM->read_rc (bochsrc);
}
delete fdialog;
}
void MyFrame::OnConfigSave(wxCommandEvent& WXUNUSED(event))
{
panel->SaveConfiguration ();
char *bochsrc;
long style = wxSAVE | wxOVERWRITE_PROMPT;
wxFileDialog *fdialog = new wxFileDialog (this, "Save configuration", "", "", "*.*", style);
if (fdialog->ShowModal() == wxID_OK) {
bochsrc = (char *)fdialog->GetPath().c_str ();
SIM->write_rc (bochsrc, 1);
}
delete fdialog;
}
void MyFrame::OnEditBoot(wxCommandEvent& WXUNUSED(event))
@ -1081,39 +1145,8 @@ MyFrame::OnSim2CIEvent (wxCommandEvent& event)
#endif
case BX_SYNC_EVT_LOG_ASK:
case BX_ASYNC_EVT_LOG_MSG:
{
wxLogDebug ("log msg: level=%d, prefix='%s', msg='%s'",
be->u.logmsg.level,
be->u.logmsg.prefix,
be->u.logmsg.msg);
if (be->type == BX_ASYNC_EVT_LOG_MSG) {
// don't ask for user response
delete be;
return;
}
wxString levelName (SIM->get_log_level_name (be->u.logmsg.level));
LogMsgAskDialog dlg (this, -1, levelName); // panic, error, etc.
#if !BX_DEBUGGER
dlg.EnableButton (dlg.DEBUG, FALSE);
#endif
dlg.SetContext (be->u.logmsg.prefix);
dlg.SetMessage (be->u.logmsg.msg);
int n = dlg.ShowModal ();
Boolean dontAsk = dlg.GetDontAsk ();
// turn the return value into the constant that logfunctions::ask is
// expecting. 0=continue, 1=continue but ignore future messages from this
// device, 2=die, 3=dump core, 4=debugger. FIXME: yuck. replace hardcoded
// constants in logfunctions::ask with enum or defined constant.
if (n==0) {
n = dontAsk? 1 : 0;
} else {
n=n+1;
}
be->retcode = n;
wxLogDebug ("you chose %d", n);
sim_thread->SendSyncResponse (be);
OnLogMsg (be);
return;
}
case BX_SYNC_EVT_GET_DBG_COMMAND:
wxLogDebug ("BX_SYNC_EVT_GET_DBG_COMMAND received");
if (debugCommand == NULL) {
@ -1153,6 +1186,47 @@ MyFrame::OnSim2CIEvent (wxCommandEvent& event)
wxASSERT_MSG (0, "switch stmt should have returned");
}
void MyFrame::OnLogMsg (BxEvent *be) {
wxLogDebug ("log msg: level=%d, prefix='%s', msg='%s'",
be->u.logmsg.level,
be->u.logmsg.prefix,
be->u.logmsg.msg);
if (be->type == BX_ASYNC_EVT_LOG_MSG) {
// don't ask for user response
delete be; // because it was async
return;
} else {
wxASSERT (be->type == BX_SYNC_EVT_LOG_ASK);
}
wxString levelName (SIM->get_log_level_name (be->u.logmsg.level));
LogMsgAskDialog dlg (this, -1, levelName); // panic, error, etc.
#if !BX_DEBUGGER
dlg.EnableButton (dlg.DEBUG, FALSE);
#endif
dlg.SetContext (be->u.logmsg.prefix);
dlg.SetMessage (be->u.logmsg.msg);
int n = dlg.ShowModal ();
Boolean dontAsk = dlg.GetDontAsk ();
// turn the return value into the constant that logfunctions::ask is
// expecting. 0=continue, 1=continue but ignore future messages from this
// device, 2=die, 3=dump core, 4=debugger. FIXME: yuck. replace hardcoded
// constants in logfunctions::ask with enum or defined constant.
if (n==0) {
n = dontAsk? 1 : 0;
} else {
n=n+1;
}
be->retcode = n;
wxLogDebug ("you chose %d", n);
// This can be called from two different contexts:
// 1) before sim_thread starts, the default application callback can
// call OnLogMsg to display messages.
// 2) after the sim_thread starts, the sim_thread callback can call
// OnLogMsg to display messages
if (sim_thread)
sim_thread->SendSyncResponse (be); // only for case #2
}
void
MyFrame::OnOtherEvent (wxCommandEvent& event)
{
@ -1331,8 +1405,9 @@ SimThread::OnExit ()
// notify the MyFrame that the bochs thread has died. I can't adjust
// the sim_thread directly because it's private.
frame->OnSimThreadExit ();
// don't use this SimThread's callback function anymore.
SIM->set_notify_callback (NULL, NULL);
// don't use this SimThread's callback function anymore. Use the
// application default callback.
SIM->set_notify_callback (&MyApp::DefaultCallback, this);
}
// Event handler function for BxEvents coming from the simulator.

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////
// $Id: wxmain.h,v 1.30 2002-09-22 20:56:12 cbothamy Exp $
// $Id: wxmain.h,v 1.31 2002-09-25 18:40:15 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.
@ -142,8 +142,6 @@ public:
void OnPaint(wxPaintEvent& event);
void OnMouse(wxMouseEvent& event);
void MyRefresh ();
void ReadConfiguration ();
void SaveConfiguration ();
void ToggleMouse ();
private:
wxCursor *blankCursor;
@ -177,6 +175,7 @@ public:
void OnPauseResumeSim(wxCommandEvent& event);
void OnKillSim(wxCommandEvent& event);
void OnSim2CIEvent(wxCommandEvent& event);
void OnLogMsg(BxEvent *logMsgEvent);
void OnEditBoot(wxCommandEvent& event);
void OnEditMemory(wxCommandEvent& event);
void OnEditSound(wxCommandEvent& event);