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 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
118 // suppress warnings about unused variables
119 static inline void Use(void *) { }
121 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x)
123 // ----------------------------------------------------------------------------
124 // initialization data
125 // ----------------------------------------------------------------------------
127 static struct InitData
135 // argv = NULL; -- not even really needed
136 #endif // wxUSE_UNICODE
139 // critical section protecting this struct
140 wxCRIT_SECT_DECLARE_MEMBER(csInit
);
142 // number of times wxInitialize() was called minus the number of times
143 // wxUninitialize() was
149 // if we receive the command line arguments as ASCII and have to convert
150 // them to Unicode ourselves (this is the case under Unix but not Windows,
151 // for example), we remember the converted argv here because we'll have to
152 // free it when doing cleanup to avoid memory leaks
154 #endif // wxUSE_UNICODE
157 // ============================================================================
159 // ============================================================================
161 // ----------------------------------------------------------------------------
162 // command line arguments ANSI -> Unicode conversion
163 // ----------------------------------------------------------------------------
167 static void ConvertArgsToUnicode(int argc
, char **argv
)
169 gs_initData
.argv
= new wchar_t *[argc
+ 1];
170 for ( int i
= 0; i
< argc
; i
++ )
172 gs_initData
.argv
[i
] = wxStrdup(wxConvLocal
.cMB2WX(argv
[i
]));
175 gs_initData
.argv
[argc
] = NULL
;
178 static void FreeConvertedArgs()
180 if ( gs_initData
.argv
)
182 for ( int i
= 0; i
< gs_initData
.argc
; i
++ )
184 free(gs_initData
.argv
[i
]);
187 delete [] gs_initData
.argv
;
188 gs_initData
.argv
= NULL
;
192 #endif // wxUSE_UNICODE
194 // ----------------------------------------------------------------------------
196 // ----------------------------------------------------------------------------
198 // initialization which is always done (not customizable) before wxApp creation
199 static bool DoCommonPreInit()
201 wxClassInfo::InitializeClasses();
206 // non customizable initialization done after wxApp creation and initialization
207 static bool DoCommonPostInit()
209 wxModule::RegisterModules();
211 return wxModule::InitializeModules();
214 bool wxEntryStart(int& argc
, wxChar
**argv
)
216 // do minimal, always necessary, initialization
217 // --------------------------------------------
220 if ( !DoCommonPreInit() )
226 // first of all, we need an application object
227 // -------------------------------------------
229 // the user might have already created it himself somehow
230 wxAppPtr
app(wxTheApp
);
233 // if not, he might have used IMPLEMENT_APP() to give us a function to
235 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
239 // he did, try to create the custom wxApp object
240 app
.Set((*fnCreate
)());
246 // either IMPLEMENT_APP() was not used at all or it failed -- in any
247 // case we still need something
249 // NB: cast is needed because for the backwards-compatibility reasons
250 // wxTheApp is really a wxApp and not just wxAppConsole...
251 app
.Set((wxApp
*)new wxDummyConsoleApp
);
255 // wxApp initialization: this can be customized
256 // --------------------------------------------
258 if ( !wxTheApp
->Initialize(argc
, argv
) )
263 wxCallAppCleanup
callAppCleanup(wxTheApp
);
265 // for compatibility call the old initialization function too
266 if ( !wxTheApp
->OnInitGui() )
270 // common initialization after wxTheApp creation
271 // ---------------------------------------------
273 if ( !DoCommonPostInit() )
277 // prevent the smart pointer from destroying its contents
280 // and the cleanup object from doing cleanup
281 callAppCleanup
.Dismiss();
288 // we provide a wxEntryStart() wrapper taking "char *" pointer too
289 bool wxEntryStart(int& argc
, char **argv
)
291 ConvertArgsToUnicode(argc
, argv
);
293 if ( !wxEntryStart(argc
, gs_initData
.argv
) )
303 #endif // wxUSE_UNICODE
305 // ----------------------------------------------------------------------------
307 // ----------------------------------------------------------------------------
309 // cleanup done before destroying wxTheApp
310 static void DoCommonPreCleanup()
313 // flush the logged messages if any and install a 'safer' log target: the
314 // default one (wxLogGui) can't be used after the resources are freed just
315 // below and the user supplied one might be even more unsafe (using any
316 // wxWindows GUI function is unsafe starting from now)
317 wxLog::DontCreateOnDemand();
319 // this will flush the old messages if any
320 delete wxLog::SetActiveTarget(new wxLogStderr
);
323 wxModule::CleanUpModules();
326 // cleanup done after destroying wxTheApp
327 static void DoCommonPostCleanup()
329 wxClassInfo::CleanUpClasses();
331 // we can't do this in wxApp itself because it doesn't know if argv had
335 #endif // wxUSE_UNICODE
338 // and now delete the last logger as well
339 delete wxLog::SetActiveTarget(NULL
);
343 void wxEntryCleanup()
345 DoCommonPreCleanup();
348 // delete the application object
358 DoCommonPostCleanup();
360 // check for memory leaks
361 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
362 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
364 wxLogDebug(wxT("There were memory leaks.\n"));
365 wxDebugContext::Dump();
366 wxDebugContext::PrintStatistics();
372 // ----------------------------------------------------------------------------
374 // ----------------------------------------------------------------------------
376 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
377 #define wxEntryReal wxEntry
378 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
380 int wxEntryReal(int& argc
, wxChar
**argv
)
382 // library initialization
383 if ( !wxEntryStart(argc
, argv
) )
388 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
389 // below returns or throws
390 wxCleanupOnExit cleanupOnExit
;
392 WX_SUPPRESS_UNUSED_WARN(cleanupOnExit
);
394 // app initialization
395 if ( !wxTheApp
->CallOnInit() )
397 // don't call OnExit() if OnInit() failed
402 int retValue
= wxTheApp
->OnRun();
404 // why should we do this? it doesn't close all window, just one of them and
405 // this shouldn't be necessary anyhow...
407 // close any remaining windows
408 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
411 // forcibly delete the window.
412 topWindow
->Destroy();
414 // collect the dead objects
415 wxTheApp
->DeletePendingObjects();
425 // wrap real wxEntry in a try-except block to be able to call
426 // OnFatalException() if necessary
427 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION
429 extern unsigned long wxGlobalSEHandler();
431 int wxEntry(int& argc
, wxChar
**argv
)
435 return wxEntryReal(argc
, argv
);
437 __except ( wxGlobalSEHandler() )
439 ::ExitProcess(3); // the same exit code as abort()
441 // this code is unreachable but put it here to suppress warnings
446 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
450 // as with wxEntryStart, we provide an ANSI wrapper
451 int wxEntry(int& argc
, char **argv
)
453 ConvertArgsToUnicode(argc
, argv
);
455 return wxEntry(argc
, gs_initData
.argv
);
458 #endif // wxUSE_UNICODE
460 // ----------------------------------------------------------------------------
461 // wxInitialize/wxUninitialize
462 // ----------------------------------------------------------------------------
464 bool wxInitialize(int argc
, wxChar
**argv
)
466 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
468 if ( gs_initData
.nInitCount
++ )
470 // already initialized
474 return wxEntryStart(argc
, argv
);
477 void wxUninitialize()
479 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
481 if ( !--gs_initData
.nInitCount
)