1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/base/appbase.cpp 
   3 // Purpose:     implements wxAppConsole class 
   4 // Author:      Vadim Zeitlin 
   6 // Created:     19.06.2003 (extracted from common/appcmn.cpp) 
   8 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org> 
   9 // License:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  35 #include "wx/apptrait.h" 
  36 #include "wx/cmdline.h" 
  37 #include "wx/confbase.h" 
  38 #include "wx/filename.h" 
  39 #include "wx/msgout.h" 
  40 #include "wx/tokenzr.h" 
  42 #if !defined(__WXMSW__) || defined(__WXMICROWIN__) 
  43   #include  <signal.h>      // for SIGTRAP used by wxTrap() 
  46 #if defined(__WXMSW__) 
  47   #include  "wx/msw/wrapwin.h"  // includes windows.h for MessageBox() 
  51     #include "wx/fontmap.h" 
  52 #endif // wxUSE_FONTMAP 
  54 #if defined(__WXMAC__) 
  55     // VZ: MacTypes.h is enough under Mac OS X (where I could test it) but 
  56     //     I don't know which headers are needed under earlier systems so 
  57     //     include everything when in doubt 
  61         #include  "wx/mac/private.h"  // includes mac headers 
  65 // ---------------------------------------------------------------------------- 
  66 // private functions prototypes 
  67 // ---------------------------------------------------------------------------- 
  70     // really just show the assert dialog 
  71     static bool DoShowAssertDialog(const wxString
& msg
); 
  73     // prepare for showing the assert dialog, use the given traits or 
  74     // DoShowAssertDialog() as last fallback to really show it 
  76     void ShowAssertDialog(const wxChar 
*szFile
, 
  80                           wxAppTraits 
*traits 
= NULL
); 
  82     // turn on the trace masks specified in the env variable WXTRACE 
  83     static void LINKAGEMODE 
SetTraceMasks(); 
  86 // ---------------------------------------------------------------------------- 
  88 // ---------------------------------------------------------------------------- 
  90 wxAppConsole 
*wxAppConsole::ms_appInstance 
= NULL
; 
  92 wxAppInitializerFunction 
wxAppConsole::ms_appInitFn 
= NULL
; 
  94 // ============================================================================ 
  95 // wxAppConsole implementation 
  96 // ============================================================================ 
  98 // ---------------------------------------------------------------------------- 
 100 // ---------------------------------------------------------------------------- 
 102 wxAppConsole::wxAppConsole() 
 106     ms_appInstance 
= this; 
 111     // In unicode mode the SetTraceMasks call can cause an apptraits to be 
 112     // created, but since we are still in the constructor the wrong kind will 
 113     // be created for GUI apps.  Destroy it so it can be created again later. 
 120 wxAppConsole::~wxAppConsole() 
 125 // ---------------------------------------------------------------------------- 
 126 // initilization/cleanup 
 127 // ---------------------------------------------------------------------------- 
 129 bool wxAppConsole::Initialize(int& argc
, wxChar 
**argv
) 
 132     // If some code logged something before wxApp instance was created, 
 133     // wxLogStderr was set as the target. Undo it here by destroying the 
 134     // current target. It will be re-created next time logging is needed, but 
 135     // this time wxAppTraits will be used: 
 136     delete wxLog::SetActiveTarget(NULL
); 
 139     // remember the command line arguments 
 143     if ( m_appName
.empty() && argv 
) 
 145         // the application name is, by default, the name of its executable file 
 146         wxFileName::SplitPath(argv
[0], NULL
, &m_appName
, NULL
); 
 152 void wxAppConsole::CleanUp() 
 156 // ---------------------------------------------------------------------------- 
 158 // ---------------------------------------------------------------------------- 
 160 bool wxAppConsole::OnInit() 
 162 #if wxUSE_CMDLINE_PARSER 
 163     wxCmdLineParser 
parser(argc
, argv
); 
 165     OnInitCmdLine(parser
); 
 168     switch ( parser
.Parse(false /* don't show usage */) ) 
 171             cont 
= OnCmdLineHelp(parser
); 
 175             cont 
