1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/init.cpp 
   3 // Purpose:     initialisation for the library 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) Vadim Zeitlin 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #include "wx/wxprec.h" 
  29     #include "wx/filefn.h" 
  31     #include "wx/thread.h" 
  36 #include "wx/ptr_scpd.h" 
  37 #include "wx/module.h" 
  38 #include "wx/except.h" 
  40 #if defined(__WXMSW__) && defined(__WXDEBUG__) 
  41     #include "wx/msw/msvcrt.h" 
  43     static struct EnableMemLeakChecking
 
  45         EnableMemLeakChecking() 
  47             // do check for memory leaks on program exit (another useful flag 
  48             // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated 
  49             // memory which may be used to simulate low-memory condition) 
  50             wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
  52     } gs_enableLeakChecks
; 
  53 #endif // __WXMSW__ && __WXDEBUG__ 
  55 // ---------------------------------------------------------------------------- 
  57 // ---------------------------------------------------------------------------- 
  59 // we need a dummy app object if the user doesn't want to create a real one 
  60 class wxDummyConsoleApp 
: public wxAppConsole
 
  63     wxDummyConsoleApp() { } 
  65     virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; } 
  67     DECLARE_NO_COPY_CLASS(wxDummyConsoleApp
) 
  70 // we need a special kind of auto pointer to wxApp which not only deletes the 
  71 // pointer it holds in its dtor but also resets the global application pointer 
  72 wxDECLARE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
); 
  73 wxDEFINE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
); 
  75 class wxAppPtr 
: public wxAppPtrBase
 
  78     wxEXPLICIT 
wxAppPtr(wxAppConsole 
*ptr 
= NULL
) : wxAppPtrBase(ptr
) { } 
  83             // the pointer is going to be deleted in the base class dtor, don't 
  84             // leave the dangling pointer! 
  85             wxApp::SetInstance(NULL
); 
  89     void Set(wxAppConsole 
*ptr
) 
  93         wxApp::SetInstance(ptr
); 
  96     DECLARE_NO_COPY_CLASS(wxAppPtr
) 
  99 // class to ensure that wxAppBase::CleanUp() is called if our Initialize() 
 101 class wxCallAppCleanup
 
 104     wxCallAppCleanup(wxAppConsole 
*app
) : m_app(app
) { } 
 105     ~wxCallAppCleanup() { if ( m_app 
) m_app
->CleanUp(); } 
 107     void Dismiss() { m_app 
= NULL
; } 
 113 // another tiny class which simply exists to ensure that wxEntryCleanup is 
 115 class wxCleanupOnExit
 
 118     ~wxCleanupOnExit() { wxEntryCleanup(); } 
 121 // ---------------------------------------------------------------------------- 
 123 // ---------------------------------------------------------------------------- 
 125 // suppress warnings about unused variables 
 126 static inline void Use(void *) { } 
 128 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x) 
 130 // ---------------------------------------------------------------------------- 
 131 // initialization data 
 132 // ---------------------------------------------------------------------------- 
 134 static struct InitData
 
 142         // argv = NULL; -- not even really needed 
 143 #endif // wxUSE_UNICODE 
 146     // critical section protecting this struct 
 147     wxCRIT_SECT_DECLARE_MEMBER(csInit
); 
 149     // number of times wxInitialize() was called minus the number of times 
 150     // wxUninitialize() was 
 156     // if we receive the command line arguments as ASCII and have to convert 
 157     // them to Unicode ourselves (this is the case under Unix but not Windows, 
 158     // for example), we remember the converted argv here because we'll have to 
 159     // free it when doing cleanup to avoid memory leaks 
 161 #endif // wxUSE_UNICODE 
 163     DECLARE_NO_COPY_CLASS(InitData
) 
 166 // ============================================================================ 
 168 // ============================================================================ 
 170 // ---------------------------------------------------------------------------- 
 171 // command line arguments ANSI -> Unicode conversion 
 172 // ---------------------------------------------------------------------------- 
 176 static void ConvertArgsToUnicode(int argc
, char **argv
) 
 178     gs_initData
.argv 
= new wchar_t *[argc 
+ 1]; 
 179     for ( int i 
= 0; i 
< argc
; i
++ ) 
 181         gs_initData
.argv
[i
] = wxStrdup(wxConvLocal
.cMB2WX(argv
[i
])); 
 184     gs_initData
.argc 
= argc
; 
 185     gs_initData
.argv
[argc
] = NULL
; 
 188 static void FreeConvertedArgs() 
 190     if ( gs_initData
.argv 
) 
 192         for ( int i 
= 0; i 
< gs_initData
.argc
; i
++ ) 
 194             free(gs_initData
.argv
[i
]); 
 197         delete [] gs_initData
.argv
; 
 198         gs_initData
.argv 
= NULL
; 
 199         gs_initData
.argc 
= 0; 
 203 #endif // wxUSE_UNICODE 
 205 // ---------------------------------------------------------------------------- 
 207 // ---------------------------------------------------------------------------- 
 209 // initialization which is always done (not customizable) before wxApp creation 
 210 static bool DoCommonPreInit() 
 215 // non customizable initialization done after wxApp creation and initialization 
 216 static bool DoCommonPostInit() 
 218     wxModule::RegisterModules(); 
 220     return wxModule::InitializeModules(); 
 223 bool wxEntryStart(int& argc
, wxChar 
**argv
) 
 225     // do minimal, always necessary, initialization 
 226     // -------------------------------------------- 
 229     if ( !DoCommonPreInit() ) 
 235     // first of all, we need an application object 
 236     // ------------------------------------------- 
 238     // the user might have already created it himself somehow 
 239     wxAppPtr 
