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