fixed Unicode compilation and run-time problems
[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 if ( gs_initData.argv )
172 {
173 for ( int i = 0; i < gs_initData.argc; i++ )
174 {
175 free(gs_initData.argv[i]);
176 }
177
178 delete [] gs_initData.argv;
179 gs_initData.argv = NULL;
180 }
181 }
182
183 #endif // wxUSE_UNICODE
184
185 // ----------------------------------------------------------------------------
186 // start up
187 // ----------------------------------------------------------------------------
188
189 // initialization which is always done (not customizable) before wxApp creation
190 static bool DoCommonPreInit()
191 {
192 wxClassInfo::InitializeClasses();
193
194 return true;
195 }
196
197 // non customizable initialization done after wxApp creation and initialization
198 static bool DoCommonPostInit()
199 {
200 wxModule::RegisterModules();
201
202 return wxModule::InitializeModules();
203 }
204
205 bool wxEntryStart(int& argc, wxChar **argv)
206 {
207 // do minimal, always necessary, initialization
208 // --------------------------------------------
209
210 // initialize wxRTTI
211 if ( !DoCommonPreInit() )
212 {
213 return false;
214 }
215
216
217 // first of all, we need an application object
218 // -------------------------------------------
219
220 // the user might have already created it himself somehow
221 wxAppPtr app(wxTheApp);
222 if ( !app.get() )
223 {
224 // if not, he might have used IMPLEMENT_APP() to give us a function to
225 // create it
226 wxAppInitializerFunction fnCreate = wxApp::GetInitializerFunction();
227
228 if ( fnCreate )
229 {
230 // he did, try to create the custom wxApp object
231 app.Set((*fnCreate)());
232 }
233 }
234
235 if ( !app.get() )
236 {
237 // either IMPLEMENT_APP() was not used at all or it failed -- in any
238 // case we still need something
239 //
240 // NB: cast is needed because for the backwards-compatibility reasons
241 // wxTheApp is really a wxApp and not just wxAppConsole...
242 app.Set((wxApp *)new wxDummyConsoleApp);
243 }
244
245
246 // wxApp initialization: this can be customized
247 // --------------------------------------------
248
249 if ( !wxTheApp->Initialize(argc, argv) )
250 {
251 return false;
252 }
253
254 wxCallAppCleanup callAppCleanup(wxTheApp);
255
256 // for compatibility call the old initialization function too
257 if ( !wxTheApp->OnInitGui() )
258 return false;
259
260
261 // common initialization after wxTheApp creation
262 // ---------------------------------------------
263
264 if ( !DoCommonPostInit() )
265 return false;
266
267
268 // prevent the smart pointer from destroying its contents
269 app.release();
270
271 // and the cleanup object from doing cleanup
272 callAppCleanup.Dismiss();
273
274 return true;
275 }
276
277 #if wxUSE_UNICODE
278
279 // we provide a wxEntryStart() wrapper taking "char *" pointer too
280 bool wxEntryStart(int& argc, char **argv)
281 {
282 ConvertArgsToUnicode(argc, argv);
283
284 if ( !wxEntryStart(argc, gs_initData.argv) )
285 {
286 FreeConvertedArgs();
287
288 return false;
289 }
290
291 return true;
292 }
293
294 #endif // wxUSE_UNICODE
295
296 // ----------------------------------------------------------------------------
297 // clean up
298 // ----------------------------------------------------------------------------
299
300 // cleanup done before destroying wxTheApp
301 static void DoCommonPreCleanup()
302 {
303 #if wxUSE_LOG
304 // flush the logged messages if any and install a 'safer' log target: the
305 // default one (wxLogGui) can't be used after the resources are freed just
306 // below and the user supplied one might be even more unsafe (using any
307 // wxWindows GUI function is unsafe starting from now)
308 wxLog::DontCreateOnDemand();
309
310 // this will flush the old messages if any
311 delete wxLog::SetActiveTarget(new wxLogStderr);
312 #endif // wxUSE_LOG
313
314 wxModule::CleanUpModules();
315 }
316
317 // cleanup done after destroying wxTheApp
318 static void DoCommonPostCleanup()
319 {
320 wxClassInfo::CleanUpClasses();
321
322 // we can't do this in wxApp itself because it doesn't know if argv had
323 // been allocated
324 #if wxUSE_UNICODE
325 FreeConvertedArgs();
326 #endif // wxUSE_UNICODE
327
328 #if wxUSE_LOG
329 // and now delete the last logger as well
330 delete wxLog::SetActiveTarget(NULL);
331 #endif // wxUSE_LOG
332 }
333
334 void wxEntryCleanup()
335 {
336 DoCommonPreCleanup();
337
338
339 // delete the application object
340 if ( wxTheApp )
341 {
342 wxTheApp->CleanUp();
343
344 delete wxTheApp;
345 wxTheApp = NULL;
346 }
347
348
349 DoCommonPostCleanup();
350
351 // check for memory leaks
352 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
353 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
354 {
355 wxLogDebug(wxT("There were memory leaks.\n"));
356 wxDebugContext::Dump();
357 wxDebugContext::PrintStatistics();
358 }
359 #endif // Debug
360
361 }
362
363 // ----------------------------------------------------------------------------
364 // wxEntry
365 // ----------------------------------------------------------------------------
366
367 #if !defined(__WXMSW__) || !wxUSE_ON_FATAL_EXCEPTION
368 #define wxEntryReal wxEntry
369 #endif // !(__WXMSW__ && wxUSE_ON_FATAL_EXCEPTION)
370
371 int wxEntryReal(int& argc, wxChar **argv)
372 {
373 // library initialization
374 if ( !wxEntryStart(argc, argv) )
375 {
376 return -1;
377 }
378
379 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
380 // below returns or throws
381 wxCleanupOnExit cleanupOnExit;
382
383 // app initialization
384 if ( !wxTheApp->OnInit() )
385 {
386 // don't call OnExit() if OnInit() failed
387 return -1;
388 }
389
390 // app execution
391 int retValue = wxTheApp->OnRun();
392
393 // why should we do this? it doesn't close all window, just one of them and
394 // this shouldn't be necessary anyhow...
395 #if 0
396 // close any remaining windows
397 wxWindow *topWindow = wxTheApp->GetTopWindow();
398 if ( topWindow )
399 {
400 // forcibly delete the window.
401 topWindow->Destroy();
402
403 // collect the dead objects
404 wxTheApp->DeletePendingObjects();
405 }
406 #endif // 0
407
408 // app clean up
409 wxTheApp->OnExit();
410
411 return retValue;
412 }
413
414 // wrap real wxEntry in a try-except block to be able to call
415 // OnFatalException() if necessary
416 #if defined(__WXMSW__) && wxUSE_ON_FATAL_EXCEPTION
417
418 extern unsigned long wxGlobalSEHandler();
419
420 int wxEntry(int& argc, wxChar **argv)
421 {
422 __try
423 {
424 return wxEntryReal(argc, argv);
425 }
426 __except ( wxGlobalSEHandler() )
427 {
428 ::ExitProcess(3); // the same exit code as abort()
429
430 // this code is unreachable but put it here to suppress warnings
431 return -1;
432 }
433 }
434
435 #endif // __WXMSW__ && wxUSE_ON_FATAL_EXCEPTION
436
437 #if wxUSE_UNICODE
438
439 // as with wxEntryStart, we provide an ANSI wrapper
440 int wxEntry(int& argc, char **argv)
441 {
442 ConvertArgsToUnicode(argc, argv);
443
444 return wxEntry(argc, gs_initData.argv);
445 }
446
447 #endif // wxUSE_UNICODE
448
449 // ----------------------------------------------------------------------------
450 // wxInitialize/wxUninitialize
451 // ----------------------------------------------------------------------------
452
453 bool wxInitialize(int argc, wxChar **argv)
454 {
455 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
456
457 if ( gs_initData.nInitCount++ )
458 {
459 // already initialized
460 return true;
461 }
462
463 return wxEntryStart(argc, argv);
464 }
465
466 void wxUninitialize()
467 {
468 wxCRIT_SECT_LOCKER(lockInit, gs_initData.csInit);
469
470 if ( !--gs_initData.nInitCount )
471 {
472 wxEntryCleanup();
473 }
474 }
475