If a base font mapper object was created prematurely before the traints
[wxWidgets.git] / src / common / init.cpp
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
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif //__BORLANDC__
25
26 #ifndef WX_PRECOMP
27 #include "wx/app.h"
28 #include "wx/filefn.h"
29 #include "wx/log.h"
30 #include "wx/thread.h"
31 #include "wx/intl.h"
32 #endif
33
34 #include "wx/init.h"
35
36 #include "wx/ptr_scpd.h"
37 #include "wx/module.h"
38 #include "wx/except.h"
39 #if wxUSE_FONTMAP
40 #include "wx/fontmap.h"
41 #endif
42
43 #if defined(__WXMSW__) && defined(__WXDEBUG__)
44 #include "wx/msw/msvcrt.h"
45
46 static struct EnableMemLeakChecking
47 {
48 EnableMemLeakChecking()
49 {
50 // do check for memory leaks on program exit (another useful flag
51 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated
52 // memory which may be used to simulate low-memory condition)
53 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
54 }
55 } gs_enableLeakChecks;
56 #endif // __WXMSW__ && __WXDEBUG__
57
58 // ----------------------------------------------------------------------------
59 // private classes
60 // ----------------------------------------------------------------------------
61
62 // we need a dummy app object if the user doesn't want to create a real one
63 class wxDummyConsoleApp : public wxAppConsole
64 {
65 public:
66 wxDummyConsoleApp() { }
67
68 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
69
70 DECLARE_NO_COPY_CLASS(wxDummyConsoleApp)
71 };
72
73 // we need a special kind of auto pointer to wxApp which not only deletes the
74 // pointer it holds in its dtor but also resets the global application pointer
75 wxDECLARE_SCOPED_PTR(wxAppConsole, wxAppPtrBase)
76 wxDEFINE_SCOPED_PTR(wxAppConsole, wxAppPtrBase)
77
78 class wxAppPtr : public wxAppPtrBase
79 {
80 public:
81 wxEXPLICIT wxAppPtr(wxAppConsole *ptr = NULL) : wxAppPtrBase(ptr) { }
82 ~wxAppPtr()
83 {
84 if ( get() )
85 {
86 // the pointer is going to be deleted in the base class dtor, don't
87 // leave the dangling pointer!
88 wxApp::SetInstance(NULL);
89 }
90 }
91
92 void Set(wxAppConsole *ptr)
93 {
94 reset(ptr);
95
96 wxApp::SetInstance(ptr);
97 }
98
99 DECLARE_NO_COPY_CLASS(wxAppPtr)
100 };
101
102 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
103 // fails
104 class wxCallAppCleanup
105 {
106 public:
107 wxCallAppCleanup(wxAppConsole *app) : m_app(app) { }
108 ~wxCallAppCleanup() { if ( m_app ) m_app->CleanUp(); }
109
110 void Dismiss() { m_app = NULL; }
111
112 private:
113 wxAppConsole *m_app;
114 };
115
116 // another tiny class which simply exists to ensure that wxEntryCleanup is
117 // always called
118 class wxCleanupOnExit
119 {
120 public:
121 ~wxCleanupOnExit() { wxEntryCleanup(); }
122 };
123
124 // ----------------------------------------------------------------------------
125 // private functions
126 // ----------------------------------------------------------------------------
127
128 // suppress warnings about unused variables
129 static inline void Use(void *) { }
130
131 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x)
132
133 // ----------------------------------------------------------------------------
134 // initialization data
135 // ----------------------------------------------------------------------------
136
137 static struct InitData
138 {
139 InitData()
140 {
141 nInitCount = 0;
142
143 #if wxUSE_UNICODE
144 argc = 0;
145 // argv = NULL; -- not even really needed
146 #endif // wxUSE_UNICODE
147 }
148
149 // critical section protecting this struct
150 wxCRIT_SECT_DECLARE_MEMBER(csInit);
151
152 // number of times wxInitialize() was called minus the number of times
153 // wxUninitialize() was
154 size_t nInitCount;
155
156 #if wxUSE_UNICODE
157 int argc;
158
159 // if we receive the command line arguments as ASCII and have to convert
160 // them to Unicode ourselves (this is the case under Unix but not Windows,
161 // for example), we remember the converted argv here because we'll have to
162 // free it when doing cleanup to avoid memory leaks
163 wchar_t **argv;
164 #endif // wxUSE_UNICODE
165
166 DECLARE_NO_COPY_CLASS(InitData)
167 } gs_initData;
168
169 // ============================================================================
170 // implementation
171 // ============================================================================
172
173 // ----------------------------------------------------------------------------
174 // command line arguments ANSI -> Unicode conversion
175 // ----------------------------------------------------------------------------
176
177 #if wxUSE_UNICODE
178
179 static void ConvertArgsToUnicode(int argc, char **argv)
180 {
181 gs_initData.argv = new wchar_t *[argc + 1];
182 for ( int i = 0; i < argc; i++ )
183 {
184 wxWCharBuffer buf(wxConvLocal.cMB2WX(argv[i]));
185 gs_initData.argv[i] = buf ? wxStrdup(buf) : NULL;
186 }
187
188 gs_initData.argc = argc;
189 gs_initData.argv[argc] = NULL;
190 }
191
192 static void FreeConvertedArgs()
193 {
194 if ( gs_initData.argv )
195 {
196 for ( int i = 0; i < gs_initData.argc; i++ )
197 {
198 free(gs_initData.argv[i]);
199 }
200
201 delete [] gs_initData.argv;
202 gs_initData.argv = NULL;
203 gs_initData.argc = 0;
204 }
205 }
206
207 #endif // wxUSE_UNICODE
208
209 // ----------------------------------------------------------------------------
210 // start up
211 // ----------------------------------------------------------------------------
212
213 // initialization which is always done (not customizable) before wxApp creation
214 static bool DoCommonPreInit()
215 {
216 #if wxUSE_LOG
217 // install temporary log sink: we can't use wxLogGui before wxApp is
218 // constructed and if we use wxLogStderr, all messages during
219 // initialization simply disappear under Windows
220 //
221 // note that we will delete this log target below
222 delete wxLog::SetActiveTarget(new wxLogBuffer);
223 #endif // wxUSE_LOG
224
225 return true;
226 }
227
228 // non customizable initialization done after wxApp creation and initialization
229 static bool DoCommonPostInit()
230 {
231 wxModule::RegisterModules();
232
233 if ( !wxModule::InitializeModules() )
234 {
235 wxLogError(_("Initialization failed in post init, aborting."));
236 return false;
237 }
238
239 return true;
240 }
241
242 bool wxEntryStart(int& argc, wxChar **argv)
243 {
244 // do minimal, always necessary, initialization
245 // --------------------------------------------
246
247 // initialize wxRTTI
248 if ( !DoCommonPreInit() )
249 {
250 return false;
251 }
252
253
254 // first of all, we need an application object
255 // -------------------------------------------
256
257 // the user might have already created it himself somehow
258 wxAppPtr app(wxTheApp);
259 if ( !app.get() )
260 {
261 // if not, he might have used IMPLEMENT_APP() to give us a function to
262 // create it
263 wxAppInitializerFunction fnCreate = wxApp::GetInitializerFunction();
264
265 if ( fnCreate )
266 {
267 // he did, try to create the custom wxApp object
268 app.Set((*fnCreate)());
269 }
270 }
271
272 if ( !app.get() )
273 {
274 // either IMPLEMENT_APP() was not used at all or it failed -- in any
275 // case we still need something
276 app.Set(new wxDummyConsoleApp);
277 }
278
279
280 // wxApp initialization: this can be customized
281 // --------------------------------------------
282
283 if ( !app->Initialize(argc, argv) )
284 {
285 return false;
286 }
287
288 wxCallAppCleanup callAppCleanup(app.get());
289
290 // for compatibility call the old initialization function too
291 if ( !app->OnInitGui() )
292 return false;
293
294
295 // common initialization after wxTheApp creation
296 // ---------------------------------------------
297
298 if ( !DoCommonPostInit() )
299 return false;
300
301
302 // prevent the smart pointer from destroying its contents
303 app.release();
304
305 // and the cleanup object from doing cleanup
306 callAppCleanup.Dismiss();
307
308 #if wxUSE_LOG
309 // now that we have a valid wxApp (wxLogGui would have crashed if we used
310 // it before now), we can delete the temporary sink we had created for the
311 // initialization messages -- the next time logging function is called, the
312 // sink will be recreated but this time wxAppTraits will be used
313 delete wxLog::SetActiveTarget(NULL);
314 #endif // wxUSE_LOG
315
316 return true;
317 }
318
319 #if wxUSE_UNICODE
320
321 // we provide a wxEntryStart() wrapper taking "char *" pointer too
322 bool wxEntryStart(int& argc, char **argv)
323 {
324 ConvertArgsToUnicode(argc, argv);
325
326 if ( !wxEntryStart(argc, gs_initData.argv) )
327 {
328 FreeConvertedArgs();
329
330 return false;
331 }
332
333 return true;
334 }
335
336 #endif // wxUSE_UNICODE
337
338 // ----------------------------------------------------------------------------
339 // clean up
340 // ----------------------------------------------------------------------------
341
342 // cleanup done before destroying wxTheApp
343 static void DoCommonPreCleanup()
344 {
345 #if wxUSE_LOG
346 // flush the logged messages if any and install a 'safer' log target: the
347 // default one (wxLogGui) can't be used after the resources are freed just
348 // below and the user supplied one might be even more unsafe (using any
349 // wxWidgets GUI function is unsafe starting from now)
350 wxLog::DontCreateOnDemand();
351
352 // this will flush the old messages if any
353 delete wxLog::SetActiveTarget(new wxLogStderr);
354 #endif // wxUSE_LOG
355 }
356
357 // cleanup done after destroying wxTheApp
358 static void DoCommonPostCleanup()
359 {
360 wxModule::CleanUpModules();
361
362 // we can't do this in wxApp itself because it doesn't know if argv had
363 // been allocated
364 #if wxUSE_UNICODE
365 FreeConvertedArgs();
366 #endif // wxUSE_UNICODE
367
368 // use Set(NULL) and not Get() to avoid creating a message output object on
369 // demand when we just want to delete it
370 delete wxMessageOutput::Set(NULL);
371
372 #if wxUSE_LOG
373 // and now delete the last logger as well
374 delete wxLog::SetActiveTarget(NULL);
375 #endif // wxUSE_LOG
376 }
377
378 void wxEntryCleanup()
379 {
380 DoCommonPreCleanup();
381
382
383 // delete the application object
384 if ( wxTheApp )
385 {
386 wxTheApp->CleanUp();
387
388 delete wxTheApp;
389 wxApp::SetInstance(NULL);
390 }
391
392
393 DoCommonPostCleanup();
394 }
395
396 // ----------------------------------------------------------------------------
397 // wxEntry
398 // ----------------------------------------------------------------------------
399
400 // for MSW the real wxEntry is defined in msw/main.cpp
401 #ifndef __WXMSW__
402 #define wxEntryReal wxEntry
403 #endif // !__WXMSW__
404
405 int wxEntryReal(int& argc, wxChar **argv)
406 {
407 // library initialization
408 if ( !wxEntryStart(argc, argv) )
409 {
410 #if wxUSE_LOG
411 // flush any log messages explaining why we failed
412 delete wxLog::SetActiveTarget(NULL);
413 #endif
414 return -1;
415 }
416
417 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
418 // below returns or throws
419 wxCleanupOnExit cleanupOnExit;
420
421 WX_SUPPRESS_UNUSED_WARN(cleanupOnExit);
422
423 wxTRY
424 {
425
426 // app initialization
427 if ( !wxTheApp->CallOnInit() )
428 {
429 // don't call OnExit() if OnInit() failed
430 return -1;
431 }
432
433 // ensure that OnExit() is called if OnInit() had succeeded
434 class CallOnExit
435 {
436 public:
437 ~CallOnExit() { wxTheApp->OnExit(); }
438 } callOnExit;
439
440 WX_SUPPRESS_UNUSED_WARN(callOnExit);
441
442 // app execution
443 return wxTheApp->OnRun();
444 }
445 wxCATCH_ALL( wxTheApp->OnUnhandledException(); return -1; )
446 }
447
448 #if wxUSE_UNICODE
449
450 // as with wxEntryStart, we provide an ANSI wrapper
451 int wxEntry(int& argc, char **argv)
452 {
453 ConvertArgsToUnicode(argc, argv);
454
455 #if wxUSE_FONTMAP
456 // If we created a font mapper during the above call,
457 // it will only be the base class, so delete it to allow
458 // app traits to create mapper.
459 delete (wxFontMapperBase*) wxFontMapperBase::Set(NULL);
460 #endif
461
462 return wxEntry(argc, gs_initData.argv);
463 }
464
465 #endif // wxUSE_UNICODE
466
467 // ----------------------------------------------------------------------------
468 // wxInitialize/wxUninitialize
469 // ----------------------------------------------------------------------------
470
471 bool wxInitialize(int argc, wxChar **argv)
472 {
473 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
474
475 if ( gs_initData.nInitCount++ )
476 {
477 // already initialized
478 return true;
479 }
480
481 return wxEntryStart(argc, argv);
482 }
483
484 void wxUninitialize()
485 {
486 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
487
488 if ( --gs_initData.nInitCount == 0 )
489 {
490 wxEntryCleanup();
491 }
492 }