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" 
  28     #include "wx/filefn.h" 
  30     #include "wx/thread.h" 
  36 #include "wx/ptr_scpd.h" 
  37 #include "wx/module.h" 
  38 #include "wx/except.h" 
  40 #include "wx/fontmap.h" 
  43 #if defined(__WXMSW__) && defined(__WXDEBUG__) 
  44     #include "wx/msw/msvcrt.h" 
  46     static struct EnableMemLeakChecking
 
  48         EnableMemLeakChecking() 
  50             // do check for memory leaks on program exit (another useful flag 
  51             // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated 
  52             // memory which may be used to simulate low-memory condition) 
  53             wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
  55     } gs_enableLeakChecks
; 
  56 #endif // __WXMSW__ && __WXDEBUG__ 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  62 // we need a dummy app object if the user doesn't want to create a real one 
  63 class wxDummyConsoleApp 
: public wxAppConsole
 
  66     wxDummyConsoleApp() { } 
  68     virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; } 
  70     DECLARE_NO_COPY_CLASS(wxDummyConsoleApp
) 
  73 // we need a special kind of auto pointer to wxApp which not only deletes the 
  74 // pointer it holds in its dtor but also resets the global application pointer 
  75 wxDECLARE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
) 
  76 wxDEFINE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
) 
  78 class wxAppPtr 
: public wxAppPtrBase
 
  81     wxEXPLICIT 
wxAppPtr(wxAppConsole 
*ptr 
= NULL
) : wxAppPtrBase(ptr
) { } 
  86             // the pointer is going to be deleted in the base class dtor, don't 
  87             // leave the dangling pointer! 
  88             wxApp::SetInstance(NULL
); 
  92     void Set(wxAppConsole 
*ptr
) 
  96         wxApp::SetInstance(ptr
); 
  99     DECLARE_NO_COPY_CLASS(wxAppPtr
) 
 102 // class to ensure that wxAppBase::CleanUp() is called if our Initialize() 
 104 class wxCallAppCleanup
 
 107     wxCallAppCleanup(wxAppConsole 
*app
) : m_app(app
) { } 
 108     ~wxCallAppCleanup() { if ( m_app 
) m_app
->CleanUp(); } 
 110     void Dismiss() { m_app 
= NULL
; } 
 116 // another tiny class which simply exists to ensure that wxEntryCleanup is 
 118 class wxCleanupOnExit
 
 121     ~wxCleanupOnExit() { wxEntryCleanup(); } 
 124 // ---------------------------------------------------------------------------- 
 126 // ---------------------------------------------------------------------------- 
 128 // suppress warnings about unused variables 
 129 static inline void Use(void *) { } 
 131 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x) 
 133 // ---------------------------------------------------------------------------- 
 134 // initialization data 
 135 // ---------------------------------------------------------------------------- 
 137 static struct InitData
 
 145         // argv = NULL; -- not even really needed 
 146 #endif // wxUSE_UNICODE 
 149     // critical section protecting this struct 
 150     wxCRIT_SECT_DECLARE_MEMBER(csInit
); 
 152     // number of times wxInitialize() was called minus the number of times 
 153     // wxUninitialize() was 
 159     // if we receive the command line arguments as ASCII and have to convert 
 160     // them to Unicode ourselves (this is the case under Unix but not Windows, 
 161     // for example), we remember the converted argv here because we'll have to 
 162     // free it when doing cleanup to avoid memory leaks 
 164 #endif // wxUSE_UNICODE 
 166     DECLARE_NO_COPY_CLASS(InitData
) 
 169 // ============================================================================ 
 171 // ============================================================================ 
 173 // ---------------------------------------------------------------------------- 
 174 // command line arguments ANSI -> Unicode conversion 
 175 // ---------------------------------------------------------------------------- 
 179 static void ConvertArgsToUnicode(int argc
, char **argv
) 
 181     gs_initData
.argv 
= new wchar_t *[argc 
+ 1]; 
 182     for ( int i 
= 0; i 
< argc
; i
++ ) 
 184         wxWCharBuffer 
buf(wxConvLocal
.cMB2WX(argv
[i
])); 
 185         gs_initData
.argv
[i
] = buf 
? wxStrdup(buf
) : NULL
; 
 188     gs_initData
.argc 
= argc
; 
 189     gs_initData
.argv
[argc
] = NULL
; 
 192 static void FreeConvertedArgs() 
 194     if ( gs_initData
.argv 
) 
 196         for ( int i 
= 0; i 
< gs_initData
.argc
; i
++ ) 
 198             free(gs_initData
.argv
[i
]); 
 201         delete [] gs_initData
.argv
; 
 202         gs_initData
.argv 
= NULL
; 
 203         gs_initData
.argc 
= 0; 
 207 #endif // wxUSE_UNICODE 
 209 // ---------------------------------------------------------------------------- 
 211 // ---------------------------------------------------------------------------- 
 213 // initialization which is always done (not customizable) before wxApp creation 
 214 static bool DoCommonPreInit() 
 217     // install temporary log sink: we can't use wxLogGui before wxApp is 
 218     // constructed and if we use wxLogStderr, all messages during 
 219     // initialization simply disappear under Windows 
 221     // note that we will delete this log target below 
 222     delete wxLog::SetActiveTarget(new wxLogBuffer
); 
 228 // non customizable initialization done after wxApp creation and initialization 
 229 static bool DoCommonPostInit() 
 231     wxModule::RegisterModules(); 
 233     if ( !wxModule::InitializeModules() ) 
 235         wxLogError(_("Initialization failed in post init, aborting.")); 
 242 bool wxEntryStart(int& argc
, wxChar 
**argv
) 
 244     // do minimal, always necessary, initialization 
 245     // -------------------------------------------- 
 248     if ( !DoCommonPreInit() ) 
 254     // first of all, we need an application object 
 255     // ------------------------------------------- 
 257     // the user might have already created it himself somehow 
 258     wxAppPtr 