app(wxTheApp
); 
 242         // if not, he might have used IMPLEMENT_APP() to give us a function to 
 244         wxAppInitializerFunction fnCreate 
= wxApp::GetInitializerFunction(); 
 248             // he did, try to create the custom wxApp object 
 249             app
.Set((*fnCreate
)()); 
 255         // either IMPLEMENT_APP() was not used at all or it failed -- in any 
 256         // case we still need something 
 257         app
.Set(new wxDummyConsoleApp
); 
 261     // wxApp initialization: this can be customized 
 262     // -------------------------------------------- 
 264     if ( !app
->Initialize(argc
, argv
) ) 
 269     wxCallAppCleanup 
callAppCleanup(app
.get()); 
 271     // for compatibility call the old initialization function too 
 272     if ( !app
->OnInitGui() ) 
 276     // common initialization after wxTheApp creation 
 277     // --------------------------------------------- 
 279     if ( !DoCommonPostInit() ) 
 283     // prevent the smart pointer from destroying its contents 
 286     // and the cleanup object from doing cleanup 
 287     callAppCleanup
.Dismiss(); 
 294 // we provide a wxEntryStart() wrapper taking "char *" pointer too 
 295 bool wxEntryStart(int& argc
, char **argv
) 
 297     ConvertArgsToUnicode(argc
, argv
); 
 299     if ( !wxEntryStart(argc
, gs_initData
.argv
) ) 
 309 #endif // wxUSE_UNICODE 
 311 // ---------------------------------------------------------------------------- 
 313 // ---------------------------------------------------------------------------- 
 315 // cleanup done before destroying wxTheApp  
 316 static void DoCommonPreCleanup() 
 319     // flush the logged messages if any and install a 'safer' log target: the 
 320     // default one (wxLogGui) can't be used after the resources are freed just 
 321     // below and the user supplied one might be even more unsafe (using any 
 322     // wxWidgets GUI function is unsafe starting from now) 
 323     wxLog::DontCreateOnDemand(); 
 325     // this will flush the old messages if any 
 326     delete wxLog::SetActiveTarget(new wxLogStderr
); 
 330 // cleanup done after destroying wxTheApp 
 331 static void DoCommonPostCleanup() 
 333     wxModule::CleanUpModules(); 
 335     wxClassInfo::CleanUp(); 
 337     // we can't do this in wxApp itself because it doesn't know if argv had 
 341 #endif // wxUSE_UNICODE 
 343     // Note: check for memory leaks is now done via wxDebugContextDumpDelayCounter 
 345     // and now delete the last logger as well 
 346     delete wxLog::SetActiveTarget(NULL
); 
 350 void wxEntryCleanup() 
 352     DoCommonPreCleanup(); 
 355     // delete the application object 
 361         wxApp::SetInstance(NULL
); 
 365     DoCommonPostCleanup(); 
 368 // ---------------------------------------------------------------------------- 
 370 // ---------------------------------------------------------------------------- 
 372 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION 
 373     #define wxEntryReal wxEntry 
 374 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION) 
 376 int wxEntryReal(int& argc
, wxChar 
**argv
) 
 378     // library initialization 
 379     if ( !wxEntryStart(argc
, argv
) ) 
 384     // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code 
 385     // below returns or throws 
 386     wxCleanupOnExit cleanupOnExit
; 
 388     WX_SUPPRESS_UNUSED_WARN(cleanupOnExit
); 
 393         // app initialization 
 394         if ( !wxTheApp
->CallOnInit() ) 
 396             // don't call OnExit() if OnInit() failed 
 400         // ensure that OnExit() is called if OnInit() had succeeded 
 404             ~CallOnExit() { wxTheApp
->OnExit(); } 
 407         WX_SUPPRESS_UNUSED_WARN(callOnExit
); 
 410         return wxTheApp
->OnRun(); 
 412     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); return -1; ) 
 415 // wrap real wxEntry in a try-except block to be able to call 
 416 // OnFatalException() if necessary 
 417 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION 
 421 #include "wx/msw/private.h" 
 424 extern unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS 
*pExcPtrs
); 
 426 int wxEntry(int& argc
, wxChar 
**argv
) 
 430         return wxEntryReal(argc
, argv
); 
 432     __except ( wxGlobalSEHandler(GetExceptionInformation()) ) 
 435         ::ExitThread(3); // the same exit code as abort() 
 437         ::ExitProcess(3); // the same exit code as abort() 
 440 #if !defined(_MSC_VER) || _MSC_VER < 1300 
 441         // this code is unreachable but put it here to suppress warnings 
 442         // from some compilers 
 448 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION 
 452 // as with wxEntryStart, we provide an ANSI wrapper 
 453 int wxEntry(int& argc
, char **argv
) 
 455     ConvertArgsToUnicode(argc
, argv
); 
 457     return wxEntry(argc
, gs_initData
.argv
); 
 460 #endif // wxUSE_UNICODE 
 462 // ---------------------------------------------------------------------------- 
 463 // wxInitialize/wxUninitialize 
 464 // ---------------------------------------------------------------------------- 
 466 bool wxInitialize(int argc
, wxChar 
**argv
) 
 468     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 470     if ( gs_initData
.nInitCount
++ ) 
 472         // already initialized 
 476     return wxEntryStart(argc
, argv
); 
 479 void wxUninitialize() 
 481     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 483     if ( !--gs_initData
.nInitCount 
)