1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/appcmn.cpp 
   3 // Purpose:     wxAppBase methods common to all platforms 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) Vadim Zeitlin 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "appbase.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #if defined(__BORLANDC__) 
  39         #include "wx/msgdlg.h" 
  43 #include "wx/cmdline.h" 
  44 #include "wx/thread.h" 
  45 #include "wx/confbase.h" 
  46 #include "wx/tokenzr.h" 
  48 #include "wx/msgout.h" 
  51     #include "wx/artprov.h" 
  54 #if !defined(__WXMSW__) || defined(__WXMICROWIN__) 
  55   #include  <signal.h>      // for SIGTRAP used by wxTrap() 
  58 #if defined(__WXMSW__) 
  59   #include  "wx/msw/private.h"  // includes windows.h for MessageBox() 
  62 #if defined(__WXMAC__) 
  63   #include  "wx/mac/private.h"  // includes mac headers 
  66 // private functions prototypes 
  68     static void LINKAGEMODE 
SetTraceMasks(); 
  71 // =========================================================================== 
  73 // =========================================================================== 
  75 // ---------------------------------------------------------------------------- 
  76 // initialization and termination 
  77 // ---------------------------------------------------------------------------- 
  79 wxAppBase::wxAppBase() 
  81     wxTheApp 
= (wxApp 
*)this; 
  83 #if WXWIN_COMPATIBILITY_2_2 
  84     m_wantDebugOutput 
= FALSE
; 
  85 #endif // WXWIN_COMPATIBILITY_2_2 
  88     m_topWindow 
= (wxWindow 
*)NULL
; 
  89     m_useBestVisual 
= FALSE
; 
  92     // We don't want to exit the app if the user code shows a dialog from its 
  93     // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete 
  94     // to Yes initially as this dialog would be the last top level window. 
  95     // OTOH, if we set it to No initially we'll have to overwrite it with Yes 
  96     // when we enter our OnRun() because we do want the default behaviour from 
  97     // then on. But this would be a problem if the user code calls 
  98     // SetExitOnFrameDelete(FALSE) from OnInit(). 
 100     // So we use the special "Later" value which is such that 
 101     // GetExitOnFrameDelete() returns FALSE for it but which we know we can 
 102     // safely (i.e. without losing the effect of the users SetExitOnFrameDelete 
 103     // call) overwrite in OnRun() 
 104     m_exitOnFrameDelete 
= Later
; 
 112 wxAppBase::~wxAppBase() 
 114     // this destructor is required for Darwin 
 119 bool wxAppBase::OnInitGui() 
 121 #ifdef __WXUNIVERSAL__ 
 122     if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) 
 124 #endif // __WXUNIVERSAL__ 
 129 int wxAppBase::OnRun() 
 131     // see the comment in ctor: if the initial value hasn't been changed, use 
 132     // the default Yes from now on 
 133     if ( m_exitOnFrameDelete 
== Later 
) 
 135         m_exitOnFrameDelete 
= Yes
; 
 137     //else: it has been changed, assume the user knows what he is doing 
 144 int wxAppBase::OnExit() 
 147     // delete the config object if any (don't use Get() here, but Set() 
 148     // because Get() could create a new config object) 
 149     delete wxConfigBase::Set((wxConfigBase 
*) NULL
); 
 150 #endif // wxUSE_CONFIG 
 152 #ifdef __WXUNIVERSAL__ 
 153     delete wxTheme::Set(NULL
); 
 154 #endif // __WXUNIVERSAL__ 
 156     // use Set(NULL) and not Get() to avoid creating a message output object on 
 157     // demand when we just want to delete it 
 158     delete wxMessageOutput::Set(NULL
); 
 163 // ---------------------------------------------------------------------------- 
 164 // customization hooks 
 165 // ---------------------------------------------------------------------------- 
 169 wxLog 
*wxAppBase::CreateLogTarget() 
 171 #if wxUSE_GUI && wxUSE_LOGGUI && !defined(__WXMICROWIN__) 
 174     return new wxLogStderr
; 
 180 wxMessageOutput 
*wxAppBase::CreateMessageOutput() 
 182     // The standard way of printing help on command line arguments (app --help) 
 183     // is (according to common practice): 
 184     //     - console apps: to stderr (on any platform) 
 185     //     - GUI apps: stderr on Unix platforms (!) 
 186     //                 message box under Windows and others 
 187 #if wxUSE_GUI && !defined(__UNIX__) 
 188     // wxMessageOutputMessageBox doesn't work under Motif 
 190         return new wxMessageOutputLog
