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