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