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