1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/init.cpp
3 // Purpose: initialisation for the library
4 // Author: Vadim Zeitlin
7 // Copyright: (c) Vadim Zeitlin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
27 #include "wx/filefn.h"
30 #include "wx/module.h"
34 #include "wx/thread.h"
36 #include "wx/scopedptr.h"
37 #include "wx/except.h"
39 #if defined(__WINDOWS__)
40 #include "wx/msw/private.h"
41 #include "wx/msw/msvcrt.h"
43 #ifdef wxCrtSetDbgFlag
44 static struct EnableMemLeakChecking
46 EnableMemLeakChecking()
48 // check for memory leaks on program exit (another useful flag
49 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated
50 // memory which may be used to simulate low-memory condition)
51 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
);
53 } gs_enableLeakChecks
;
54 #endif // wxCrtSetDbgFlag
57 #if wxUSE_UNICODE && defined(__WXOSX__)
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 // we need a dummy app object if the user doesn't want to create a real one
66 class wxDummyConsoleApp
: public wxAppConsole
69 wxDummyConsoleApp() { }
71 virtual int OnRun() { wxFAIL_MSG( wxT("unreachable code") ); return 0; }
72 virtual bool DoYield(bool, long) { return true; }
74 wxDECLARE_NO_COPY_CLASS(wxDummyConsoleApp
);
77 // we need a special kind of auto pointer to wxApp which not only deletes the
78 // pointer it holds in its dtor but also resets the global application pointer
79 wxDECLARE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
)
80 wxDEFINE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
)
82 class wxAppPtr
: public wxAppPtrBase
85 wxEXPLICIT
wxAppPtr(wxAppConsole
*ptr
= NULL
) : wxAppPtrBase(ptr
) { }
90 // the pointer is going to be deleted in the base class dtor, don't
91 // leave the dangling pointer!
92 wxApp::SetInstance(NULL
);
96 void Set(wxAppConsole
*ptr
)
100 wxApp::SetInstance(ptr
);
103 wxDECLARE_NO_COPY_CLASS(wxAppPtr
);
106 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
108 class wxCallAppCleanup
111 wxCallAppCleanup(wxAppConsole
*app
) : m_app(app
) { }
112 ~wxCallAppCleanup() { if ( m_app
) m_app
->CleanUp(); }
114 void Dismiss() { m_app
= NULL
; }
120 // ----------------------------------------------------------------------------
122 // ----------------------------------------------------------------------------
124 // suppress warnings about unused variables
125 static inline void Use(void *) { }
127 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x)
129 // ----------------------------------------------------------------------------
130 // initialization data
131 // ----------------------------------------------------------------------------
133 static struct InitData
141 // argv = NULL; -- not even really needed
142 #endif // wxUSE_UNICODE
145 // critical section protecting this struct
146 wxCRIT_SECT_DECLARE_MEMBER(csInit
);
148 // number of times wxInitialize() was called minus the number of times
149 // wxUninitialize() was
155 // if we receive the command line arguments as ASCII and have to convert
156 // them to Unicode ourselves (this is the case under Unix but not Windows,
157 // for example), we remember the converted argv here because we'll have to
158 // free it when doing cleanup to avoid memory leaks
160 #endif // wxUSE_UNICODE
162 wxDECLARE_NO_COPY_CLASS(InitData
);
165 // ============================================================================
167 // ============================================================================
169 // ----------------------------------------------------------------------------
170 // command line arguments ANSI -> Unicode conversion
171 // ----------------------------------------------------------------------------
175 static void ConvertArgsToUnicode(int argc
, char **argv
)
177 gs_initData
.argv
= new wchar_t *[argc
+ 1];
179 for ( int i
= 0; i
< argc
; i
++ )
182 wxWCharBuffer
buf(wxConvFileName
->cMB2WX(argv
[i
]));
184 wxWCharBuffer
buf(wxConvLocal
.cMB2WX(argv
[i
]));
188 wxLogWarning(_("Command line argument %d couldn't be converted to Unicode and will be ignored."),
193 gs_initData
.argv
[wargc
++] = wxStrdup(buf
);
197 gs_initData
.argc
= wargc
;
198 gs_initData
.argv
[wargc
] = NULL
;
201 static void FreeConvertedArgs()
203 if ( gs_initData
.argv
)
205 for ( int i
= 0; i
< gs_initData
.argc
; i
++ )
207 free(gs_initData
.argv
[i
]);
210 wxDELETEA(gs_initData
.argv
);
211 gs_initData
.argc
= 0;
215 #endif // wxUSE_UNICODE
217 // ----------------------------------------------------------------------------
219 // ----------------------------------------------------------------------------
221 // initialization which is always done (not customizable) before wxApp creation
222 static bool DoCommonPreInit()
224 #if wxUSE_UNICODE && defined(__WXOSX__)
225 // In OS X and iOS, wchar_t CRT functions convert to char* and fail under
226 // some locales. The safest fix is to set LC_CTYPE to UTF-8 to ensure that
227 // they can handle any input.
229 // Note that this must be done for any app, Cocoa or console, whether or
230 // not it uses wxLocale.
232 // See http://stackoverflow.com/questions/11713745/why-does-the-printf-family-of-functions-care-about-locale
233 setlocale(LC_CTYPE
, "UTF-8");
234 #endif // wxUSE_UNICODE && defined(__WXOSX__)
237 // Reset logging in case we were cleaned up and are being reinitialized.
238 wxLog::DoCreateOnDemand();
240 // force wxLog to create a log target now: we do it because wxTheApp
241 // doesn't exist yet so wxLog will create a special log target which is
242 // safe to use even when the GUI is not available while without this call
243 // we could create wxApp in wxEntryStart() below, then log an error about
244 // e.g. failure to establish connection to the X server and wxLog would
245 // send it to wxLogGui (because wxTheApp does exist already) which, of
246 // course, can't be used in this case
248 // notice also that this does nothing if the user had set up a custom log
249 // target before -- which is fine as we want to give him this possibility
250 // (as it's impossible to override logging by overriding wxAppTraits::
251 // CreateLogTarget() before wxApp is created) and we just assume he knows
253 wxLog::GetActiveTarget();
257 // GUI applications obtain HINSTANCE in their WinMain() but we also need to
258 // initialize the global wxhInstance variable for the console programs as
259 // they may need it too, so set it here if it wasn't done yet
260 if ( !wxGetInstance() )
262 wxSetInstance(::GetModuleHandle(NULL
));
264 #endif // __WINDOWS__
269 // non customizable initialization done after wxApp creation and initialization
270 static bool DoCommonPostInit()
272 wxModule::RegisterModules();
274 if ( !wxModule::InitializeModules() )
276 wxLogError(_("Initialization failed in post init, aborting."));
283 bool wxEntryStart(int& argc
, wxChar
**argv
)
285 // do minimal, always necessary, initialization
286 // --------------------------------------------
289 if ( !DoCommonPreInit() )
293 // first of all, we need an application object
294 // -------------------------------------------
296 // the user might have already created it himself somehow
297 wxAppPtr
app(wxTheApp
);
300 // if not, he might have used IMPLEMENT_APP() to give us a function to
302 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
306 // he did, try to create the custom wxApp object
307 app
.Set((*fnCreate
)());
313 // either IMPLEMENT_APP() was not used at all or it failed -- in any
314 // case we still need something
315 app
.Set(new wxDummyConsoleApp
);
319 // wxApp initialization: this can be customized
320 // --------------------------------------------
322 if ( !app
->Initialize(argc
, argv
) )
325 // remember, possibly modified (e.g. due to removal of toolkit-specific
326 // parameters), command line arguments in member variables
330 wxCallAppCleanup
callAppCleanup(app
.get());
333 // common initialization after wxTheApp creation
334 // ---------------------------------------------
336 if ( !DoCommonPostInit() )
340 // prevent the smart pointer from destroying its contents
343 // and the cleanup object from doing cleanup
344 callAppCleanup
.Dismiss();
347 // now that we have a valid wxApp (wxLogGui would have crashed if we used
348 // it before now), we can delete the temporary sink we had created for the
349 // initialization messages -- the next time logging function is called, the
350 // sink will be recreated but this time wxAppTraits will be used
351 delete wxLog::SetActiveTarget(NULL
);
359 // we provide a wxEntryStart() wrapper taking "char *" pointer too
360 bool wxEntryStart(int& argc
, char **argv
)
362 ConvertArgsToUnicode(argc
, argv
);
364 if ( !wxEntryStart(gs_initData
.argc
, gs_initData
.argv
) )
374 #endif // wxUSE_UNICODE
376 // ----------------------------------------------------------------------------
378 // ----------------------------------------------------------------------------
380 // cleanup done before destroying wxTheApp
381 static void DoCommonPreCleanup()
384 // flush the logged messages if any and don't use the current probably
385 // unsafe log target any more: the default one (wxLogGui) can't be used
386 // after the resources are freed which happens when we return and the user
387 // supplied one might be even more unsafe (using any wxWidgets GUI function
388 // is unsafe starting from now)
390 // notice that wxLog will still recreate a default log target if any
391 // messages are logged but that one will be safe to use until the very end
392 delete wxLog::SetActiveTarget(NULL
);
396 // cleanup done after destroying wxTheApp
397 static void DoCommonPostCleanup()
399 wxModule::CleanUpModules();
401 // we can't do this in wxApp itself because it doesn't know if argv had
405 #endif // wxUSE_UNICODE
407 // use Set(NULL) and not Get() to avoid creating a message output object on
408 // demand when we just want to delete it
409 delete wxMessageOutput::Set(NULL
);
412 // call this first as it has a side effect: in addition to flushing all
413 // logs for this thread, it also flushes everything logged from other
415 wxLog::FlushActive();
417 // and now delete the last logger as well
419 // we still don't disable log target auto-vivification even if any log
420 // objects created now will result in memory leaks because it seems better
421 // to leak memory which doesn't matter much considering the application is
422 // exiting anyhow than to not show messages which could still be logged
423 // from the user code (e.g. static dtors and such)
424 delete wxLog::SetActiveTarget(NULL
);
428 void wxEntryCleanup()
430 DoCommonPreCleanup();
433 // delete the application object
438 // reset the global pointer to it to NULL before destroying it as in
439 // some circumstances this can result in executing the code using
440 // wxTheApp and using half-destroyed object is no good
441 wxAppConsole
* const app
= wxApp::GetInstance();
442 wxApp::SetInstance(NULL
);
447 DoCommonPostCleanup();
450 // ----------------------------------------------------------------------------
452 // ----------------------------------------------------------------------------
454 // for MSW the real wxEntry is defined in msw/main.cpp
456 #define wxEntryReal wxEntry
457 #endif // !__WINDOWS__
459 int wxEntryReal(int& argc
, wxChar
**argv
)
461 // library initialization
462 wxInitializer
initializer(argc
, argv
);
464 if ( !initializer
.IsOk() )
467 // flush any log messages explaining why we failed
468 delete wxLog::SetActiveTarget(NULL
);
475 #if defined(__WXOSX__) && wxOSX_USE_COCOA_OR_IPHONE
476 // everything done in OnRun using native callbacks
478 // app initialization
479 if ( !wxTheApp
->CallOnInit() )
481 // don't call OnExit() if OnInit() failed
485 // ensure that OnExit() is called if OnInit() had succeeded
489 ~CallOnExit() { wxTheApp
->OnExit(); }
492 WX_SUPPRESS_UNUSED_WARN(callOnExit
);
495 return wxTheApp
->OnRun();
497 wxCATCH_ALL( wxTheApp
->OnUnhandledException(); return -1; )
502 // as with wxEntryStart, we provide an ANSI wrapper
503 int wxEntry(int& argc
, char **argv
)
505 ConvertArgsToUnicode(argc
, argv
);
507 return wxEntry(gs_initData
.argc
, gs_initData
.argv
);
510 #endif // wxUSE_UNICODE
512 // ----------------------------------------------------------------------------
513 // wxInitialize/wxUninitialize
514 // ----------------------------------------------------------------------------
518 return wxInitialize(0, (wxChar
**)NULL
);
521 bool wxInitialize(int argc
, wxChar
**argv
)
523 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
525 if ( gs_initData
.nInitCount
++ )
527 // already initialized
531 return wxEntryStart(argc
, argv
);
535 bool wxInitialize(int argc
, char **argv
)
537 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
539 if ( gs_initData
.nInitCount
++ )
541 // already initialized
545 return wxEntryStart(argc
, argv
);
547 #endif // wxUSE_UNICODE
549 void wxUninitialize()
551 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
553 if ( --gs_initData
.nInitCount
== 0 )