= OnCmdLineParsed(parser
); 
 179             cont 
= OnCmdLineError(parser
); 
 185 #endif // wxUSE_CMDLINE_PARSER 
 190 int wxAppConsole::OnExit() 
 193     // delete the config object if any (don't use Get() here, but Set() 
 194     // because Get() could create a new config object) 
 195     delete wxConfigBase::Set((wxConfigBase 
*) NULL
); 
 196 #endif // wxUSE_CONFIG 
 198     // use Set(NULL) and not Get() to avoid creating a message output object on 
 199     // demand when we just want to delete it 
 200     delete wxMessageOutput::Set(NULL
); 
 205 void wxAppConsole::Exit() 
 210 // ---------------------------------------------------------------------------- 
 212 // ---------------------------------------------------------------------------- 
 214 wxAppTraits 
*wxAppConsole::CreateTraits() 
 216     return new wxConsoleAppTraits
; 
 219 wxAppTraits 
*wxAppConsole::GetTraits() 
 221     // FIXME-MT: protect this with a CS? 
 224         m_traits 
= CreateTraits(); 
 226         wxASSERT_MSG( m_traits
, _T("wxApp::CreateTraits() failed?") ); 
 232 // we must implement CreateXXX() in wxApp itself for backwards compatibility 
 233 #if WXWIN_COMPATIBILITY_2_4 
 237 wxLog 
*wxAppConsole::CreateLogTarget() 
 239     wxAppTraits 
*traits 
= GetTraits(); 
 240     return traits 
? traits
->CreateLogTarget() : NULL
; 
 245 wxMessageOutput 
*wxAppConsole::CreateMessageOutput() 
 247     wxAppTraits 
*traits 
= GetTraits(); 
 248     return traits 
? traits
->CreateMessageOutput() : NULL
; 
 251 #endif // WXWIN_COMPATIBILITY_2_4 
 253 // ---------------------------------------------------------------------------- 
 255 // ---------------------------------------------------------------------------- 
 257 void wxAppConsole::ProcessPendingEvents() 
 259     // ensure that we're the only thread to modify the pending events list 
 260     wxENTER_CRIT_SECT( *wxPendingEventsLocker 
); 
 262     if ( !wxPendingEvents 
) 
 264         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 268     // iterate until the list becomes empty 
 269     wxList::compatibility_iterator node 
= wxPendingEvents
->GetFirst(); 
 272         wxEvtHandler 
*handler 
= (wxEvtHandler 
*)node
->GetData(); 
 273         wxPendingEvents
->Erase(node
); 
 275         // In ProcessPendingEvents(), new handlers might be add 
 276         // and we can safely leave the critical section here. 
 277         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 278         handler
->ProcessPendingEvents(); 
 279         wxENTER_CRIT_SECT( *wxPendingEventsLocker 
); 
 281         node 
= wxPendingEvents
->GetFirst(); 
 284     wxLEAVE_CRIT_SECT( *wxPendingEventsLocker 
); 
 287 int wxAppConsole::FilterEvent(wxEvent
& WXUNUSED(event
)) 
 289     // process the events normally by default 
 293 // ---------------------------------------------------------------------------- 
 294 // exception handling 
 295 // ---------------------------------------------------------------------------- 
 300 wxAppConsole::HandleEvent(wxEvtHandler 
*handler
, 
 301                           wxEventFunction func
, 
 302                           wxEvent
& event
) const 
 304     // by default, simply call the handler 
 305     (handler
->*func
)(event
); 
 309 wxAppConsole::OnExceptionInMainLoop() 
 313     // some compilers are too stupid to know that we never return after throw 
 314 #if defined(__DMC__) || (defined(_MSC_VER) && _MSC_VER < 1200) 
 319 #endif // wxUSE_EXCEPTIONS 
 321 // ---------------------------------------------------------------------------- 
 323 // ---------------------------------------------------------------------------- 
 325 #if wxUSE_CMDLINE_PARSER 
 327 #define OPTION_VERBOSE _T("verbose") 
 329 void wxAppConsole::OnInitCmdLine(wxCmdLineParser
& parser
) 
 331     // the standard command line options 
 332     static const wxCmdLineEntryDesc cmdLineDesc
