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 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
65 // we need a special kind of auto pointer to wxApp which not only deletes the
66 // pointer it holds in its dtor but also resets wxTheApp
67 wxDECLARE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
68 wxDEFINE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
70 class wxAppPtr
: public wxAppPtrBase
73 wxEXPLICIT
wxAppPtr(wxApp
*ptr
= NULL
) : wxAppPtrBase(ptr
) { }
78 // the pointer is going to be deleted in the base class dtor, don't
79 // leave the dangling pointer!
92 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
94 class wxCallAppCleanup
97 wxCallAppCleanup(wxApp
*app
) : m_app(app
) { }
98 ~wxCallAppCleanup() { if ( m_app
) m_app
->CleanUp(); }
100 void Dismiss() { m_app
= NULL
; }
106 // another tiny class which simply exists to ensure that wxEntryCleanup is
108 class wxCleanupOnExit
111 ~wxCleanupOnExit() { wxEntryCleanup(); }
114 // ----------------------------------------------------------------------------
115 // initialization data
116 // ----------------------------------------------------------------------------
118 static struct InitData
126 // argv = NULL; -- not even really needed
127 #endif // wxUSE_UNICODE
130 // critical section protecting this struct
131 wxCRIT_SECT_DECLARE_MEMBER(csInit
);
133 // number of times wxInitialize() was called minus the number of times
134 // wxUninitialize() was
140 // if we receive the command line arguments as ASCII and have to convert
141 // them to Unicode ourselves (this is the case under Unix but not Windows,
142 // for example), we remember the converted argv here because we'll have to
143 // free it when doing cleanup to avoid memory leaks
145 #endif // wxUSE_UNICODE
148 // ============================================================================
150 // ============================================================================
152 // ----------------------------------------------------------------------------
153 // command line arguments ANSI -> Unicode conversion
154 // ----------------------------------------------------------------------------
158 static void ConvertArgsToUnicode(int argc
, char **argv
)
160 gs_initData
.argv
= new wchar_t *[argc
+ 1];
161 for ( int i
= 0; i
< argc
; i
++ )
163 gs_initData
.argv
[i
] = wxStrdup(wxConvLocal
.cMB2WX(argv
[i
]));
166 gs_initData
.argv
[argc
] = NULL
;
169 static void FreeConvertedArgs()
171 if ( gs_initData
.argv
)
173 for ( int i
= 0; i
< gs_initData
.argc
; i
++ )
175 free(gs_initData
.argv
[i
]);
178 delete [] gs_initData
.argv
;
179 gs_initData
.argv
= NULL
;
183 #endif // wxUSE_UNICODE
185 // ----------------------------------------------------------------------------
187 // ----------------------------------------------------------------------------
189 // initialization which is always done (not customizable) before wxApp creation
190 static bool DoCommonPreInit()
192 wxClassInfo::InitializeClasses();
197 // non customizable initialization done after wxApp creation and initialization
198 static bool DoCommonPostInit()
200 wxModule::RegisterModules();
202 return wxModule::InitializeModules();
205 bool wxEntryStart(int& argc
, wxChar
**argv
)
207 // do minimal, always necessary, initialization
208 // --------------------------------------------
211 if ( !DoCommonPreInit() )
217 // first of all, we need an application object
218 // -------------------------------------------
220 // the user might have already created it himself somehow
221 wxAppPtr
app(wxTheApp
);
224 // if not, he might have used IMPLEMENT_APP() to give us a function to
226 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
230 // he did, try to create the custom wxApp object
231 app
.Set((*fnCreate
)());
237 // either IMPLEMENT_APP() was not used at all or it failed -- in any
238 // case we still need something
240 // NB: cast is needed because for the backwards-compatibility reasons
241 // wxTheApp is really a wxApp and not just wxAppConsole...
242 app
.Set((wxApp
*)new wxDummyConsoleApp
);
246 // wxApp initialization: this can be customized
247 // --------------------------------------------
249 if ( !wxTheApp
->Initialize(argc
, argv
) )
254 wxCallAppCleanup
callAppCleanup(wxTheApp
);
256 // for compatibility call the old initialization function too
257 if ( !wxTheApp
->OnInitGui() )
261 // common initialization after wxTheApp creation
262 // ---------------------------------------------
264 if ( !DoCommonPostInit() )
268 // prevent the smart pointer from destroying its contents
271 // and the cleanup object from doing cleanup
272 callAppCleanup
.Dismiss();
279 // we provide a wxEntryStart() wrapper taking "char *" pointer too
280 bool wxEntryStart(int& argc
, char **argv
)
282 ConvertArgsToUnicode(argc
, argv
);
284 if ( !wxEntryStart(argc
, gs_initData
.argv
) )
294 #endif // wxUSE_UNICODE
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
300 // cleanup done before destroying wxTheApp
301 static void DoCommonPreCleanup()
304 // flush the logged messages if any and install a 'safer' log target: the
305 // default one (wxLogGui) can't be used after the resources are freed just
306 // below and the user supplied one might be even more unsafe (using any
307 // wxWindows GUI function is unsafe starting from now)
308 wxLog::DontCreateOnDemand();
310 // this will flush the old messages if any
311 delete wxLog::SetActiveTarget(new wxLogStderr
);
314 wxModule::CleanUpModules();
317 // cleanup done after destroying wxTheApp
318 static void DoCommonPostCleanup()
320 wxClassInfo::CleanUpClasses();
322 // we can't do this in wxApp itself because it doesn't know if argv had
326 #endif // wxUSE_UNICODE
329 // and now delete the last logger as well
330 delete wxLog::SetActiveTarget(NULL
);
334 void wxEntryCleanup()
336 DoCommonPreCleanup();
339 // delete the application object
349 DoCommonPostCleanup();
351 // check for memory leaks
352 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
353 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
355 wxLogDebug(wxT("There were memory leaks.\n"));
356 wxDebugContext::Dump();
357 wxDebugContext::PrintStatistics();
363 // ----------------------------------------------------------------------------
365 // ----------------------------------------------------------------------------
367 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
368 #define wxEntryReal wxEntry
369 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
371 int wxEntryReal(int& argc
, wxChar
**argv
)
373 // library initialization
374 if ( !wxEntryStart(argc
, argv
) )
379 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
380 // below returns or throws
381 wxCleanupOnExit cleanupOnExit
;
383 // app initialization
384 if ( !wxTheApp
->OnInit() )
386 // don't call OnExit() if OnInit() failed
391 int retValue
= wxTheApp
->OnRun();
393 // why should we do this? it doesn't close all window, just one of them and
394 // this shouldn't be necessary anyhow...
396 // close any remaining windows
397 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
400 // forcibly delete the window.
401 topWindow
->Destroy();
403 // collect the dead objects
404 wxTheApp
->DeletePendingObjects();
414 // wrap real wxEntry in a try-except block to be able to call
415 // OnFatalException() if necessary
416 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION
418 extern unsigned long wxGlobalSEHandler();
420 int wxEntry(int& argc
, wxChar
**argv
)
424 return wxEntryReal(argc
, argv
);
426 __except ( wxGlobalSEHandler() )
428 ::ExitProcess(3); // the same exit code as abort()
430 // this code is unreachable but put it here to suppress warnings
435 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
439 // as with wxEntryStart, we provide an ANSI wrapper
440 int wxEntry(int& argc
, char **argv
)
442 ConvertArgsToUnicode(argc
, argv
);
444 return wxEntry(argc
, gs_initData
.argv
);
447 #endif // wxUSE_UNICODE
449 // ----------------------------------------------------------------------------
450 // wxInitialize/wxUninitialize
451 // ----------------------------------------------------------------------------
453 bool wxInitialize(int argc
, wxChar
**argv
)
455 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
457 if ( gs_initData
.nInitCount
++ )
459 // already initialized
463 return wxEntryStart(argc
, argv
);
466 void wxUninitialize()
468 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
470 if ( !--gs_initData
.nInitCount
)