]> git.saurik.com Git - wxWidgets.git/blame - src/common/appbase.cpp
minor cleanup of Unix GetInfo(): assert if invalid parameters are passed; don't use...
[wxWidgets.git] / src / common / appbase.cpp
CommitLineData
e2478fde 1///////////////////////////////////////////////////////////////////////////////
8ecff181 2// Name: src/common/appbase.cpp
e0954e72 3// Purpose: implements wxAppConsoleBase class
e2478fde
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 19.06.2003 (extracted from common/appcmn.cpp)
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
0a53b9b8 9// License: wxWindows license
e2478fde
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
57bd4c60
WS
28 #ifdef __WXMSW__
29 #include "wx/msw/wrapwin.h" // includes windows.h for MessageBox()
30 #endif
8ecff181 31 #include "wx/list.h"
8df6de97
VS
32 #include "wx/app.h"
33 #include "wx/intl.h"
86f8d1a8 34 #include "wx/log.h"
de6185e2 35 #include "wx/utils.h"
0cb7e05c 36 #include "wx/wxcrtvararg.h"
e2478fde
VZ
37#endif //WX_PRECOMP
38
39#include "wx/apptrait.h"
40#include "wx/cmdline.h"
41#include "wx/confbase.h"
b46b1d59 42#include "wx/evtloop.h"
ce39c39e 43#include "wx/filename.h"
e2478fde 44#include "wx/msgout.h"
664e1314 45#include "wx/scopedptr.h"
e2478fde 46#include "wx/tokenzr.h"
204abcd4 47#include "wx/thread.h"
e2478fde 48
1663c655
VZ
49#if wxUSE_EXCEPTIONS && wxUSE_STL
50 #include <exception>
51 #include <typeinfo>
52#endif
53
9b4da627 54#ifndef __WXPALMOS5__
e2478fde
VZ
55#if !defined(__WXMSW__) || defined(__WXMICROWIN__)
56 #include <signal.h> // for SIGTRAP used by wxTrap()
57#endif //Win/Unix
58
0e5ab030 59#include <locale.h>
9b4da627 60#endif // ! __WXPALMOS5__
0e5ab030 61
1c193821
JS
62#if wxUSE_FONTMAP
63 #include "wx/fontmap.h"
64#endif // wxUSE_FONTMAP
65
657a8a35 66#if wxDEBUG_LEVEL
7b1c3469 67 #if wxUSE_STACKWALKER
6c8f8d92 68 #include "wx/stackwalk.h"
4a92d4bc
VZ
69 #ifdef __WXMSW__
70 #include "wx/msw/debughlp.h"
71 #endif
6c8f8d92 72 #endif // wxUSE_STACKWALKER
000eea7a
VZ
73
74 #include "wx/recguard.h"
657a8a35 75#endif // wxDEBUG_LEVEL
6c8f8d92 76
121aea46
MW
77// wxABI_VERSION can be defined when compiling applications but it should be
78// left undefined when compiling the library itself, it is then set to its
79// default value in version.h
80#if wxABI_VERSION != wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + 99
81#error "wxABI_VERSION should not be defined when compiling the library"
82#endif
83
e2478fde
VZ
84// ----------------------------------------------------------------------------
85// private functions prototypes
86// ----------------------------------------------------------------------------
87
657a8a35 88#if wxDEBUG_LEVEL
e2478fde
VZ
89 // really just show the assert dialog
90 static bool DoShowAssertDialog(const wxString& msg);
91
92 // prepare for showing the assert dialog, use the given traits or
93 // DoShowAssertDialog() as last fallback to really show it
94 static
657a8a35
VZ
95 void ShowAssertDialog(const wxString& file,
96 int line,
97 const wxString& func,
98 const wxString& cond,
99 const wxString& msg,
e2478fde 100 wxAppTraits *traits = NULL);
657a8a35 101#endif // wxDEBUG_LEVEL
e2478fde 102
657a8a35 103#ifdef __WXDEBUG__
e2478fde
VZ
104 // turn on the trace masks specified in the env variable WXTRACE
105 static void LINKAGEMODE SetTraceMasks();
106#endif // __WXDEBUG__
107
108// ----------------------------------------------------------------------------
109// global vars
110// ----------------------------------------------------------------------------
111
e0954e72 112wxAppConsole *wxAppConsoleBase::ms_appInstance = NULL;
e2478fde 113
e0954e72 114wxAppInitializerFunction wxAppConsoleBase::ms_appInitFn = NULL;
e2478fde 115
51fe4b60
VZ
116wxSocketManager *wxAppTraitsBase::ms_manager = NULL;
117
b46b1d59
VZ
118// ----------------------------------------------------------------------------
119// wxEventLoopPtr
120// ----------------------------------------------------------------------------
121
122// this defines wxEventLoopPtr
2ddff00c 123wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoopBase)
b46b1d59 124
e2478fde 125// ============================================================================
e0954e72 126// wxAppConsoleBase implementation
e2478fde
VZ
127// ============================================================================
128
129// ----------------------------------------------------------------------------
130// ctor/dtor
131// ----------------------------------------------------------------------------
132
e0954e72 133wxAppConsoleBase::wxAppConsoleBase()
e2478fde
VZ
134{
135 m_traits = NULL;
b46b1d59 136 m_mainLoop = NULL;
cae9e7b1 137 m_bDoPendingEventProcessing = true;
e2478fde 138
5c33522f 139 ms_appInstance = static_cast<wxAppConsole *>(this);
e2478fde
VZ
140
141#ifdef __WXDEBUG__
142 SetTraceMasks();
bc334f39
RD
143#if wxUSE_UNICODE
144 // In unicode mode the SetTraceMasks call can cause an apptraits to be
145 // created, but since we are still in the constructor the wrong kind will
146 // be created for GUI apps. Destroy it so it can be created again later.
147 delete m_traits;
148 m_traits = NULL;
149#endif
e2478fde
VZ
150#endif
151}
152
e0954e72 153wxAppConsoleBase::~wxAppConsoleBase()
e2478fde
VZ
154{
155 delete m_traits;
156}
157
94826170 158// ----------------------------------------------------------------------------
8b93348e 159// initialization/cleanup
94826170
VZ
160// ----------------------------------------------------------------------------
161
a7d980f6 162bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **argv)
94826170 163{
d774f916
VZ
164#if wxUSE_INTL
165 GetTraits()->SetLocale();
166#endif // wxUSE_INTL
167
4055ed82 168#ifndef __WXPALMOS__
a7d980f6 169 if ( m_appName.empty() && argv && argv[0] )
94826170
VZ
170 {
171 // the application name is, by default, the name of its executable file
94826170 172 wxFileName::SplitPath(argv[0], NULL, &m_appName, NULL);
94826170 173 }
d774f916 174#endif // !__WXPALMOS__
94826170
VZ
175
176 return true;
177}
178
e0954e72 179wxEventLoopBase *wxAppConsoleBase::CreateMainLoop()
b46b1d59
VZ
180{
181 return GetTraits()->CreateEventLoop();
182}
183
e0954e72 184void wxAppConsoleBase::CleanUp()
94826170 185{
aea33a3e
VZ
186 if ( m_mainLoop )
187 {
188 delete m_mainLoop;
189 m_mainLoop = NULL;
190 }
94826170
VZ
191}
192
e2478fde
VZ
193// ----------------------------------------------------------------------------
194// OnXXX() callbacks
195// ----------------------------------------------------------------------------
196
e0954e72 197bool wxAppConsoleBase::OnInit()
e2478fde
VZ
198{
199#if wxUSE_CMDLINE_PARSER
200 wxCmdLineParser parser(argc, argv);
201
202 OnInitCmdLine(parser);
203
204 bool cont;
4629016d 205 switch ( parser.Parse(false /* don't show usage */) )
e2478fde
VZ
206 {
207 case -1:
208 cont = OnCmdLineHelp(parser);
209 break;
210
211 case 0:
212 cont = OnCmdLineParsed(parser);
213 break;
214
215 default:
216 cont = OnCmdLineError(parser);
217 break;
218 }
219
220 if ( !cont )
4629016d 221 return false;
e2478fde
VZ
222#endif // wxUSE_CMDLINE_PARSER
223
4629016d 224 return true;
e2478fde
VZ
225}
226
e0954e72 227int wxAppConsoleBase::OnRun()
b46b1d59
VZ
228{
229 return MainLoop();
8ac09e52 230}
b46b1d59 231
e0954e72 232int wxAppConsoleBase::OnExit()
e2478fde
VZ
233{
234#if wxUSE_CONFIG
235 // delete the config object if any (don't use Get() here, but Set()
236 // because Get() could create a new config object)
d3b9f782 237 delete wxConfigBase::Set(NULL);
e2478fde
VZ
238#endif // wxUSE_CONFIG
239
e2478fde
VZ
240 return 0;
241}
242
e0954e72 243void wxAppConsoleBase::Exit()
e2478fde 244{
b46b1d59
VZ
245 if (m_mainLoop != NULL)
246 ExitMainLoop();
247 else
248 exit(-1);
e2478fde
VZ
249}
250
251// ----------------------------------------------------------------------------
252// traits stuff
253// ----------------------------------------------------------------------------
254
e0954e72 255wxAppTraits *wxAppConsoleBase::CreateTraits()
e2478fde 256{
7843d11b 257 return new wxConsoleAppTraits;
e2478fde
VZ
258}
259
e0954e72 260wxAppTraits *wxAppConsoleBase::GetTraits()
e2478fde
VZ
261{
262 // FIXME-MT: protect this with a CS?
263 if ( !m_traits )
264 {
265 m_traits = CreateTraits();
266
267 wxASSERT_MSG( m_traits, _T("wxApp::CreateTraits() failed?") );
268 }
269
270 return m_traits;
271}
272
96b2cbe8
VZ
273/* static */
274wxAppTraits *wxAppConsoleBase::GetTraitsIfExists()
275{
276 wxAppConsole * const app = GetInstance();
277 return app ? app->GetTraits() : NULL;
278}
279
e2478fde 280// ----------------------------------------------------------------------------
dde19c21 281// wxEventLoop redirection
e2478fde
VZ
282// ----------------------------------------------------------------------------
283
e0954e72 284int wxAppConsoleBase::MainLoop()
e2478fde 285{
2ddff00c 286 wxEventLoopBaseTiedPtr mainLoop(&m_mainLoop, CreateMainLoop());
b46b1d59
VZ
287
288 return m_mainLoop ? m_mainLoop->Run() : -1;
289}
290
e0954e72 291void wxAppConsoleBase::ExitMainLoop()
b46b1d59
VZ
292{
293 // we should exit from the main event loop, not just any currently active
294 // (e.g. modal dialog) event loop
295 if ( m_mainLoop && m_mainLoop->IsRunning() )
296 {
297 m_mainLoop->Exit(0);
298 }
299}
300
e0954e72 301bool wxAppConsoleBase::Pending()
b46b1d59
VZ
302{
303 // use the currently active message loop here, not m_mainLoop, because if
304 // we're showing a modal dialog (with its own event loop) currently the
305 // main event loop is not running anyhow
2ddff00c 306 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
b46b1d59
VZ
307
308 return loop && loop->Pending();
309}
310
e0954e72 311bool wxAppConsoleBase::Dispatch()
b46b1d59
VZ
312{
313 // see comment in Pending()
2ddff00c 314 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
b46b1d59
VZ
315
316 return loop && loop->Dispatch();
317}
8ecff181 318
dde19c21
FM
319bool wxAppConsoleBase::Yield(bool onlyIfNeeded)
320{
321 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
d48b06bd 322
dde19c21 323 return loop && loop->Yield(onlyIfNeeded);
e2478fde
VZ
324}
325
e0954e72 326void wxAppConsoleBase::WakeUpIdle()
b46b1d59
VZ
327{
328 if ( m_mainLoop )
329 m_mainLoop->WakeUp();
330}
331
e0954e72 332bool wxAppConsoleBase::ProcessIdle()
b46b1d59 333{
dde19c21
FM
334 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
335
336 return loop && loop->ProcessIdle();
337}
14eb37a0 338
dde19c21
FM
339// ----------------------------------------------------------------------------
340// events
341// ----------------------------------------------------------------------------
b46b1d59 342
dde19c21
FM
343/* static */
344bool wxAppConsoleBase::IsMainLoopRunning()
345{
346 const wxAppConsole * const app = GetInstance();
347
348 return app && app->m_mainLoop != NULL;
b46b1d59
VZ
349}
350
e0954e72 351int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event))
e2478fde
VZ
352{
353 // process the events normally by default
354 return -1;
355}
356
8e40ed85
FM
357void wxAppConsoleBase::DelayPendingEventHandler(wxEvtHandler* toDelay)
358{
359 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
360
361 // move the handler from the list of handlers with processable pending events
362 // to the list of handlers with pending events which needs to be processed later
363 m_handlersWithPendingEvents.Remove(toDelay);
364
365 if (m_handlersWithPendingDelayedEvents.Index(toDelay) == wxNOT_FOUND)
366 m_handlersWithPendingDelayedEvents.Add(toDelay);
367
368 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
369}
370
371void wxAppConsoleBase::RemovePendingEventHandler(wxEvtHandler* toRemove)
372{
373 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
374
375 if (m_handlersWithPendingEvents.Index(toRemove) != wxNOT_FOUND)
376 {
377 m_handlersWithPendingEvents.Remove(toRemove);
378
379 // check that the handler was present only once in the list
380 wxASSERT_MSG( m_handlersWithPendingEvents.Index(toRemove) == wxNOT_FOUND,
381 "Handler occurs twice in the m_handlersWithPendingEvents list!" );
382 }
383 //else: it wasn't in this list at all, it's ok
384
385 if (m_handlersWithPendingDelayedEvents.Index(toRemove) != wxNOT_FOUND)
386 {
387 m_handlersWithPendingDelayedEvents.Remove(toRemove);
388
389 // check that the handler was present only once in the list
390 wxASSERT_MSG( m_handlersWithPendingDelayedEvents.Index(toRemove) == wxNOT_FOUND,
391 "Handler occurs twice in m_handlersWithPendingDelayedEvents list!" );
392 }
393 //else: it wasn't in this list at all, it's ok
394
395 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
396}
397
398void wxAppConsoleBase::AppendPendingEventHandler(wxEvtHandler* toAppend)
399{
400 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
401
402 if ( m_handlersWithPendingEvents.Index(toAppend) == wxNOT_FOUND )
403 m_handlersWithPendingEvents.Add(toAppend);
404
405 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
406}
407
408bool wxAppConsoleBase::HasPendingEvents() const
409{
410 wxENTER_CRIT_SECT(const_cast<wxAppConsoleBase*>(this)->m_handlersWithPendingEventsLocker);
411
412 bool has = !m_handlersWithPendingEvents.IsEmpty();
413
414 wxLEAVE_CRIT_SECT(const_cast<wxAppConsoleBase*>(this)->m_handlersWithPendingEventsLocker);
415
416 return has;
417}
418
419void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
420{
cae9e7b1 421 m_bDoPendingEventProcessing = false;
8e40ed85
FM
422}
423
424void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
425{
cae9e7b1 426 m_bDoPendingEventProcessing = true;
8e40ed85
FM
427}
428
429void wxAppConsoleBase::ProcessPendingEvents()
430{
cae9e7b1
FM
431 if (!m_bDoPendingEventProcessing)
432 return;
433
8e40ed85
FM
434 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
435
436 wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
437 "this helper list should be empty" );
438
439 // iterate until the list becomes empty: the handlers remove themselves
440 // from it when they don't have any more pending events
441 while (!m_handlersWithPendingEvents.IsEmpty())
442 {
443 // In ProcessPendingEvents(), new handlers might be added
444 // and we can safely leave the critical section here.
445 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
446
447 // NOTE: we always call ProcessPendingEvents() on the first event handler
448 // with pending events because handlers auto-remove themselves
449 // from this list (see RemovePendingEventHandler) if they have no
450 // more pending events.
451 m_handlersWithPendingEvents[0]->ProcessPendingEvents();
452
453 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
454 }
455
456 // now the wxHandlersWithPendingEvents is surely empty; however some event
457 // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents
458 // because of a selective wxYield call in progress.
459 // Now we need to move them back to wxHandlersWithPendingEvents so the next
460 // call to this function has the chance of processing them:
461 if (!m_handlersWithPendingDelayedEvents.IsEmpty())
462 {
463 WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents);
464 m_handlersWithPendingDelayedEvents.Clear();
465 }
466
467 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
468}
469
cae9e7b1
FM
470void wxAppConsoleBase::DeletePendingEvents()
471{
472 wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
473
474 wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
475 "this helper list should be empty" );
476
477 for (unsigned int i=0; i<m_handlersWithPendingEvents.GetCount(); i++)
478 m_handlersWithPendingEvents[i]->DeletePendingEvents();
479
480 m_handlersWithPendingEvents.Clear();
481
482 wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
483}
484
78361a0e
VZ
485// ----------------------------------------------------------------------------
486// exception handling
487// ----------------------------------------------------------------------------
488
6f054ac5
VZ
489#if wxUSE_EXCEPTIONS
490
491void
e0954e72
VZ
492wxAppConsoleBase::HandleEvent(wxEvtHandler *handler,
493 wxEventFunction func,
494 wxEvent& event) const
6f054ac5 495{
96d38c7e
VS
496 // by default, simply call the handler
497 (handler->*func)(event);
6f054ac5
VZ
498}
499
3c778901
VZ
500void wxAppConsoleBase::CallEventHandler(wxEvtHandler *handler,
501 wxEventFunctor& functor,
502 wxEvent& event) const
503{
504 // If the functor holds a method then, for backward compatibility, call
505 // HandleEvent():
506 wxEventFunction eventFunction = functor.GetMethod();
507
508 if ( eventFunction )
509 HandleEvent(handler, eventFunction, event);
510 else
511 functor(handler, event);
512}
513
1663c655
VZ
514void wxAppConsoleBase::OnUnhandledException()
515{
516#ifdef __WXDEBUG__
517 // we're called from an exception handler so we can re-throw the exception
518 // to recover its type
519 wxString what;
520 try
521 {
522 throw;
523 }
524#if wxUSE_STL
525 catch ( std::exception& e )
526 {
527 what.Printf("std::exception of type \"%s\", what() = \"%s\"",
528 typeid(e).name(), e.what());
529 }
530#endif // wxUSE_STL
531 catch ( ... )
532 {
533 what = "unknown exception";
534 }
535
536 wxMessageOutputBest().Printf(
537 "*** Caught unhandled %s; terminating\n", what
538 );
539#endif // __WXDEBUG__
540}
541
b46b1d59
VZ
542// ----------------------------------------------------------------------------
543// exceptions support
544// ----------------------------------------------------------------------------
545
e0954e72 546bool wxAppConsoleBase::OnExceptionInMainLoop()
b46b1d59
VZ
547{
548 throw;
549
550 // some compilers are too stupid to know that we never return after throw
551#if defined(__DMC__) || (defined(_MSC_VER) && _MSC_VER < 1200)
552 return false;
553#endif
554}
555
6f054ac5
VZ
556#endif // wxUSE_EXCEPTIONS
557
e2478fde
VZ
558// ----------------------------------------------------------------------------
559// cmd line parsing
560// ----------------------------------------------------------------------------
561
562#if wxUSE_CMDLINE_PARSER
563
e6d4038a 564#define OPTION_VERBOSE "verbose"
e2478fde 565
e0954e72 566void wxAppConsoleBase::OnInitCmdLine(wxCmdLineParser& parser)
e2478fde
VZ
567{
568 // the standard command line options
569 static const wxCmdLineEntryDesc cmdLineDesc[] =
570 {
571 {
572 wxCMD_LINE_SWITCH,
e6d4038a
VZ
573 "h",
574 "help",
e2478fde
VZ
575 gettext_noop("show this help message"),
576 wxCMD_LINE_VAL_NONE,
577 wxCMD_LINE_OPTION_HELP
578 },
579
580#if wxUSE_LOG
581 {
582 wxCMD_LINE_SWITCH,
0d5ab92f 583 NULL,
e2478fde
VZ
584 OPTION_VERBOSE,
585 gettext_noop("generate verbose log messages"),
586 wxCMD_LINE_VAL_NONE,
587 0x0
588 },
589#endif // wxUSE_LOG
590
e2478fde 591 // terminator
0d5ab92f 592 wxCMD_LINE_DESC_END
e2478fde
VZ
593 };
594
595 parser.SetDesc(cmdLineDesc);
596}
597
e0954e72 598bool wxAppConsoleBase::OnCmdLineParsed(wxCmdLineParser& parser)
e2478fde
VZ
599{
600#if wxUSE_LOG
601 if ( parser.Found(OPTION_VERBOSE) )
602 {
fa0d3447 603 wxLog::SetVerbose(true);
e2478fde 604 }
fa0d3447
WS
605#else
606 wxUnusedVar(parser);
e2478fde
VZ
607#endif // wxUSE_LOG
608
fa0d3447 609 return true;
e2478fde
VZ
610}
611
e0954e72 612bool wxAppConsoleBase::OnCmdLineHelp(wxCmdLineParser& parser)
e2478fde
VZ
613{
614 parser.Usage();
615
4629016d 616 return false;
e2478fde
VZ
617}
618
e0954e72 619bool wxAppConsoleBase::OnCmdLineError(wxCmdLineParser& parser)
e2478fde
VZ
620{
621 parser.Usage();
622
4629016d 623 return false;
e2478fde
VZ
624}
625
626#endif // wxUSE_CMDLINE_PARSER
627
628// ----------------------------------------------------------------------------
629// debugging support
630// ----------------------------------------------------------------------------
631
632/* static */
e0954e72
VZ
633bool wxAppConsoleBase::CheckBuildOptions(const char *optionsSignature,
634 const char *componentName)
e2478fde 635{
2a7c7605
VS
636#if 0 // can't use wxLogTrace, not up and running yet
637 printf("checking build options object '%s' (ptr %p) in '%s'\n",
638 optionsSignature, optionsSignature, componentName);
e2478fde
VZ
639#endif
640
2a7c7605 641 if ( strcmp(optionsSignature, WX_BUILD_OPTIONS_SIGNATURE) != 0 )
e2478fde 642 {
2a7c7605
VS
643 wxString lib = wxString::FromAscii(WX_BUILD_OPTIONS_SIGNATURE);
644 wxString prog = wxString::FromAscii(optionsSignature);
645 wxString progName = wxString::FromAscii(componentName);
e2478fde 646 wxString msg;
2dbc444a 647
b880adec 648 msg.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."),
2a7c7605 649 lib.c_str(), progName.c_str(), prog.c_str());
2dbc444a 650
095d49f2 651 wxLogFatalError(msg.c_str());
e2478fde
VZ
652
653 // normally wxLogFatalError doesn't return
4629016d 654 return false;
e2478fde 655 }
e2478fde 656
4629016d 657 return true;
e2478fde
VZ
658}
659
e0954e72
VZ
660void wxAppConsoleBase::OnAssertFailure(const wxChar *file,
661 int line,
662 const wxChar *func,
663 const wxChar *cond,
664 const wxChar *msg)
dfa0b52f 665{
657a8a35 666#if wxDEBUG_LEVEL
dfa0b52f 667 ShowAssertDialog(file, line, func, cond, msg, GetTraits());
657a8a35
VZ
668#else
669 // this function is still present even in debug level 0 build for ABI
670 // compatibility reasons but is never called there and so can simply do
671 // nothing in it
672 wxUnusedVar(file);
673 wxUnusedVar(line);
674 wxUnusedVar(func);
675 wxUnusedVar(cond);
676 wxUnusedVar(msg);
677#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
dfa0b52f
VZ
678}
679
e0954e72
VZ
680void wxAppConsoleBase::OnAssert(const wxChar *file,
681 int line,
682 const wxChar *cond,
683 const wxChar *msg)
e2478fde 684{
acc476c5 685 OnAssertFailure(file, line, NULL, cond, msg);
e2478fde
VZ
686}
687
e2478fde
VZ
688// ============================================================================
689// other classes implementations
690// ============================================================================
691
692// ----------------------------------------------------------------------------
693// wxConsoleAppTraitsBase
694// ----------------------------------------------------------------------------
695
696#if wxUSE_LOG
697
698wxLog *wxConsoleAppTraitsBase::CreateLogTarget()
699{
700 return new wxLogStderr;
701}
702
703#endif // wxUSE_LOG
704
705wxMessageOutput *wxConsoleAppTraitsBase::CreateMessageOutput()
706{
707 return new wxMessageOutputStderr;
708}
709
710#if wxUSE_FONTMAP
711
712wxFontMapper *wxConsoleAppTraitsBase::CreateFontMapper()
713{
714 return (wxFontMapper *)new wxFontMapperBase;
715}
716
717#endif // wxUSE_FONTMAP
718
f0244295
VZ
719wxRendererNative *wxConsoleAppTraitsBase::CreateRenderer()
720{
721 // console applications don't use renderers
722 return NULL;
723}
724
e2478fde
VZ
725bool wxConsoleAppTraitsBase::ShowAssertDialog(const wxString& msg)
726{
727 return wxAppTraitsBase::ShowAssertDialog(msg);
728}
729
730bool wxConsoleAppTraitsBase::HasStderr()
731{
732 // console applications always have stderr, even under Mac/Windows
733 return true;
734}
735
736void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject *object)
737{
738 delete object;
739}
740
741void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject * WXUNUSED(object))
742{
743 // nothing to do
744}
2dbc444a 745
e2478fde
VZ
746// ----------------------------------------------------------------------------
747// wxAppTraits
748// ----------------------------------------------------------------------------
749
6c4f5ea5 750#if wxUSE_INTL
d774f916
VZ
751void wxAppTraitsBase::SetLocale()
752{
d6f2a891 753 wxSetlocale(LC_ALL, "");
cb352236 754 wxUpdateLocaleIsUtf8();
d774f916 755}
6c4f5ea5 756#endif
d774f916 757
d254213e
PC
758#if wxUSE_THREADS
759void wxMutexGuiEnterImpl();
760void wxMutexGuiLeaveImpl();
761
762void wxAppTraitsBase::MutexGuiEnter()
763{
764 wxMutexGuiEnterImpl();
765}
766
767void wxAppTraitsBase::MutexGuiLeave()
768{
769 wxMutexGuiLeaveImpl();
770}
771
772void WXDLLIMPEXP_BASE wxMutexGuiEnter()
773{
96b2cbe8
VZ
774 wxAppTraits * const traits = wxAppConsoleBase::GetTraitsIfExists();
775 if ( traits )
776 traits->MutexGuiEnter();
d254213e
PC
777}
778
779void WXDLLIMPEXP_BASE wxMutexGuiLeave()
780{
96b2cbe8
VZ
781 wxAppTraits * const traits = wxAppConsoleBase::GetTraitsIfExists();
782 if ( traits )
783 traits->MutexGuiLeave();
d254213e
PC
784}
785#endif // wxUSE_THREADS
786
db9febdf 787bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal)
e2478fde 788{
657a8a35 789#if wxDEBUG_LEVEL
db9febdf
RR
790 wxString msg = msgOriginal;
791
792#if wxUSE_STACKWALKER
793#if !defined(__WXMSW__)
794 // on Unix stack frame generation may take some time, depending on the
795 // size of the executable mainly... warn the user that we are working
796 wxFprintf(stderr, wxT("[Debug] Generating a stack trace... please wait"));
797 fflush(stderr);
798#endif
799
800 const wxString stackTrace = GetAssertStackTrace();
801 if ( !stackTrace.empty() )
802 msg << _T("\n\nCall stack:\n") << stackTrace;
803#endif // wxUSE_STACKWALKER
804
e2478fde 805 return DoShowAssertDialog(msg);
657a8a35
VZ
806#else // !wxDEBUG_LEVEL
807 wxUnusedVar(msgOriginal);
808
809 return false;
810#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
e2478fde
VZ
811}
812
db9febdf
RR
813#if wxUSE_STACKWALKER
814wxString wxAppTraitsBase::GetAssertStackTrace()
815{
657a8a35 816#if wxDEBUG_LEVEL
db9febdf
RR
817 wxString stackTrace;
818
819 class StackDump : public wxStackWalker
820 {
821 public:
822 StackDump() { }
823
824 const wxString& GetStackTrace() const { return m_stackTrace; }
825
826 protected:
827 virtual void OnStackFrame(const wxStackFrame& frame)
828 {
829 m_stackTrace << wxString::Format
830 (
831 _T("[%02d] "),
832 wx_truncate_cast(int, frame.GetLevel())
833 );
834
835 wxString name = frame.GetName();
836 if ( !name.empty() )
837 {
838 m_stackTrace << wxString::Format(_T("%-40s"), name.c_str());
839 }
840 else
841 {
842 m_stackTrace << wxString::Format(_T("%p"), frame.GetAddress());
843 }
844
845 if ( frame.HasSourceLocation() )
846 {
847 m_stackTrace << _T('\t')
848 << frame.GetFileName()
849 << _T(':')
850 << frame.GetLine();
851 }
852
853 m_stackTrace << _T('\n');
854 }
855
856 private:
857 wxString m_stackTrace;
858 };
859
860 // don't show more than maxLines or we could get a dialog too tall to be
861 // shown on screen: 20 should be ok everywhere as even with 15 pixel high
862 // characters it is still only 300 pixels...
863 static const int maxLines = 20;
864
865 StackDump dump;
866 dump.Walk(2, maxLines); // don't show OnAssert() call itself
867 stackTrace = dump.GetStackTrace();
868
869 const int count = stackTrace.Freq(wxT('\n'));
870 for ( int i = 0; i < count - maxLines; i++ )
871 stackTrace = stackTrace.BeforeLast(wxT('\n'));
872
873 return stackTrace;
657a8a35
VZ
874#else // !wxDEBUG_LEVEL
875 // this function is still present for ABI-compatibility even in debug level
876 // 0 build but is not used there and so can simply do nothing
877 return wxString();
878#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
db9febdf
RR
879}
880#endif // wxUSE_STACKWALKER
881
882
e2478fde
VZ
883// ============================================================================
884// global functions implementation
885// ============================================================================
886
887void wxExit()
888{
889 if ( wxTheApp )
890 {
891 wxTheApp->Exit();
892 }
893 else
894 {
895 // what else can we do?
896 exit(-1);
897 }
898}
899
900void wxWakeUpIdle()
901{
902 if ( wxTheApp )
903 {
904 wxTheApp->WakeUpIdle();
905 }
906 //else: do nothing, what can we do?
907}
908
e2478fde
VZ
909// wxASSERT() helper
910bool wxAssertIsEqual(int x, int y)
911{
912 return x == y;
913}
914
657a8a35
VZ
915#if wxDEBUG_LEVEL
916
e2478fde
VZ
917// break into the debugger
918void wxTrap()
919{
920#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
921 DebugBreak();
f0756afe
DE
922#elif defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
923 Debugger();
e2478fde
VZ
924#elif defined(__UNIX__)
925 raise(SIGTRAP);
926#else
927 // TODO
928#endif // Win/Unix
929}
930
657a8a35
VZ
931// default assert handler
932static void
933wxDefaultAssertHandler(const wxString& file,
934 int line,
935 const wxString& func,
936 const wxString& cond,
937 const wxString& msg)
e2478fde
VZ
938{
939 // FIXME MT-unsafe
000eea7a 940 static int s_bInAssert = 0;
e2478fde 941
000eea7a
VZ
942 wxRecursionGuard guard(s_bInAssert);
943 if ( guard.IsInside() )
e2478fde 944 {
000eea7a 945 // can't use assert here to avoid infinite loops, so just trap
e2478fde
VZ
946 wxTrap();
947
e2478fde
VZ
948 return;
949 }
950
e2478fde
VZ
951 if ( !wxTheApp )
952 {
953 // by default, show the assert dialog box -- we can't customize this
954 // behaviour
657a8a35 955 ShowAssertDialog(file, line, func, cond, msg);
e2478fde
VZ
956 }
957 else
958 {
959 // let the app process it as it wants
0accd1cf 960 // FIXME-UTF8: use wc_str(), not c_str(), when ANSI build is removed
657a8a35
VZ
961 wxTheApp->OnAssertFailure(file.c_str(), line, func.c_str(),
962 cond.c_str(), msg.c_str());
e2478fde 963 }
e2478fde
VZ
964}
965
657a8a35
VZ
966wxAssertHandler_t wxTheAssertHandler = wxDefaultAssertHandler;
967
968void wxOnAssert(const wxString& file,
969 int line,
970 const wxString& func,
971 const wxString& cond,
972 const wxString& msg)
0accd1cf 973{
657a8a35 974 wxTheAssertHandler(file, line, func, cond, msg);
0accd1cf
VS
975}
976
657a8a35
VZ
977void wxOnAssert(const wxString& file,
978 int line,
979 const wxString& func,
980 const wxString& cond)
0accd1cf 981{
657a8a35 982 wxTheAssertHandler(file, line, func, cond, wxString());
0accd1cf
VS
983}
984
657a8a35
VZ
985void wxOnAssert(const wxChar *file,
986 int line,
987 const char *func,
988 const wxChar *cond,
989 const wxChar *msg)
0accd1cf 990{
657a8a35
VZ
991 // this is the backwards-compatible version (unless we don't use Unicode)
992 // so it could be called directly from the user code and this might happen
993 // even when wxTheAssertHandler is NULL
994#if wxUSE_UNICODE
995 if ( wxTheAssertHandler )
996#endif // wxUSE_UNICODE
997 wxTheAssertHandler(file, line, func, cond, msg);
0accd1cf
VS
998}
999
657a8a35
VZ
1000void wxOnAssert(const char *file,
1001 int line,
1002 const char *func,
1003 const char *cond,
1004 const wxString& msg)
fbaf7d45 1005{
657a8a35 1006 wxTheAssertHandler(file, line, func, cond, msg);
fbaf7d45
VS
1007}
1008
657a8a35
VZ
1009void wxOnAssert(const char *file,
1010 int line,
1011 const char *func,
1012 const char *cond,
2b232d20
VZ
1013 const wxCStrData& msg)
1014{
657a8a35 1015 wxTheAssertHandler(file, line, func, cond, msg);
2b232d20
VZ
1016}
1017
0accd1cf 1018#if wxUSE_UNICODE
657a8a35
VZ
1019void wxOnAssert(const char *file,
1020 int line,
1021 const char *func,
1022 const char *cond)
0accd1cf 1023{
657a8a35 1024 wxTheAssertHandler(file, line, func, cond, wxString());
0accd1cf
VS
1025}
1026
657a8a35
VZ
1027void wxOnAssert(const char *file,
1028 int line,
1029 const char *func,
1030 const char *cond,
1031 const char *msg)
0accd1cf 1032{
657a8a35 1033 wxTheAssertHandler(file, line, func, cond, msg);
0accd1cf
VS
1034}
1035
657a8a35
VZ
1036void wxOnAssert(const char *file,
1037 int line,
1038 const char *func,
1039 const char *cond,
1040 const wxChar *msg)
0accd1cf 1041{
657a8a35 1042 wxTheAssertHandler(file, line, func, cond, msg);
0accd1cf
VS
1043}
1044#endif // wxUSE_UNICODE
1045
657a8a35 1046#endif // wxDEBUG_LEVEL
e2478fde
VZ
1047
1048// ============================================================================
1049// private functions implementation
1050// ============================================================================
1051
1052#ifdef __WXDEBUG__
1053
1054static void LINKAGEMODE SetTraceMasks()
1055{
1056#if wxUSE_LOG
1057 wxString mask;
1058 if ( wxGetEnv(wxT("WXTRACE"), &mask) )
1059 {
1060 wxStringTokenizer tkn(mask, wxT(",;:"));
1061 while ( tkn.HasMoreTokens() )
1062 wxLog::AddTraceMask(tkn.GetNextToken());
1063 }
1064#endif // wxUSE_LOG
1065}
1066
657a8a35
VZ
1067#endif // __WXDEBUG__
1068
1069#if wxDEBUG_LEVEL
1070
6ef1b2a1 1071static
e2478fde
VZ
1072bool DoShowAssertDialog(const wxString& msg)
1073{
1074 // under MSW we can show the dialog even in the console mode
1075#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
1076 wxString msgDlg(msg);
1077
657a8a35
VZ
1078 // this message is intentionally not translated -- it is for developers
1079 // only -- and the less code we use here, less is the danger of recursively
1080 // asserting and dying
e2478fde
VZ
1081 msgDlg += wxT("\nDo you want to stop the program?\n")
1082 wxT("You can also choose [Cancel] to suppress ")
1083 wxT("further warnings.");
1084
e0a050e3 1085 switch ( ::MessageBox(NULL, msgDlg.wx_str(), _T("wxWidgets Debug Alert"),
e2478fde
VZ
1086 MB_YESNOCANCEL | MB_ICONSTOP ) )
1087 {
1088 case IDYES:
1089 wxTrap();
1090 break;
1091
1092 case IDCANCEL:
1093 // stop the asserts
1094 return true;
1095
1096 //case IDNO: nothing to do
1097 }
1098#else // !__WXMSW__
1099 wxFprintf(stderr, wxT("%s\n"), msg.c_str());
1100 fflush(stderr);
1101
1102 // TODO: ask the user to enter "Y" or "N" on the console?
1103 wxTrap();
1104#endif // __WXMSW__/!__WXMSW__
1105
1106 // continue with the asserts
1107 return false;
1108}
1109
657a8a35 1110// show the standard assert dialog
4a92d4bc 1111static
657a8a35
VZ
1112void ShowAssertDialog(const wxString& file,
1113 int line,
1114 const wxString& func,
1115 const wxString& cond,
1116 const wxString& msgUser,
4a92d4bc
VZ
1117 wxAppTraits *traits)
1118{
1119 // this variable can be set to true to suppress "assert failure" messages
1120 static bool s_bNoAsserts = false;
1121
1122 wxString msg;
1123 msg.reserve(2048);
1124
1125 // make life easier for people using VC++ IDE by using this format: like
1126 // this, clicking on the message will take us immediately to the place of
1127 // the failed assert
657a8a35 1128 msg.Printf(wxT("%s(%d): assert \"%s\" failed"), file, line, cond);
4a92d4bc 1129
dfa0b52f 1130 // add the function name, if any
657a8a35
VZ
1131 if ( !func.empty() )
1132 msg << _T(" in ") << func << _T("()");
dfa0b52f
VZ
1133
1134 // and the message itself
657a8a35 1135 if ( !msgUser.empty() )
2c9b3131 1136 {
657a8a35 1137 msg << _T(": ") << msgUser;
2c9b3131 1138 }
4a92d4bc
VZ
1139 else // no message given
1140 {
1141 msg << _T('.');
1142 }
1143
e2478fde
VZ
1144#if wxUSE_THREADS
1145 // if we are not in the main thread, output the assert directly and trap
1146 // since dialogs cannot be displayed
1147 if ( !wxThread::IsMain() )
1148 {
1149 msg += wxT(" [in child thread]");
1150
1151#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
1152 msg << wxT("\r\n");
e0a050e3 1153 OutputDebugString(msg.wx_str());
e2478fde
VZ
1154#else
1155 // send to stderr
1156 wxFprintf(stderr, wxT("%s\n"), msg.c_str());
1157 fflush(stderr);
1158#endif
1159 // He-e-e-e-elp!! we're asserting in a child thread
1160 wxTrap();
1161 }
6c8f8d92 1162 else
e2478fde
VZ
1163#endif // wxUSE_THREADS
1164
1165 if ( !s_bNoAsserts )
1166 {
1167 // send it to the normal log destination
56fae7b8 1168 wxLogDebug(_T("%s"), msg.c_str());
e2478fde
VZ
1169
1170 if ( traits )
1171 {
1172 // delegate showing assert dialog (if possible) to that class
1173 s_bNoAsserts = traits->ShowAssertDialog(msg);
1174 }
1175 else // no traits object
1176 {
1177 // fall back to the function of last resort
1178 s_bNoAsserts = DoShowAssertDialog(msg);
1179 }
1180 }
1181}
1182
657a8a35 1183#endif // wxDEBUG_LEVEL