[] = 
 338             gettext_noop("show this help message"), 
 340             wxCMD_LINE_OPTION_HELP
 
 348             gettext_noop("generate verbose log messages"), 
 365     parser
.SetDesc(cmdLineDesc
); 
 368 bool wxAppConsole::OnCmdLineParsed(wxCmdLineParser
& parser
) 
 371     if ( parser
.Found(OPTION_VERBOSE
) ) 
 373         wxLog::SetVerbose(true); 
 382 bool wxAppConsole::OnCmdLineHelp(wxCmdLineParser
& parser
) 
 389 bool wxAppConsole::OnCmdLineError(wxCmdLineParser
& parser
) 
 396 #endif // wxUSE_CMDLINE_PARSER 
 398 // ---------------------------------------------------------------------------- 
 400 // ---------------------------------------------------------------------------- 
 403 bool wxAppConsole::CheckBuildOptions(const char *optionsSignature
, 
 404                                      const char *componentName
) 
 406 #if 0 // can't use wxLogTrace, not up and running yet 
 407     printf("checking build options object '%s' (ptr %p) in '%s'\n", 
 408              optionsSignature
, optionsSignature
, componentName
); 
 411     if ( strcmp(optionsSignature
, WX_BUILD_OPTIONS_SIGNATURE
) != 0 ) 
 413         wxString lib 
= wxString::FromAscii(WX_BUILD_OPTIONS_SIGNATURE
); 
 414         wxString prog 
= wxString::FromAscii(optionsSignature
); 
 415         wxString progName 
= wxString::FromAscii(componentName
); 
 418         msg
.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."), 
 419                    lib
.c_str(), progName
.c_str(), prog
.c_str()); 
 421         wxLogFatalError(msg
.c_str()); 
 423         // normally wxLogFatalError doesn't return 
 433 void wxAppConsole::OnAssert(const wxChar 
*file
, 
 438     ShowAssertDialog(file
, line
, cond
, msg
, GetTraits()); 
 441 #endif // __WXDEBUG__ 
 443 // ============================================================================ 
 444 // other classes implementations 
 445 // ============================================================================ 
 447 // ---------------------------------------------------------------------------- 
 448 // wxConsoleAppTraitsBase 
 449 // ---------------------------------------------------------------------------- 
 453 wxLog 
*wxConsoleAppTraitsBase::CreateLogTarget() 
 455     return new wxLogStderr
; 
 460 wxMessageOutput 
*wxConsoleAppTraitsBase::CreateMessageOutput() 
 462     return new wxMessageOutputStderr
; 
 467 wxFontMapper 
*wxConsoleAppTraitsBase::CreateFontMapper() 
 469     return (wxFontMapper 
*)new wxFontMapperBase
; 
 472 #endif // wxUSE_FONTMAP 
 474 wxRendererNative 
*wxConsoleAppTraitsBase::CreateRenderer() 
 476     // console applications don't use renderers 
 481 bool wxConsoleAppTraitsBase::ShowAssertDialog(const wxString
& msg
) 
 483     return wxAppTraitsBase::ShowAssertDialog(msg
); 
 487 bool wxConsoleAppTraitsBase::HasStderr() 
 489     // console applications always have stderr, even under Mac/Windows 
 493 void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject 
*object
) 
 498 void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject 
* WXUNUSED(object
)) 
 504 GSocketGUIFunctionsTable
* wxConsoleAppTraitsBase::GetSocketGUIFunctionsTable() 
 510 // ---------------------------------------------------------------------------- 
 512 // ---------------------------------------------------------------------------- 
 516 bool wxAppTraitsBase::ShowAssertDialog(const wxString
& msg
) 
 518     return DoShowAssertDialog(msg
); 
 521 #endif // __WXDEBUG__ 
 523 // ============================================================================ 
 524 // global functions implementation 
 525 // ============================================================================ 
 535         // what else can we do? 
 544         wxTheApp
