]> git.saurik.com Git - wxWidgets.git/blame - src/common/init.cpp
More COMPATIBILITY_2_4 fixes.
[wxWidgets.git] / src / common / init.cpp
CommitLineData
e90c1d2a
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: common/init.cpp
3// Purpose: initialisation for the library
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 04.10.99
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
f4c890fd
JS
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif //__BORLANDC__
25
e87271f3
VZ
26#ifndef WX_PRECOMP
27 #include "wx/app.h"
28 #include "wx/debug.h"
bc385ba9 29 #include "wx/filefn.h"
e2450fa9 30 #include "wx/log.h"
94826170 31 #include "wx/thread.h"
e87271f3 32#endif
e90c1d2a 33
abca8ebf
VZ
34#include "wx/init.h"
35
94826170 36#include "wx/ptr_scpd.h"
51abe921
SC
37#include "wx/module.h"
38
94826170
VZ
39#if defined(__WXMSW__) && defined(__WXDEBUG__)
40 #include "wx/msw/msvcrt.h"
41
42 static struct EnableMemLeakChecking
43 {
44 EnableMemLeakChecking()
45 {
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);
50 }
51 } gs_enableLeakChecks;
52#endif // __WXMSW__ && __WXDEBUG__
53
e90c1d2a
VZ
54// ----------------------------------------------------------------------------
55// private classes
56// ----------------------------------------------------------------------------
57
e2478fde 58// we need a dummy app object if the user doesn't want to create a real one
94826170 59class wxDummyConsoleApp : public wxAppConsole
e90c1d2a
VZ
60{
61public:
e2478fde 62 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
e90c1d2a
VZ
63};
64
94826170
VZ
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
67wxDECLARE_SCOPED_PTR(wxApp, wxAppPtrBase);
68wxDEFINE_SCOPED_PTR(wxApp, wxAppPtrBase);
bc385ba9 69
94826170
VZ
70class wxAppPtr : public wxAppPtrBase
71{
72public:
73 wxEXPLICIT wxAppPtr(wxApp *ptr = NULL) : wxAppPtrBase(ptr) { }
74 ~wxAppPtr()
75 {
76 if ( get() )
77 {
78 // the pointer is going to be deleted in the base class dtor, don't
79 // leave the dangling pointer!
80 wxTheApp = NULL;
81 }
82 }
83
84 void Set(wxApp *ptr)
85 {
86 reset(ptr);
87
88 wxTheApp = ptr;
89 }
90};
91
05e2b077
VZ
92// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
93// fails
94class wxCallAppCleanup
95{
96public:
97 wxCallAppCleanup(wxApp *app) : m_app(app) { }
98 ~wxCallAppCleanup() { if ( m_app ) m_app->CleanUp(); }
99
100 void Dismiss() { m_app = NULL; }
101
102private:
103 wxApp *m_app;
104};
105
94826170
VZ
106// another tiny class which simply exists to ensure that wxEntryCleanup is
107// always called
108class wxCleanupOnExit
109{
110public:
111 ~wxCleanupOnExit() { wxEntryCleanup(); }
112};
bc385ba9 113
005b5298
VZ
114// ----------------------------------------------------------------------------
115// private functions
116// ----------------------------------------------------------------------------
117
118// suppress warnings about unused variables
119static inline void Use(void *) { }
120
121#define WX_SUPPRESS_UNUSED_WARN(x) Use(&x)
122
e90c1d2a 123// ----------------------------------------------------------------------------
94826170 124// initialization data
e90c1d2a
VZ
125// ----------------------------------------------------------------------------
126
94826170
VZ
127static struct InitData
128{
129 InitData()
130 {
131 nInitCount = 0;
132
133#if wxUSE_UNICODE
134 argc = 0;
135 // argv = NULL; -- not even really needed
136#endif // wxUSE_UNICODE
137 }
138
139 // critical section protecting this struct
140 wxCRIT_SECT_DECLARE_MEMBER(csInit);
141
142 // number of times wxInitialize() was called minus the number of times
143 // wxUninitialize() was
144 size_t nInitCount;
145
146#if wxUSE_UNICODE
147 int argc;
148
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
150cb195 153 wchar_t **argv;
94826170
VZ
154#endif // wxUSE_UNICODE
155} gs_initData;
e90c1d2a
VZ
156
157// ============================================================================
158// implementation
159// ============================================================================
160
252a752e 161// ----------------------------------------------------------------------------
94826170 162// command line arguments ANSI -> Unicode conversion
252a752e
VZ
163// ----------------------------------------------------------------------------
164
94826170
VZ
165#if wxUSE_UNICODE
166
167static void ConvertArgsToUnicode(int argc, char **argv)
e90c1d2a 168{
94826170
VZ
169 gs_initData.argv = new wchar_t *[argc + 1];
170 for ( int i = 0; i < argc; i++ )
e90c1d2a 171 {
94826170 172 gs_initData.argv[i] = wxStrdup(wxConvLocal.cMB2WX(argv[i]));
e90c1d2a
VZ
173 }
174
94826170
VZ
175 gs_initData.argv[argc] = NULL;
176}
e90c1d2a 177
94826170
VZ
178static void FreeConvertedArgs()
179{
150cb195 180 if ( gs_initData.argv )
bbfa0322 181 {
150cb195
VZ
182 for ( int i = 0; i < gs_initData.argc; i++ )
183 {
184 free(gs_initData.argv[i]);
185 }
186
187 delete [] gs_initData.argv;
188 gs_initData.argv = NULL;
bbfa0322 189 }
94826170 190}
bbfa0322 191
94826170 192#endif // wxUSE_UNICODE
e90c1d2a 193
94826170
VZ
194// ----------------------------------------------------------------------------
195// start up
196// ----------------------------------------------------------------------------
bbfa0322 197
94826170
VZ
198// initialization which is always done (not customizable) before wxApp creation
199static bool DoCommonPreInit()
200{
201 wxClassInfo::InitializeClasses();
bbfa0322 202
94826170 203 return true;
e90c1d2a
VZ
204}
205
94826170
VZ
206// non customizable initialization done after wxApp creation and initialization
207static bool DoCommonPostInit()
e90c1d2a 208{
94826170
VZ
209 wxModule::RegisterModules();
210
211 return wxModule::InitializeModules();
bc385ba9
VZ
212}
213
05e2b077 214bool wxEntryStart(int& argc, wxChar **argv)
bc385ba9 215{
94826170
VZ
216 // do minimal, always necessary, initialization
217 // --------------------------------------------
218
219 // initialize wxRTTI
220 if ( !DoCommonPreInit() )
bc385ba9 221 {
94826170 222 return false;
bc385ba9
VZ
223 }
224
bc385ba9 225
94826170
VZ
226 // first of all, we need an application object
227 // -------------------------------------------
228
229 // the user might have already created it himself somehow
230 wxAppPtr app(wxTheApp);
231 if ( !app.get() )
232 {
233 // if not, he might have used IMPLEMENT_APP() to give us a function to
234 // create it
bc385ba9
VZ
235 wxAppInitializerFunction fnCreate = wxApp::GetInitializerFunction();
236
94826170
VZ
237 if ( fnCreate )
238 {
239 // he did, try to create the custom wxApp object
240 app.Set((*fnCreate)());
241 }
242 }
243
244 if ( !app.get() )
245 {
246 // either IMPLEMENT_APP() was not used at all or it failed -- in any
247 // case we still need something
248 //
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);
bc385ba9
VZ
252 }
253
bc385ba9 254
94826170
VZ
255 // wxApp initialization: this can be customized
256 // --------------------------------------------
bc385ba9 257
94826170 258 if ( !wxTheApp->Initialize(argc, argv) )
bc385ba9 259 {
94826170 260 return false;
bc385ba9 261 }
bc385ba9 262
05e2b077
VZ
263 wxCallAppCleanup callAppCleanup(wxTheApp);
264
265 // for compatibility call the old initialization function too
266 if ( !wxTheApp->OnInitGui() )
267 return false;
268
bc385ba9 269
94826170
VZ
270 // common initialization after wxTheApp creation
271 // ---------------------------------------------
bc385ba9 272
94826170 273 if ( !DoCommonPostInit() )
94826170 274 return false;
bc385ba9 275
bc385ba9 276
94826170
VZ
277 // prevent the smart pointer from destroying its contents
278 app.release();
279
05e2b077
VZ
280 // and the cleanup object from doing cleanup
281 callAppCleanup.Dismiss();
282
94826170 283 return true;
bc385ba9
VZ
284}
285
94826170 286#if wxUSE_UNICODE
bbfa0322 287
94826170 288// we provide a wxEntryStart() wrapper taking "char *" pointer too
05e2b077 289bool wxEntryStart(int& argc, char **argv)
bc385ba9 290{
94826170 291 ConvertArgsToUnicode(argc, argv);
bc385ba9 292
94826170 293 if ( !wxEntryStart(argc, gs_initData.argv) )
bc385ba9 294 {
94826170
VZ
295 FreeConvertedArgs();
296
297 return false;
e90c1d2a 298 }
bc385ba9 299
94826170 300 return true;
bc385ba9
VZ
301}
302
94826170
VZ
303#endif // wxUSE_UNICODE
304
305// ----------------------------------------------------------------------------
306// clean up
307// ----------------------------------------------------------------------------
308
309// cleanup done before destroying wxTheApp
310static void DoCommonPreCleanup()
bc385ba9
VZ
311{
312#if wxUSE_LOG
94826170
VZ
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)
8a9c2246 317 wxLog::DontCreateOnDemand();
94826170
VZ
318
319 // this will flush the old messages if any
8a9c2246 320 delete wxLog::SetActiveTarget(new wxLogStderr);
bc385ba9
VZ
321#endif // wxUSE_LOG
322
323 wxModule::CleanUpModules();
94826170 324}
bc385ba9 325
94826170
VZ
326// cleanup done after destroying wxTheApp
327static void DoCommonPostCleanup()
328{
bc385ba9
VZ
329 wxClassInfo::CleanUpClasses();
330
94826170
VZ
331 // we can't do this in wxApp itself because it doesn't know if argv had
332 // been allocated
90aaa865 333#if wxUSE_UNICODE
94826170 334 FreeConvertedArgs();
90aaa865
VZ
335#endif // wxUSE_UNICODE
336
8a9c2246
VZ
337#if wxUSE_LOG
338 // and now delete the last logger as well
339 delete wxLog::SetActiveTarget(NULL);
340#endif // wxUSE_LOG
e90c1d2a 341}
e2450fa9 342
94826170
VZ
343void wxEntryCleanup()
344{
345 DoCommonPreCleanup();
346
347
348 // delete the application object
349 if ( wxTheApp )
350 {
351 wxTheApp->CleanUp();
352
353 delete wxTheApp;
354 wxTheApp = NULL;
355 }
356
357
358 DoCommonPostCleanup();
359
360 // check for memory leaks
361#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
362 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
363 {
364 wxLogDebug(wxT("There were memory leaks.\n"));
365 wxDebugContext::Dump();
366 wxDebugContext::PrintStatistics();
367 }
368#endif // Debug
369
370}
371
372// ----------------------------------------------------------------------------
373// wxEntry
374// ----------------------------------------------------------------------------
375
376#if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
377 #define wxEntryReal wxEntry
378#endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
379
05e2b077 380int wxEntryReal(int& argc, wxChar **argv)
94826170
VZ
381{
382 // library initialization
383 if ( !wxEntryStart(argc, argv) )
384 {
385 return -1;
386 }
387
388 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
389 // below returns or throws
390 wxCleanupOnExit cleanupOnExit;
391
005b5298
VZ
392 WX_SUPPRESS_UNUSED_WARN(cleanupOnExit);
393
94826170
VZ
394 // app initialization
395 if ( !wxTheApp->OnInit() )
396 {
397 // don't call OnExit() if OnInit() failed
398 return -1;
399 }
400
401 // app execution
402 int retValue = wxTheApp->OnRun();
403
404 // why should we do this? it doesn't close all window, just one of them and
405 // this shouldn't be necessary anyhow...
406#if 0
407 // close any remaining windows
408 wxWindow *topWindow = wxTheApp->GetTopWindow();
409 if ( topWindow )
410 {
411 // forcibly delete the window.
412 topWindow->Destroy();
413
414 // collect the dead objects
415 wxTheApp->DeletePendingObjects();
416 }
417#endif // 0
418
419 // app clean up
420 wxTheApp->OnExit();
421
422 return retValue;
423}
424
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
428
429extern unsigned long wxGlobalSEHandler();
430
abca8ebf 431int wxEntry(int& argc, wxChar **argv)
94826170
VZ
432{
433 __try
434 {
435 return wxEntryReal(argc, argv);
436 }
437 __except ( wxGlobalSEHandler() )
438 {
439 ::ExitProcess(3); // the same exit code as abort()
440
441 // this code is unreachable but put it here to suppress warnings
442 return -1;
443 }
444}
445
446#endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
447
448#if wxUSE_UNICODE
449
450// as with wxEntryStart, we provide an ANSI wrapper
abca8ebf 451int wxEntry(int& argc, char **argv)
94826170
VZ
452{
453 ConvertArgsToUnicode(argc, argv);
454
455 return wxEntry(argc, gs_initData.argv);
456}
457
458#endif // wxUSE_UNICODE
459
460// ----------------------------------------------------------------------------
461// wxInitialize/wxUninitialize
462// ----------------------------------------------------------------------------
463
464bool wxInitialize(int argc, wxChar **argv)
465{
466 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
467
468 if ( gs_initData.nInitCount++ )
469 {
470 // already initialized
471 return true;
472 }
473
474 return wxEntryStart(argc, argv);
475}
476
477void wxUninitialize()
478{
479 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
480
481 if ( !--gs_initData.nInitCount )
482 {
483 wxEntryCleanup();
484 }
485}
486