app(wxTheApp
); 
 261         // if not, he might have used IMPLEMENT_APP() to give us a function to 
 263         wxAppInitializerFunction fnCreate 
= wxApp::GetInitializerFunction(); 
 267             // he did, try to create the custom wxApp object 
 268             app
.Set((*fnCreate
)()); 
 274         // either IMPLEMENT_APP() was not used at all or it failed -- in any 
 275         // case we still need something 
 276         app
.Set(new wxDummyConsoleApp
); 
 280     // wxApp initialization: this can be customized 
 281     // -------------------------------------------- 
 283     if ( !app
->Initialize(argc
, argv
) ) 
 288     wxCallAppCleanup 
callAppCleanup(app
.get()); 
 290     // for compatibility call the old initialization function too 
 291     if ( !app
->OnInitGui() ) 
 295     // common initialization after wxTheApp creation 
 296     // --------------------------------------------- 
 298     if ( !DoCommonPostInit() ) 
 302     // prevent the smart pointer from destroying its contents 
 305     // and the cleanup object from doing cleanup 
 306     callAppCleanup
.Dismiss(); 
 309     // now that we have a valid wxApp (wxLogGui would have crashed if we used 
 310     // it before now), we can delete the temporary sink we had created for the 
 311     // initialization messages -- the next time logging function is called, the 
 312     // sink will be recreated but this time wxAppTraits will be used 
 313     delete wxLog::SetActiveTarget(NULL
); 
 321 // we provide a wxEntryStart() wrapper taking "char *" pointer too 
 322 bool wxEntryStart(int& argc
, char **argv
) 
 324     ConvertArgsToUnicode(argc
, argv
); 
 326     if ( !wxEntryStart(argc
, gs_initData
.argv
) ) 
 336 #endif // wxUSE_UNICODE 
 338 // ---------------------------------------------------------------------------- 
 340 // ---------------------------------------------------------------------------- 
 342 // cleanup done before destroying wxTheApp 
 343 static void DoCommonPreCleanup() 
 346     // flush the logged messages if any and install a 'safer' log target: the 
 347     // default one (wxLogGui) can't be used after the resources are freed just 
 348     // below and the user supplied one might be even more unsafe (using any 
 349     // wxWidgets GUI function is unsafe starting from now) 
 350     wxLog::DontCreateOnDemand(); 
 352     // this will flush the old messages if any 
 353     delete wxLog::SetActiveTarget(new wxLogStderr
); 
 357 // cleanup done after destroying wxTheApp 
 358 static void DoCommonPostCleanup() 
 360     wxModule::CleanUpModules(); 
 362     // we can't do this in wxApp itself because it doesn't know if argv had 
 366 #endif // wxUSE_UNICODE 
 368     // use Set(NULL) and not Get() to avoid creating a message output object on 
 369     // demand when we just want to delete it 
 370     delete wxMessageOutput::Set(NULL
); 
 373     // and now delete the last logger as well 
 374     delete wxLog::SetActiveTarget(NULL
); 
 378 void wxEntryCleanup() 
 380     DoCommonPreCleanup(); 
 383     // delete the application object 
 389         wxApp::SetInstance(NULL
); 
 393     DoCommonPostCleanup(); 
 396 // ---------------------------------------------------------------------------- 
 398 // ---------------------------------------------------------------------------- 
 400 // for MSW the real wxEntry is defined in msw/main.cpp 
 402     #define wxEntryReal wxEntry 
 405 int wxEntryReal(int& argc
, wxChar 
**argv
) 
 407     // library initialization 
 408     if ( !wxEntryStart(argc
, argv
) ) 
 411         // flush any log messages explaining why we failed 
 412         delete wxLog::SetActiveTarget(NULL
); 
 417     // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code 
 418     // below returns or throws 
 419     wxCleanupOnExit cleanupOnExit
; 
 421     WX_SUPPRESS_UNUSED_WARN(cleanupOnExit
); 
 426         // app initialization 
 427         if ( !wxTheApp
->CallOnInit() ) 
 429             // don't call OnExit() if OnInit() failed 
 433         // ensure that OnExit() is called if OnInit() had succeeded 
 437             ~CallOnExit() { wxTheApp
->OnExit(); } 
 440         WX_SUPPRESS_UNUSED_WARN(callOnExit
); 
 443         return wxTheApp
->OnRun(); 
 445     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); return -1; ) 
 450 // as with wxEntryStart, we provide an ANSI wrapper 
 451 int wxEntry(int& argc
, char **argv
) 
 453     ConvertArgsToUnicode(argc
, argv
); 
 456     // If we created a font mapper during the above call, 
 457     // it will only be the base class, so delete it to allow 
 458     // app traits to create mapper. 
 459     delete (wxFontMapperBase
*) wxFontMapperBase::Set(NULL
); 
 462     return wxEntry(argc
, gs_initData
.argv
); 
 465 #endif // wxUSE_UNICODE 
 467 // ---------------------------------------------------------------------------- 
 468 // wxInitialize/wxUninitialize 
 469 // ---------------------------------------------------------------------------- 
 471 bool wxInitialize(int argc
, wxChar 
**argv
) 
 473     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 475     if ( gs_initData
.nInitCount
++ ) 
 477         // already initialized 
 481     return wxEntryStart(argc
, argv
); 
 484 void wxUninitialize() 
 486     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 488     if ( --gs_initData
.nInitCount 
== 0 )