->WakeUpIdle(); 
 546     //else: do nothing, what can we do? 
 552 bool wxAssertIsEqual(int x
, int y
) 
 557 // break into the debugger 
 560 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 562 #elif defined(__WXMAC__) && !defined(__DARWIN__) 
 568 #elif defined(__UNIX__) 
 575 void wxAssert(int cond
, 
 576               const wxChar 
*szFile
, 
 578               const wxChar 
*szCond
, 
 582         wxOnAssert(szFile
, nLine
, szCond
, szMsg
); 
 585 // this function is called when an assert fails 
 586 void wxOnAssert(const wxChar 
*szFile
, 
 588                 const wxChar 
*szCond
, 
 592     static bool s_bInAssert 
= false; 
 596         // He-e-e-e-elp!! we're trapped in endless loop 
 608         // by default, show the assert dialog box -- we can't customize this 
 610         ShowAssertDialog(szFile
, nLine
, szCond
, szMsg
); 
 614         // let the app process it as it wants 
 615         wxTheApp
->OnAssert(szFile
, nLine
, szCond
, szMsg
); 
 621 #endif // __WXDEBUG__ 
 623 // ============================================================================ 
 624 // private functions implementation 
 625 // ============================================================================ 
 629 static void LINKAGEMODE 
SetTraceMasks() 
 633     if ( wxGetEnv(wxT("WXTRACE"), &mask
) ) 
 635         wxStringTokenizer 
tkn(mask
, wxT(",;:")); 
 636         while ( tkn
.HasMoreTokens() ) 
 637             wxLog::AddTraceMask(tkn
.GetNextToken()); 
 642 bool DoShowAssertDialog(const wxString
& msg
) 
 644     // under MSW we can show the dialog even in the console mode 
 645 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 646     wxString 
msgDlg(msg
); 
 648     // this message is intentionally not translated -- it is for 
 650     msgDlg 
+= wxT("\nDo you want to stop the program?\n") 
 651               wxT("You can also choose [Cancel] to suppress ") 
 652               wxT("further warnings."); 
 654     switch ( ::MessageBox(NULL
, msgDlg
, _T("wxWidgets Debug Alert"), 
 655                           MB_YESNOCANCEL 
| MB_ICONSTOP 
) ) 
 665         //case IDNO: nothing to do 
 668     wxFprintf(stderr
, wxT("%s\n"), msg
.c_str()); 
 671     // TODO: ask the user to enter "Y" or "N" on the console? 
 673 #endif // __WXMSW__/!__WXMSW__ 
 675     // continue with the asserts 
 679 // show the assert modal dialog 
 681 void ShowAssertDialog(const wxChar 
*szFile
, 
 683                       const wxChar 
*szCond
, 
 687     // this variable can be set to true to suppress "assert failure" messages 
 688     static bool s_bNoAsserts 
= false; 
 693     // make life easier for people using VC++ IDE by using this format: like 
 694     // this, clicking on the message will take us immediately to the place of 
 696     msg
.Printf(wxT("%s(%d): assert \"%s\" failed"), szFile
, nLine
, szCond
); 
 700         msg 
<< _T(": ") << szMsg
; 
 702     else // no message given 
 708     // if we are not in the main thread, output the assert directly and trap 
 709     // since dialogs cannot be displayed 
 710     if ( !wxThread::IsMain() ) 
 712         msg 
+= wxT(" [in child thread]"); 
 714 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 716         OutputDebugString(msg 
); 
 719         wxFprintf(stderr
, wxT("%s\n"), msg
.c_str()); 
 722         // He-e-e-e-elp!! we're asserting in a child thread 
 725 #endif // wxUSE_THREADS 
 729         // send it to the normal log destination 
 730         wxLogDebug(_T("%s"), msg
.c_str()); 
 734             // delegate showing assert dialog (if possible) to that class 
 735             s_bNoAsserts 
= traits
->ShowAssertDialog(msg
); 
 737         else // no traits object 
 739             // fall back to the function of last resort 
 740             s_bNoAsserts 
= DoShowAssertDialog(msg
); 
 745 #endif // __WXDEBUG__