; 
 192         return new wxMessageOutputMessageBox
; 
 194 #else // !wxUSE_GUI || __UNIX__ 
 195     return new wxMessageOutputStderr
; 
 199 // --------------------------------------------------------------------------- 
 201 // ---------------------------------------------------------------------------- 
 203 void wxAppBase::ProcessPendingEvents() 
 205     // ensure that we're the only thread to modify the pending events list 
 206     wxENTER_CRIT_SECT( *wxPendingEventsLocker 
); 
 208     if ( !wxPendingEvents 
) 
 210         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 214     // iterate until the list becomes empty 
 215     wxNode 
*node 
= wxPendingEvents
->First(); 
 218         wxEvtHandler 
*handler 
= (wxEvtHandler 
*)node
->Data(); 
 221         // In ProcessPendingEvents(), new handlers might be add 
 222         // and we can safely leave the critical section here. 
 223         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 224         handler
->ProcessPendingEvents(); 
 225         wxENTER_CRIT_SECT( *wxPendingEventsLocker 
); 
 227         node 
= wxPendingEvents
->First(); 
 230     wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 233 // ---------------------------------------------------------------------------- 
 235 // ---------------------------------------------------------------------------- 
 239 void wxAppBase::SetActive(bool active
, wxWindow 
* WXUNUSED(lastFocus
)) 
 241     if ( active 
== m_isActive 
) 
 246     wxActivateEvent 
event(wxEVT_ACTIVATE_APP
, active
); 
 247     event
.SetEventObject(this); 
 249     (void)ProcessEvent(event
); 
 254 int wxAppBase::FilterEvent(wxEvent
& WXUNUSED(event
)) 
 256     // process the events normally by default 
 260 // ---------------------------------------------------------------------------- 
 262 // ---------------------------------------------------------------------------- 
 264 bool wxAppBase::OnInit() 
 266 #if wxUSE_CMDLINE_PARSER 
 267     wxCmdLineParser 
parser(argc
, argv
); 
 269     OnInitCmdLine(parser
); 
 272     switch ( parser
.Parse(FALSE 
/* don't show usage */) ) 
 275             cont 
= OnCmdLineHelp(parser
); 
 279             cont 
= OnCmdLineParsed(parser
); 
 283             cont 
= OnCmdLineError(parser
); 
 289 #endif // wxUSE_CMDLINE_PARSER 
 294 #if wxUSE_CMDLINE_PARSER 
 296 #define OPTION_VERBOSE _T("verbose") 
 297 #define OPTION_THEME   _T("theme") 
 298 #define OPTION_MODE    _T("mode") 
 300 void wxAppBase::OnInitCmdLine(wxCmdLineParser
& parser
) 
 302     // the standard command line options 
 303     static const wxCmdLineEntryDesc cmdLineDesc
[] = 
 309             gettext_noop("show this help message"), 
 311             wxCMD_LINE_OPTION_HELP
 
 319             gettext_noop("generate verbose log messages"), 
 325 #ifdef __WXUNIVERSAL__ 
 330             gettext_noop("specify the theme to use"), 
 331             wxCMD_LINE_VAL_STRING
, 
 334 #endif // __WXUNIVERSAL__ 
 336 #if defined(__WXMGL__) 
 337         // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports 
 338         //     should provide this option. That's why it is in common/appcmn.cpp 
 339         //     and not mgl/app.cpp 
 344             gettext_noop("specify display mode to use (e.g. 640x480-16)"), 
 345             wxCMD_LINE_VAL_STRING
, 
 361     parser
.SetDesc(cmdLineDesc
); 
 364 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser
& parser
) 
 367     if ( parser
.Found(OPTION_VERBOSE
) ) 
 369         wxLog::SetVerbose(TRUE
); 
 373 #ifdef __WXUNIVERSAL__ 
 375     if ( parser
.Found(OPTION_THEME
, &themeName
) ) 
 377         wxTheme 
