1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/init.cpp
3 // Purpose: initialisation for the library
4 // Author: Vadim Zeitlin
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
28 #include "wx/filefn.h"
30 #include "wx/thread.h"
36 #include "wx/ptr_scpd.h"
37 #include "wx/module.h"
38 #include "wx/except.h"
40 #include "wx/fontmap.h"
43 #if defined(__WXMSW__) && defined(__WXDEBUG__)
44 #include "wx/msw/msvcrt.h"
46 static struct EnableMemLeakChecking
48 EnableMemLeakChecking()
50 // do check for memory leaks on program exit (another useful flag
51 // is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free deallocated
52 // memory which may be used to simulate low-memory condition)
53 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
);
55 } gs_enableLeakChecks
;
56 #endif // __WXMSW__ && __WXDEBUG__
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 // we need a dummy app object if the user doesn't want to create a real one
63 class wxDummyConsoleApp
: public wxAppConsole
66 wxDummyConsoleApp() { }
68 virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
70 DECLARE_NO_COPY_CLASS(wxDummyConsoleApp
)
73 // we need a special kind of auto pointer to wxApp which not only deletes the
74 // pointer it holds in its dtor but also resets the global application pointer
75 wxDECLARE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
)
76 wxDEFINE_SCOPED_PTR(wxAppConsole
, wxAppPtrBase
)
78 class wxAppPtr
: public wxAppPtrBase
81 wxEXPLICIT
wxAppPtr(wxAppConsole
*ptr
= NULL
) : wxAppPtrBase(ptr
) { }
86 // the pointer is going to be deleted in the base class dtor, don't
87 // leave the dangling pointer!
88 wxApp::SetInstance(NULL
);
92 void Set(wxAppConsole
*ptr
)
96 wxApp::SetInstance(ptr
);
99 DECLARE_NO_COPY_CLASS(wxAppPtr
)
102 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
104 class wxCallAppCleanup
107 wxCallAppCleanup(wxAppConsole
*app
) : m_app(app
) { }
108 ~wxCallAppCleanup() { if ( m_app
) m_app
->CleanUp(); }
110 void Dismiss() { m_app
= NULL
; }
116 // another tiny class which simply exists to ensure that wxEntryCleanup is
118 class wxCleanupOnExit
121 ~wxCleanupOnExit() { wxEntryCleanup(); }
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 // suppress warnings about unused variables
129 static inline void Use(void *) { }
131 #define WX_SUPPRESS_UNUSED_WARN(x) Use(&x)
133 // ----------------------------------------------------------------------------
134 // initialization data
135 // ----------------------------------------------------------------------------
137 static struct InitData
145 // argv = NULL; -- not even really needed
146 #endif // wxUSE_UNICODE
149 // critical section protecting this struct
150 wxCRIT_SECT_DECLARE_MEMBER(csInit
);
152 // number of times wxInitialize() was called minus the number of times
153 // wxUninitialize() was
159 // if we receive the command line arguments as ASCII and have to convert
160 // them to Unicode ourselves (this is the case under Unix but not Windows,
161 // for example), we remember the converted argv here because we'll have to
162 // free it when doing cleanup to avoid memory leaks
164 #endif // wxUSE_UNICODE
166 DECLARE_NO_COPY_CLASS(InitData
)
169 // ============================================================================
171 // ============================================================================
173 // ----------------------------------------------------------------------------
174 // command line arguments ANSI -> Unicode conversion
175 // ----------------------------------------------------------------------------
179 static void ConvertArgsToUnicode(int argc
, char **argv
)
181 gs_initData
.argv
= new wchar_t *[argc
+ 1];
182 for ( int i
= 0; i
< argc
; i
++ )
184 wxWCharBuffer
buf(wxConvLocal
.cMB2WX(argv
[i
]));
185 gs_initData
.argv
[i
] = buf
? wxStrdup(buf
) : NULL
;
188 gs_initData
.argc
= argc
;
189 gs_initData
.argv
[argc
] = NULL
;
192 static void FreeConvertedArgs()
194 if ( gs_initData
.argv
)
196 for ( int i
= 0; i
< gs_initData
.argc
; i
++ )
198 free(gs_initData
.argv
[i
]);
201 delete [] gs_initData
.argv
;
202 gs_initData
.argv
= NULL
;
203 gs_initData
.argc
= 0;
207 #endif // wxUSE_UNICODE
209 // ----------------------------------------------------------------------------
211 // ----------------------------------------------------------------------------
213 // initialization which is always done (not customizable) before wxApp creation
214 static bool DoCommonPreInit()
217 // install temporary log sink: we can't use wxLogGui before wxApp is
218 // constructed and if we use wxLogStderr, all messages during
219 // initialization simply disappear under Windows
221 // note that we will delete this log target below
222 delete wxLog::SetActiveTarget(new wxLogBuffer
);
228 // non customizable initialization done after wxApp creation and initialization
229 static bool DoCommonPostInit()
231 wxModule::RegisterModules();
233 if ( !wxModule::InitializeModules() )
235 wxLogError(_("Initialization failed in post init, aborting."));
242 bool wxEntryStart(int& argc
, wxChar
**argv
)
244 // do minimal, always necessary, initialization
245 // --------------------------------------------
248 if ( !DoCommonPreInit() )
254 // first of all, we need an application object
255 // -------------------------------------------
257 // the user might have already created it himself somehow
258 wxAppPtr
app(wxTheApp
);
261 // if not, he might have used IMPLEMENT_APP() to give us a function to
263 wxAppInitializerFunction fnCreate
= wxApp::GetInitializerFunction();
267 // he did, try to create the custom wxApp object
268 app
.Set((*fnCreate
)());
274 // either IMPLEMENT_APP() was not used at all or it failed -- in any
275 // case we still need something
276 app
.Set(new wxDummyConsoleApp
);
280 // wxApp initialization: this can be customized
281 // --------------------------------------------
283 if ( !app
->Initialize(argc
, argv
) )
288 wxCallAppCleanup
callAppCleanup(app
.get());
290 // for compatibility call the old initialization function too
291 if ( !app
->OnInitGui() )
295 // common initialization after wxTheApp creation
296 // ---------------------------------------------
298 if ( !DoCommonPostInit() )
302 // prevent the smart pointer from destroying its contents
305 // and the cleanup object from doing cleanup
306 callAppCleanup
.Dismiss();
309 // now that we have a valid wxApp (wxLogGui would have crashed if we used
310 // it before now), we can delete the temporary sink we had created for the
311 // initialization messages -- the next time logging function is called, the
312 // sink will be recreated but this time wxAppTraits will be used
313 delete wxLog::SetActiveTarget(NULL
);
321 // we provide a wxEntryStart() wrapper taking "char *" pointer too
322 bool wxEntryStart(int& argc
, char **argv
)
324 ConvertArgsToUnicode(argc
, argv
);
326 if ( !wxEntryStart(argc
, gs_initData
.argv
) )
336 #endif // wxUSE_UNICODE
338 // ----------------------------------------------------------------------------
340 // ----------------------------------------------------------------------------
342 // cleanup done before destroying wxTheApp
343 static void DoCommonPreCleanup()
346 // flush the logged messages if any and install a 'safer' log target: the
347 // default one (wxLogGui) can't be used after the resources are freed just
348 // below and the user supplied one might be even more unsafe (using any
349 // wxWidgets GUI function is unsafe starting from now)
350 wxLog::DontCreateOnDemand();
352 // this will flush the old messages if any
353 delete wxLog::SetActiveTarget(new wxLogStderr
);
357 // cleanup done after destroying wxTheApp
358 static void DoCommonPostCleanup()
360 wxModule::CleanUpModules();
362 // we can't do this in wxApp itself because it doesn't know if argv had
366 #endif // wxUSE_UNICODE
368 // use Set(NULL) and not Get() to avoid creating a message output object on
369 // demand when we just want to delete it
370 delete wxMessageOutput::Set(NULL
);
373 // and now delete the last logger as well
374 delete wxLog::SetActiveTarget(NULL
);
378 void wxEntryCleanup()
380 DoCommonPreCleanup();
383 // delete the application object
389 wxApp::SetInstance(NULL
);
393 DoCommonPostCleanup();
396 // ----------------------------------------------------------------------------
398 // ----------------------------------------------------------------------------
400 // for MSW the real wxEntry is defined in msw/main.cpp
402 #define wxEntryReal wxEntry
405 int wxEntryReal(int& argc
, wxChar
**argv
)
407 // library initialization
408 if ( !wxEntryStart(argc
, argv
) )
411 // flush any log messages explaining why we failed
412 delete wxLog::SetActiveTarget(NULL
);
417 // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
418 // below returns or throws
419 wxCleanupOnExit cleanupOnExit
;
421 WX_SUPPRESS_UNUSED_WARN(cleanupOnExit
);
426 // app initialization
427 if ( !wxTheApp
->CallOnInit() )
429 // don't call OnExit() if OnInit() failed
433 // ensure that OnExit() is called if OnInit() had succeeded
437 ~CallOnExit() { wxTheApp
->OnExit(); }
440 WX_SUPPRESS_UNUSED_WARN(callOnExit
);
443 return wxTheApp
->OnRun();
445 wxCATCH_ALL( wxTheApp
->OnUnhandledException(); return -1; )
450 // as with wxEntryStart, we provide an ANSI wrapper
451 int wxEntry(int& argc
, char **argv
)
453 ConvertArgsToUnicode(argc
, argv
);
456 // If we created a font mapper during the above call,
457 // it will only be the base class, so delete it to allow
458 // app traits to create mapper.
459 delete (wxFontMapperBase
*) wxFontMapperBase::Set(NULL
);
462 return wxEntry(argc
, gs_initData
.argv
);
465 #endif // wxUSE_UNICODE
467 // ----------------------------------------------------------------------------
468 // wxInitialize/wxUninitialize
469 // ----------------------------------------------------------------------------
471 bool wxInitialize(int argc
, wxChar
**argv
)
473 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
475 if ( gs_initData
.nInitCount
++ )
477 // already initialized
481 return wxEntryStart(argc
, argv
);
484 void wxUninitialize()
486 wxCRIT_SECT_LOCKER(lockInit
, gs_initData
.csInit
);
488 if ( --gs_initData
.nInitCount
== 0 )