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