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"
34 #include "wx/ptr_scpd.h"
35 #include "wx/module.h"
37 #if defined(__WXMSW__) && defined(__WXDEBUG__)
38 #include "wx/msw/msvcrt.h"
40 static struct EnableMemLeakChecking
42 EnableMemLeakChecking()
44 // do check for memory leaks on program exit (another useful flag
45 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated
46 // memory which may be used to simulate low-memory condition)
47 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
);
49 } gs_enableLeakChecks
;
50 #endif // __WXMSW__ && __WXDEBUG__
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 // we need a dummy app object if the user doesn't want to create a real one
57 class wxDummyConsoleApp
: public wxAppConsole
60 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
63 // we need a special kind of auto pointer to wxApp which not only deletes the
64 // pointer it holds in its dtor but also resets wxTheApp
65 wxDECLARE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
66 wxDEFINE_SCOPED_PTR(wxApp
, wxAppPtrBase
);
68 class wxAppPtr
: public wxAppPtrBase
71 wxEXPLICIT
wxAppPtr(wxApp
*ptr
= NULL
) : wxAppPtrBase(ptr
) { }
76 // the pointer is going to be deleted in the base class dtor, don't
77 // leave the dangling pointer!
90 // another tiny class which simply exists to ensure that wxEntryCleanup is
95 ~wxCleanupOnExit() { wxEntryCleanup(); }
98 // ----------------------------------------------------------------------------
99 // initialization data
100 // ----------------------------------------------------------------------------
102 static struct InitData
110 // argv = NULL; -- not even really needed
111 #endif // wxUSE_UNICODE
114 // critical section protecting this struct
115 wxCRIT_SECT_DECLARE_MEMBER(csInit
);
117 // number of times wxInitialize() was called minus the number of times
118 // wxUninitialize() was
124 // if we receive the command line arguments as ASCII and have to convert
125 // them to Unicode ourselves (this is the case under Unix but not Windows,
126 // for example), we remember the converted argv here because we'll have to
127 // free it when doing cleanup to avoid memory leaks
129 #endif // wxUSE_UNICODE
132 // ============================================================================
134 // ============================================================================
136 // ----------------------------------------------------------------------------
137 // command line arguments ANSI -> Unicode conversion
138 // ----------------------------------------------------------------------------
142 static void ConvertArgsToUnicode(int argc
, char **argv
)
144 gs_initData
.argv
= new wchar_t *[argc
+ 1];
145 for ( int i
= 0; i
< argc
; i
++ )
147 gs_initData
.argv
[i
] = wxStrdup(wxConvLocal
.cMB2WX(argv
[i
]));
150 gs_initData
.argv
[argc
] = NULL
;
153 static void FreeConvertedArgs()
155 for ( int mb_argc
= 0; mb_argc
< wxTheApp
->argc
; mb_argc
++ )
157 free(wxTheApp
->argv
[mb_argc
]);
161 #endif // wxUSE_UNICODE
163 // ----------------------------------------------------------------------------
165 // ----------------------------------------------------------------------------
167 // initialization which is always done (not customizable) before wxApp creation
168 static bool DoCommonPreInit()
170 wxClassInfo::InitializeClasses();
175 // non customizable initialization done after wxApp creation and initialization
176 static bool DoCommonPostInit()
178 wxModule::RegisterModules();
180 return wxModule::InitializeModules();
183 bool wxEntryStart(int argc
, wxChar
**argv
)
185 // do minimal, always necessary, initialization
186 // --------------------------------------------
189 if ( !DoCommonPreInit() )
195 // first of all, we need an application object
196 // -------------------------------------------
198 // the user might have already created it himself somehow
199 wxAppPtr
app(wxTheApp
);
202 // if not, he might have used IMPLEMENT_APP() to give us a function to
204 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
208 // he did, try to create the custom wxApp object
209 app
.Set((*fnCreate
)());
215 // either IMPLEMENT_APP() was not used at all or it failed -- in any
216 // case we still need something
218 // NB: cast is needed because for the backwards-compatibility reasons
219 // wxTheApp is really a wxApp and not just wxAppConsole...
220 app
.Set((wxApp
*)new wxDummyConsoleApp
);
224 // wxApp initialization: this can be customized
225 // --------------------------------------------
227 if ( !wxTheApp
->Initialize(argc
, argv
) )
233 // common initialization after wxTheApp creation
234 // ---------------------------------------------
236 if ( !DoCommonPostInit() )
242 // prevent the smart pointer from destroying its contents
250 // we provide a wxEntryStart() wrapper taking "char *" pointer too
251 bool wxEntryStart(int argc
, char **argv
)
253 ConvertArgsToUnicode(argc
, argv
);
255 if ( !wxEntryStart(argc
, gs_initData
.argv
) )
265 #endif // wxUSE_UNICODE
267 // ----------------------------------------------------------------------------
269 // ----------------------------------------------------------------------------
271 // cleanup done before destroying wxTheApp
272 static void DoCommonPreCleanup()
275 // flush the logged messages if any and install a 'safer' log target: the
276 // default one (wxLogGui) can't be used after the resources are freed just
277 // below and the user supplied one might be even more unsafe (using any
278 // wxWindows GUI function is unsafe starting from now)
279 wxLog::DontCreateOnDemand();
281 // this will flush the old messages if any
282 delete wxLog::SetActiveTarget(new wxLogStderr
);
285 wxModule::CleanUpModules();
288 // cleanup done after destroying wxTheApp
289 static void DoCommonPostCleanup()
291 wxClassInfo::CleanUpClasses();
293 // we can't do this in wxApp itself because it doesn't know if argv had
297 #endif // wxUSE_UNICODE
300 // and now delete the last logger as well
301 delete wxLog::SetActiveTarget(NULL
);
305 void wxEntryCleanup()
307 DoCommonPreCleanup();
310 // delete the application object
320 DoCommonPostCleanup();
322 // check for memory leaks
323 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
324 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
326 wxLogDebug(wxT("There were memory leaks.\n"));
327 wxDebugContext::Dump();
328 wxDebugContext::PrintStatistics();
334 // ----------------------------------------------------------------------------
336 // ----------------------------------------------------------------------------
338 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
339 #define wxEntryReal wxEntry
340 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
342 int wxEntryReal(int argc
, wxChar
**argv
)
344 // library initialization
345 if ( !wxEntryStart(argc
, argv
) )
350 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
351 // below returns or throws
352 wxCleanupOnExit cleanupOnExit
;
354 // app initialization
355 if ( !wxTheApp
->OnInit() )
357 // don't call OnExit() if OnInit() failed
362 int retValue
= wxTheApp
->OnRun();
364 // why should we do this? it doesn't close all window, just one of them and
365 // this shouldn't be necessary anyhow...
367 // close any remaining windows
368 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
371 // forcibly delete the window.
372 topWindow
->Destroy();
374 // collect the dead objects
375 wxTheApp
->DeletePendingObjects();
385 // wrap real wxEntry in a try-except block to be able to call
386 // OnFatalException() if necessary
387 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION
389 extern unsigned long wxGlobalSEHandler();
391 int wxEntry(int argc
, wxChar
**argv
)
395 return wxEntryReal(argc
, argv
);
397 __except ( wxGlobalSEHandler() )
399 ::ExitProcess(3); // the same exit code as abort()
401 // this code is unreachable but put it here to suppress warnings
406 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
410 // as with wxEntryStart, we provide an ANSI wrapper
411 int wxEntry(int argc
, char **argv
)
413 ConvertArgsToUnicode(argc
, argv
);
415 return wxEntry(argc
, gs_initData
.argv
);
418 #endif // wxUSE_UNICODE
420 // ----------------------------------------------------------------------------
421 // wxInitialize/wxUninitialize
422 // ----------------------------------------------------------------------------
424 bool wxInitialize(int argc
, wxChar
**argv
)
426 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
428 if ( gs_initData
.nInitCount
++ )
430 // already initialized
434 return wxEntryStart(argc
, argv
);
437 void wxUninitialize()
439 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
441 if ( !--gs_initData
.nInitCount
)