1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/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" 
  31     #include "wx/module.h" 
  35 #include "wx/thread.h" 
  37 #include "wx/scopedptr.h" 
  38 #include "wx/except.h" 
  40 #if defined(__WINDOWS__) 
  41     #include "wx/msw/private.h" 
  42     #include "wx/msw/msvcrt.h" 
  44     #ifdef wxCrtSetDbgFlag 
  45         static struct EnableMemLeakChecking
 
  47             EnableMemLeakChecking() 
  49                 // check for memory leaks on program exit (another useful flag 
  50                 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated 
  51                 // memory which may be used to simulate low-memory condition) 
  52                 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
  54         } gs_enableLeakChecks
; 
  55     #endif // wxCrtSetDbgFlag 
  58 #if wxUSE_UNICODE && defined(__WXOSX__) 
  62 // ---------------------------------------------------------------------------- 
  64 // ---------------------------------------------------------------------------- 
  66 // we need a dummy app object if the user doesn't want to create a real one 
  67 class wxDummyConsoleApp 
: public wxAppConsole
 
  70     wxDummyConsoleApp() { } 
  72     virtual int OnRun() { wxFAIL_MSG( wxT("unreachable code") ); return 0; } 
  73     virtual bool DoYield(bool, long) { return true; } 
  75     wxDECLARE_NO_COPY_CLASS(wxDummyConsoleApp
); 
  78 // we need a special kind of auto pointer to wxApp which not only deletes the 
  79 // pointer it holds in its dtor but also resets the global application pointer 
  80 wxDECLARE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
) 
  81 wxDEFINE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
) 
  83 class wxAppPtr 
: public wxAppPtrBase
 
  86     wxEXPLICIT 
wxAppPtr(wxAppConsole 
*ptr 
= NULL
) : wxAppPtrBase(ptr
) { } 
  91             // the pointer is going to be deleted in the base class dtor, don't 
  92             // leave the dangling pointer! 
  93             wxApp::SetInstance(NULL
); 
  97     void Set(wxAppConsole 
*ptr
) 
 101         wxApp::SetInstance(ptr
); 
 104     wxDECLARE_NO_COPY_CLASS(wxAppPtr
); 
 107 // class to ensure that wxAppBase::CleanUp() is called if our Initialize() 
 109 class wxCallAppCleanup
 
 112     wxCallAppCleanup(wxAppConsole 
*app
) : m_app(app
) { } 
 113     ~wxCallAppCleanup() { if ( m_app 
) m_app
->CleanUp(); } 
 115     void Dismiss() { m_app 
= NULL
; } 
 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     wxDECLARE_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]; 
 180     for ( int i 
= 0; i 
< argc
; i
++ ) 
 183         wxWCharBuffer 
buf(wxConvFileName
->cMB2WX(argv
[i
])); 
 185         wxWCharBuffer 