*theme 
= wxTheme::Create(themeName
); 
 380             wxLogError(_("Unsupported theme '%s'."), themeName
.c_str()); 
 385         // Delete the defaultly created theme and set the new theme. 
 386         delete wxTheme::Get(); 
 389 #endif // __WXUNIVERSAL__ 
 391 #if defined(__WXMGL__) 
 393     if ( parser
.Found(OPTION_MODE
, &modeDesc
) ) 
 396         if ( wxSscanf(modeDesc
.c_str(), _T("%ux%u-%u"), &w
, &h
, &bpp
) != 3 ) 
 398             wxLogError(_("Invalid display mode specification '%s'."), modeDesc
.c_str()); 
 403         if ( !SetDisplayMode(wxDisplayModeInfo(w
, h
, bpp
)) ) 
 411 bool wxAppBase::OnCmdLineHelp(wxCmdLineParser
& parser
) 
 418 bool wxAppBase::OnCmdLineError(wxCmdLineParser
& parser
) 
 425 #endif // wxUSE_CMDLINE_PARSER 
 427 // ---------------------------------------------------------------------------- 
 429 // ---------------------------------------------------------------------------- 
 432 bool wxAppBase::CheckBuildOptions(const wxBuildOptions
& opts
) 
 434 #define wxCMP(what)   (what == opts.m_ ## what) 
 443     int verMaj 
= wxMAJOR_VERSION
, 
 444         verMin 
= wxMINOR_VERSION
; 
 446     if ( !(wxCMP(isDebug
) && wxCMP(verMaj
) && wxCMP(verMin
)) ) 
 449         wxString libDebug
, progDebug
; 
 452             libDebug 
= wxT("debug"); 
 454             libDebug 
= wxT("no debug"); 
 457             progDebug 
= wxT("debug"); 
 459             progDebug 
= wxT("no debug"); 
 461         msg
.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %d.%d (%s), and your program used %d.%d (%s)."), 
 462                    verMaj
, verMin
, libDebug
.c_str(), opts
.m_verMaj
, opts
.m_verMin
, progDebug
.c_str()); 
 464         wxLogFatalError(msg
); 
 466         // normally wxLogFatalError doesn't return 
 476 static void LINKAGEMODE 
SetTraceMasks() 
 480     if ( wxGetEnv(wxT("WXTRACE"), &mask
) ) 
 482         wxStringTokenizer 
tkn(mask
, wxT(",")); 
 483         while ( tkn
.HasMoreTokens() ) 
 484             wxLog::AddTraceMask(tkn
.GetNextToken()); 
 490 bool wxAssertIsEqual(int x
, int y
) 
 495 // break into the debugger 
 498 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 500 #elif defined(__WXMAC__) && !defined(__DARWIN__) 
 506 #elif defined(__UNIX__) 
 514 void wxAssert(int cond
, 
 515                   const wxChar 
*szFile
, 
 517                   const wxChar 
*szCond
, 
 521           wxOnAssert(szFile
, nLine
, szCond
, szMsg
); 
 524 // show the assert modal dialog 
 526 void ShowAssertDialog(const wxChar 
*szFile
, 
 528                       const wxChar 
*szCond
, 
 531     // this variable can be set to true to suppress "assert failure" messages 
 532     static bool s_bNoAsserts 
= FALSE
; 
 536     // make life easier for people using VC++ IDE by using this format: like 
 537     // this, clicking on the message will take us immediately to the place of 
 539     wxSnprintf(szBuf
, WXSIZEOF(szBuf
), 
 540                wxT("%s(%d): assert \"%s\" failed"), 
 541                szFile
, nLine
, szCond
); 
 545         wxStrcat(szBuf
, wxT(": ")); 
 546         wxStrcat(szBuf
, szMsg
); 
 548     else // no message given 
 550         wxStrcat(szBuf
, wxT(".")); 
 555         // send it to the normal log destination 
 558 #if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__) 
 559         // this message is intentionally not translated - it is for 
 561         wxStrcat(szBuf
, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings.")); 
 563         // use the native message box if available: this is more robust than 
 565 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 566         switch ( ::MessageBox(NULL
, szBuf
, _T("Debug"), 
 567                               MB_YESNOCANCEL 
| MB_ICONSTOP 
) ) 
 577             //case IDNO: nothing to do 
 580         switch ( wxMessageBox(szBuf
, wxT("Debug"), 
 581                               wxYES_NO 
| wxCANCEL 
| wxICON_STOP 
) ) 
 591             //case wxNO: nothing to do 
 601 // this function is called when an assert fails 
 602 void wxOnAssert(const wxChar 
*szFile
, 
 604                 const wxChar 
*szCond
, 
 608     static bool s_bInAssert 
= FALSE
; 
 612         // He-e-e-e-elp!! we're trapped in endless loop 
 624         // by default, show the assert dialog box - we can't customize this 
 626         ShowAssertDialog(szFile
, nLine
, szCond
, szMsg
); 
 630         // let the app process it as it wants 
 631         wxTheApp
->OnAssert(szFile
, nLine
, szCond
, szMsg
); 
 637 void wxAppBase::OnAssert(const wxChar 
*file
, 
 642     ShowAssertDialog(file
, line
, cond
, msg
);