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"
39 #if defined(__WXMSW__) && defined(__WXDEBUG__)
40 #include "wx/msw/msvcrt.h"
42 static struct EnableMemLeakChecking
44 EnableMemLeakChecking()
46 // do check for memory leaks on program exit (another useful flag
47 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated
48 // memory which may be used to simulate low-memory condition)
49 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
);
51 } gs_enableLeakChecks
;
52 #endif // __WXMSW__ && __WXDEBUG__
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 // we need a dummy app object if the user doesn't want to create a real one
59 class wxDummyConsoleApp
: public wxAppConsole
62 wxDummyConsoleApp() { }
64 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
66 DECLARE_NO_COPY_CLASS(wxDummyConsoleApp
)
69 // we need a special kind of auto pointer to wxApp which not only deletes the
70 // pointer it holds in its dtor but also resets wxTheApp
71 wxDECLARE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
72 wxDEFINE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
74 class wxAppPtr
: public wxAppPtrBase
77 wxEXPLICIT
wxAppPtr(wxApp
*ptr
= NULL
) : wxAppPtrBase(ptr
) { }
82 // the pointer is going to be deleted in the base class dtor, don't
83 // leave the dangling pointer!
95 DECLARE_NO_COPY_CLASS(wxAppPtr
)
98 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
100 class wxCallAppCleanup
103 wxCallAppCleanup(wxApp
*app
) : m_app(app
) { }
104 ~wxCallAppCleanup() { if ( m_app
) m_app
->CleanUp(); }
106 void Dismiss() { m_app
= NULL
; }
112 // another tiny class which simply exists to ensure that wxEntryCleanup is
114 class wxCleanupOnExit
117 ~wxCleanupOnExit() { wxEntryCleanup(); }
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 DECLARE_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];
178 for ( int i
= 0; i
< argc
; i
++ )
180 gs_initData
.argv
[i
] = wxStrdup(wxConvLocal
.cMB2WX(argv
[i
]));
183 gs_initData
.argv
[argc
] = NULL
;
186 static void FreeConvertedArgs()
188 if ( gs_initData
.argv
)
190 for ( int i
= 0; i
< gs_initData
.argc
; i
++ )
192 free(gs_initData
.argv
[i
]);
195 delete [] gs_initData
.argv
;
196 gs_initData
.argv
= NULL
;
200 #endif // wxUSE_UNICODE
202 // ----------------------------------------------------------------------------
204 // ----------------------------------------------------------------------------
206 // initialization which is always done (not customizable) before wxApp creation
207 static bool DoCommonPreInit()
209 wxClassInfo::InitializeClasses();
214 // non customizable initialization done after wxApp creation and initialization
215 static bool DoCommonPostInit()
217 wxModule::RegisterModules();
219 return wxModule::InitializeModules();
222 bool wxEntryStart(int& argc
, wxChar
**argv
)
224 // do minimal, always necessary, initialization
225 // --------------------------------------------
228 if ( !DoCommonPreInit() )
234 // first of all, we need an application object
235 // -------------------------------------------
237 // the user might have already created it himself somehow
238 wxAppPtr
app(wxTheApp
);
241 // if not, he might have used IMPLEMENT_APP() to give us a function to
243 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
247 // he did, try to create the custom wxApp object
249 // NB: cast is needed because for the backwards-compatibility
250 // reasons wxTheApp is really a wxApp and not just
252 app
.Set((wxApp
*)(*fnCreate
)());
258 // either IMPLEMENT_APP() was not used at all or it failed -- in any
259 // case we still need something
261 // NB: cast is needed because for the backwards-compatibility reasons
262 // wxTheApp is really a wxApp and not just wxAppConsole...
263 app
.Set((wxApp
*)new wxDummyConsoleApp
);
267 // wxApp initialization: this can be customized
268 // --------------------------------------------
270 if ( !wxTheApp
->Initialize(argc
, argv
) )
275 wxCallAppCleanup
callAppCleanup(wxTheApp
);
277 // for compatibility call the old initialization function too
278 if ( !wxTheApp
->OnInitGui() )
282 // common initialization after wxTheApp creation
283 // ---------------------------------------------
285 if ( !DoCommonPostInit() )
289 // prevent the smart pointer from destroying its contents
292 // and the cleanup object from doing cleanup
293 callAppCleanup
.Dismiss();
300 // we provide a wxEntryStart() wrapper taking "char *" pointer too
301 bool wxEntryStart(int& argc
, char **argv
)
303 ConvertArgsToUnicode(argc
, argv
);
305 if ( !wxEntryStart(argc
, gs_initData
.argv
) )
315 #endif // wxUSE_UNICODE
317 // ----------------------------------------------------------------------------
319 // ----------------------------------------------------------------------------
321 // cleanup done before destroying wxTheApp
322 static void DoCommonPreCleanup()
325 // flush the logged messages if any and install a 'safer' log target: the
326 // default one (wxLogGui) can't be used after the resources are freed just
327 // below and the user supplied one might be even more unsafe (using any
328 // wxWindows GUI function is unsafe starting from now)
329 wxLog::DontCreateOnDemand();
331 // this will flush the old messages if any
332 delete wxLog::SetActiveTarget(new wxLogStderr
);
335 wxModule::CleanUpModules();
338 // cleanup done after destroying wxTheApp
339 static void DoCommonPostCleanup()
341 wxClassInfo::CleanUpClasses();
343 // we can't do this in wxApp itself because it doesn't know if argv had
347 #endif // wxUSE_UNICODE
350 // and now delete the last logger as well
351 delete wxLog::SetActiveTarget(NULL
);
355 void wxEntryCleanup()
357 DoCommonPreCleanup();
360 // delete the application object
370 DoCommonPostCleanup();
372 // check for memory leaks
373 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
374 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
376 wxLogDebug(wxT("There were memory leaks.\n"));
377 wxDebugContext::Dump();
378 wxDebugContext::PrintStatistics();
384 // ----------------------------------------------------------------------------
386 // ----------------------------------------------------------------------------
388 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
389 #define wxEntryReal wxEntry
390 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
392 int wxEntryReal(int& argc
, wxChar
**argv
)
394 // library initialization
395 if ( !wxEntryStart(argc
, argv
) )
400 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
401 // below returns or throws
402 wxCleanupOnExit cleanupOnExit
;
404 WX_SUPPRESS_UNUSED_WARN(cleanupOnExit
);
406 // app initialization
407 if ( !wxTheApp
->CallOnInit() )
409 // don't call OnExit() if OnInit() failed
414 int retValue
= wxTheApp
->OnRun();
422 // wrap real wxEntry in a try-except block to be able to call
423 // OnFatalException() if necessary
424 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION
428 #include "wx/msw/private.h"
431 extern unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS
*pExcPtrs
);
433 int wxEntry(int& argc
, wxChar
**argv
)
437 return wxEntryReal(argc
, argv
);
439 __except ( wxGlobalSEHandler(GetExceptionInformation()) )
442 ::ExitThread(3); // the same exit code as abort()
444 ::ExitProcess(3); // the same exit code as abort()
447 #if !defined(_MSC_VER) || _MSC_VER < 1300
448 // this code is unreachable but put it here to suppress warnings
449 // from some compilers
455 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
459 // as with wxEntryStart, we provide an ANSI wrapper
460 int wxEntry(int& argc
, char **argv
)
462 ConvertArgsToUnicode(argc
, argv
);
464 return wxEntry(argc
, gs_initData
.argv
);
467 #endif // wxUSE_UNICODE
469 // ----------------------------------------------------------------------------
470 // wxInitialize/wxUninitialize
471 // ----------------------------------------------------------------------------
473 bool wxInitialize(int argc
, wxChar
**argv
)
475 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
477 if ( gs_initData
.nInitCount
++ )
479 // already initialized
483 return wxEntryStart(argc
, argv
);
486 void wxUninitialize()
488 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
490 if ( !--gs_initData
.nInitCount
)