buf(wxConvLocal
.cMB2WX(argv
[i
])); 
 189             wxLogWarning(_("Command line argument %d couldn't be converted to Unicode and will be ignored."), 
 194             gs_initData
.argv
[wargc
++] = wxStrdup(buf
); 
 198     gs_initData
.argc 
= wargc
; 
 199     gs_initData
.argv
[wargc
] = NULL
; 
 202 static void FreeConvertedArgs() 
 204     if ( gs_initData
.argv 
) 
 206         for ( int i 
= 0; i 
< gs_initData
.argc
; i
++ ) 
 208             free(gs_initData
.argv
[i
]); 
 211         wxDELETEA(gs_initData
.argv
); 
 212         gs_initData
.argc 
= 0; 
 216 #endif // wxUSE_UNICODE 
 218 // ---------------------------------------------------------------------------- 
 220 // ---------------------------------------------------------------------------- 
 222 // initialization which is always done (not customizable) before wxApp creation 
 223 static bool DoCommonPreInit() 
 225 #if wxUSE_UNICODE && defined(__WXOSX__) 
 226     // In OS X and iOS, wchar_t CRT functions convert to char* and fail under 
 227     // some locales. The safest fix is to set LC_CTYPE to UTF-8 to ensure that 
 228     // they can handle any input. 
 230     // Note that this must be done for any app, Cocoa or console, whether or 
 231     // not it uses wxLocale. 
 233     // See http://stackoverflow.com/questions/11713745/why-does-the-printf-family-of-functions-care-about-locale 
 234     setlocale(LC_CTYPE
, "UTF-8"); 
 235 #endif // wxUSE_UNICODE && defined(__WXOSX__) 
 238     // Reset logging in case we were cleaned up and are being reinitialized. 
 239     wxLog::DoCreateOnDemand(); 
 241     // force wxLog to create a log target now: we do it because wxTheApp 
 242     // doesn't exist yet so wxLog will create a special log target which is 
 243     // safe to use even when the GUI is not available while without this call 
 244     // we could create wxApp in wxEntryStart() below, then log an error about 
 245     // e.g. failure to establish connection to the X server and wxLog would 
 246     // send it to wxLogGui (because wxTheApp does exist already) which, of 
 247     // course, can't be used in this case 
 249     // notice also that this does nothing if the user had set up a custom log 
 250     // target before -- which is fine as we want to give him this possibility 
 251     // (as it's impossible to override logging by overriding wxAppTraits:: 
 252     // CreateLogTarget() before wxApp is created) and we just assume he knows 
 254     wxLog::GetActiveTarget(); 
 258     // GUI applications obtain HINSTANCE in their WinMain() but we also need to 
 259     // initialize the global wxhInstance variable for the console programs as 
 260     // they may need it too, so set it here if it wasn't done yet 
 261     if ( !wxGetInstance() ) 
 263         wxSetInstance(::GetModuleHandle(NULL
)); 
 265 #endif // __WINDOWS__ 
 270 // non customizable initialization done after wxApp creation and initialization 
 271 static bool DoCommonPostInit() 
 273     wxModule::RegisterModules(); 
 275     if ( !wxModule::InitializeModules() ) 
 277         wxLogError(_("Initialization failed in post init, aborting.")); 
 284 bool wxEntryStart(int& argc
, wxChar 
**argv
) 
 286     // do minimal, always necessary, initialization 
 287     // -------------------------------------------- 
 290     if ( !DoCommonPreInit() ) 
 294     // first of all, we need an application object 
 295     // ------------------------------------------- 
 297     // the user might have already created it himself somehow 
 298     wxAppPtr 
app(wxTheApp
); 
 301         // if not, he might have used IMPLEMENT_APP() to give us a function to 
 303         wxAppInitializerFunction fnCreate 
= wxApp::GetInitializerFunction(); 
 307             // he did, try to create the custom wxApp object 
 308             app
.Set((*fnCreate
)()); 
 314         // either IMPLEMENT_APP() was not used at all or it failed -- in any 
 315         // case we still need something 
 316         app
.Set(new wxDummyConsoleApp
); 
 320     // wxApp initialization: this can be customized 
 321     // -------------------------------------------- 
 323     if ( !app
->Initialize(argc
, argv
) ) 
 326     // remember, possibly modified (e.g. due to removal of toolkit-specific 
 327     // parameters), command line arguments in member variables 
 331     wxCallAppCleanup 
callAppCleanup(app
.get()); 
 334     // common initialization after wxTheApp creation 
 335     // --------------------------------------------- 
 337     if ( !DoCommonPostInit() ) 
 341     // prevent the smart pointer from destroying its contents 
 344     // and the cleanup object from doing cleanup 
 345     callAppCleanup
.Dismiss(); 
 348     // now that we have a valid wxApp (wxLogGui would have crashed if we used 
 349     // it before now), we can delete the temporary sink we had created for the 
 350     // initialization messages -- the next time logging function is called, the 
 351     // sink will be recreated but this time wxAppTraits will be used 
 352     delete wxLog::SetActiveTarget(NULL
); 
 360 // we provide a wxEntryStart() wrapper taking "char *" pointer too 
 361 bool wxEntryStart(int& argc
, char **argv
) 
 363     ConvertArgsToUnicode(argc
, argv
); 
 365     if ( !wxEntryStart(gs_initData
.argc
, gs_initData
.argv
) ) 
 375 #endif // wxUSE_UNICODE 
 377 // ---------------------------------------------------------------------------- 
 379 // ---------------------------------------------------------------------------- 
 381 // cleanup done before destroying wxTheApp 
 382 static void DoCommonPreCleanup() 
 385     // flush the logged messages if any and don't use the current probably 
 386     // unsafe log target any more: the default one (wxLogGui) can't be used 
 387     // after the resources are freed which happens when we return and the user 
 388     // supplied one might be even more unsafe (using any wxWidgets GUI function 
 389     // is unsafe starting from now) 
 391     // notice that wxLog will still recreate a default log target if any 
 392     // messages are logged but that one will be safe to use until the very end 
 393     delete wxLog::SetActiveTarget(NULL
); 
 397 // cleanup done after destroying wxTheApp 
 398 static void DoCommonPostCleanup() 
 400     wxModule::CleanUpModules(); 
 402     // we can't do this in wxApp itself because it doesn't know if argv had 
 406 #endif // wxUSE_UNICODE 
 408     // use Set(NULL) and not Get() to avoid creating a message output object on 
 409     // demand when we just want to delete it 
 410     delete wxMessageOutput::Set(NULL
); 
 413     // and now delete the last logger as well 
 415     // we still don't disable log target auto-vivification even if any log 
 416     // objects created now will result in memory leaks because it seems better 
 417     // to leak memory which doesn't matter much considering the application is 
 418     // exiting anyhow than to not show messages which could still be logged 
 419     // from the user code (e.g. static dtors and such) 
 420     delete wxLog::SetActiveTarget(NULL
); 
 424 void wxEntryCleanup() 
 426     DoCommonPreCleanup(); 
 429     // delete the application object 
 434         // reset the global pointer to it to NULL before destroying it as in 
 435         // some circumstances this can result in executing the code using 
 436         // wxTheApp and using half-destroyed object is no good 
 437         wxAppConsole 
* const app 
= wxApp::GetInstance(); 
 438         wxApp::SetInstance(NULL
); 
 443     DoCommonPostCleanup(); 
 446 // ---------------------------------------------------------------------------- 
 448 // ---------------------------------------------------------------------------- 
 450 // for MSW the real wxEntry is defined in msw/main.cpp 
 452     #define wxEntryReal wxEntry 
 453 #endif // !__WINDOWS__ 
 455 int wxEntryReal(int& argc
, wxChar 
**argv
) 
 457     // library initialization 
 458     wxInitializer 
initializer(argc
, argv
); 
 460     if ( !initializer
.IsOk() ) 
 463         // flush any log messages explaining why we failed 
 464         delete wxLog::SetActiveTarget(NULL
); 
 471         // app initialization 
 472         if ( !wxTheApp
->CallOnInit() ) 
 474             // don't call OnExit() if OnInit() failed 
 478         // ensure that OnExit() is called if OnInit() had succeeded 
 482             ~CallOnExit() { wxTheApp
->OnExit(); } 
 485         WX_SUPPRESS_UNUSED_WARN(callOnExit
); 
 488         return wxTheApp
->OnRun(); 
 490     wxCATCH_ALL( wxTheApp
->OnUnhandledException(); return -1; ) 
 495 // as with wxEntryStart, we provide an ANSI wrapper 
 496 int wxEntry(int& argc
, char **argv
) 
 498     ConvertArgsToUnicode(argc
, argv
); 
 500     return wxEntry(gs_initData
.argc
, gs_initData
.argv
); 
 503 #endif // wxUSE_UNICODE 
 505 // ---------------------------------------------------------------------------- 
 506 // wxInitialize/wxUninitialize 
 507 // ---------------------------------------------------------------------------- 
 511     return wxInitialize(0, (wxChar
**)NULL
); 
 514 bool wxInitialize(int argc
, wxChar 
**argv
) 
 516     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 518     if ( gs_initData
.nInitCount
++ ) 
 520         // already initialized 
 524     return wxEntryStart(argc
, argv
); 
 528 bool wxInitialize(int argc
, char **argv
) 
 530     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 532     if ( gs_initData
.nInitCount
++ ) 
 534         // already initialized 
 538     return wxEntryStart(argc
, argv
); 
 540 #endif // wxUSE_UNICODE 
 542 void wxUninitialize() 
 544     wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
); 
 546     if ( --gs_initData
.nInitCount 
== 0 )