]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/appbase.cpp
(blind) fix for gcc 3.4 warning for an always true comparison in an assert
[wxWidgets.git] / src / common / appbase.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: common/base/appbase.cpp
3// Purpose: implements wxAppConsole class
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>
9// License: wxWindows license
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
28 #include "wx/app.h"
29 #include "wx/intl.h"
30 #include "wx/list.h"
31 #if wxUSE_LOG
32 #include "wx/log.h"
33 #endif // wxUSE_LOG
34#endif //WX_PRECOMP
35
36#include "wx/utils.h"
37#include "wx/apptrait.h"
38#include "wx/cmdline.h"
39#include "wx/confbase.h"
40#include "wx/filename.h"
41#include "wx/msgout.h"
42#include "wx/tokenzr.h"
43
44#if !defined(__WXMSW__) || defined(__WXMICROWIN__)
45 #include <signal.h> // for SIGTRAP used by wxTrap()
46#endif //Win/Unix
47
48#if defined(__WXMSW__)
49 #include "wx/msw/wrapwin.h" // includes windows.h for MessageBox()
50#endif
51
52#if wxUSE_FONTMAP
53 #include "wx/fontmap.h"
54#endif // wxUSE_FONTMAP
55
56#if defined(__WXMAC__)
57 // VZ: MacTypes.h is enough under Mac OS X (where I could test it) but
58 // I don't know which headers are needed under earlier systems so
59 // include everything when in doubt
60 #ifdef __DARWIN__
61 #include "MacTypes.h"
62 #else
63 #include "wx/mac/private.h" // includes mac headers
64 #endif
65#endif // __WXMAC__
66
67// ----------------------------------------------------------------------------
68// private functions prototypes
69// ----------------------------------------------------------------------------
70
71#ifdef __WXDEBUG__
72 // really just show the assert dialog
73 static bool DoShowAssertDialog(const wxString& msg);
74
75 // prepare for showing the assert dialog, use the given traits or
76 // DoShowAssertDialog() as last fallback to really show it
77 static
78 void ShowAssertDialog(const wxChar *szFile,
79 int nLine,
80 const wxChar *szCond,
81 const wxChar *szMsg,
82 wxAppTraits *traits = NULL);
83
84 // turn on the trace masks specified in the env variable WXTRACE
85 static void LINKAGEMODE SetTraceMasks();
86#endif // __WXDEBUG__
87
88// ----------------------------------------------------------------------------
89// global vars
90// ----------------------------------------------------------------------------
91
92wxAppConsole *wxAppConsole::ms_appInstance = NULL;
93
94wxAppInitializerFunction wxAppConsole::ms_appInitFn = NULL;
95
96// ============================================================================
97// wxAppConsole implementation
98// ============================================================================
99
100// ----------------------------------------------------------------------------
101// ctor/dtor
102// ----------------------------------------------------------------------------
103
104wxAppConsole::wxAppConsole()
105{
106 m_traits = NULL;
107
108 ms_appInstance = this;
109
110#ifdef __WXDEBUG__
111 SetTraceMasks();
112#if wxUSE_UNICODE
113 // In unicode mode the SetTraceMasks call can cause an apptraits to be
114 // created, but since we are still in the constructor the wrong kind will
115 // be created for GUI apps. Destroy it so it can be created again later.
116 delete m_traits;
117 m_traits = NULL;
118#endif
119#endif
120}
121
122wxAppConsole::~wxAppConsole()
123{
124 delete m_traits;
125}
126
127// ----------------------------------------------------------------------------
128// initilization/cleanup
129// ----------------------------------------------------------------------------
130
131bool wxAppConsole::Initialize(int& argc, wxChar **argv)
132{
133 // remember the command line arguments
134 this->argc = argc;
135 this->argv = argv;
136
137 if ( m_appName.empty() && argv )
138 {
139 // the application name is, by default, the name of its executable file
140 wxFileName::SplitPath(argv[0], NULL, &m_appName, NULL);
141 }
142
143 return true;
144}
145
146void wxAppConsole::CleanUp()
147{
148}
149
150// ----------------------------------------------------------------------------
151// OnXXX() callbacks
152// ----------------------------------------------------------------------------
153
154bool wxAppConsole::OnInit()
155{
156#if wxUSE_CMDLINE_PARSER
157 wxCmdLineParser parser(argc, argv);
158
159 OnInitCmdLine(parser);
160
161 bool cont;
162 switch ( parser.Parse(FALSE /* don't show usage */) )
163 {
164 case -1:
165 cont = OnCmdLineHelp(parser);
166 break;
167
168 case 0:
169 cont = OnCmdLineParsed(parser);
170 break;
171
172 default:
173 cont = OnCmdLineError(parser);
174 break;
175 }
176
177 if ( !cont )
178 return FALSE;
179#endif // wxUSE_CMDLINE_PARSER
180
181 return TRUE;
182}
183
184int wxAppConsole::OnExit()
185{
186#if wxUSE_CONFIG
187 // delete the config object if any (don't use Get() here, but Set()
188 // because Get() could create a new config object)
189 delete wxConfigBase::Set((wxConfigBase *) NULL);
190#endif // wxUSE_CONFIG
191
192 // use Set(NULL) and not Get() to avoid creating a message output object on
193 // demand when we just want to delete it
194 delete wxMessageOutput::Set(NULL);
195
196 return 0;
197}
198
199void wxAppConsole::Exit()
200{
201 exit(-1);
202}
203
204// ----------------------------------------------------------------------------
205// traits stuff
206// ----------------------------------------------------------------------------
207
208wxAppTraits *wxAppConsole::CreateTraits()
209{
210 return new wxConsoleAppTraits;
211}
212
213wxAppTraits *wxAppConsole::GetTraits()
214{
215 // FIXME-MT: protect this with a CS?
216 if ( !m_traits )
217 {
218 m_traits = CreateTraits();
219
220 wxASSERT_MSG( m_traits, _T("wxApp::CreateTraits() failed?") );
221 }
222
223 return m_traits;
224}
225
226// we must implement CreateXXX() in wxApp itself for backwards compatibility
227#if WXWIN_COMPATIBILITY_2_4
228
229#if wxUSE_LOG
230
231wxLog *wxAppConsole::CreateLogTarget()
232{
233 wxAppTraits *traits = GetTraits();
234 return traits ? traits->CreateLogTarget() : NULL;
235}
236
237#endif // wxUSE_LOG
238
239wxMessageOutput *wxAppConsole::CreateMessageOutput()
240{
241 wxAppTraits *traits = GetTraits();
242 return traits ? traits->CreateMessageOutput() : NULL;
243}
244
245#endif // WXWIN_COMPATIBILITY_2_4
246
247// ----------------------------------------------------------------------------
248// event processing
249// ----------------------------------------------------------------------------
250
251void wxAppConsole::ProcessPendingEvents()
252{
253 // ensure that we're the only thread to modify the pending events list
254 wxENTER_CRIT_SECT( *wxPendingEventsLocker );
255
256 if ( !wxPendingEvents )
257 {
258 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
259 return;
260 }
261
262 // iterate until the list becomes empty
263 wxList::compatibility_iterator node = wxPendingEvents->GetFirst();
264 while (node)
265 {
266 wxEvtHandler *handler = (wxEvtHandler *)node->GetData();
267 wxPendingEvents->Erase(node);
268
269 // In ProcessPendingEvents(), new handlers might be add
270 // and we can safely leave the critical section here.
271 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
272 handler->ProcessPendingEvents();
273 wxENTER_CRIT_SECT( *wxPendingEventsLocker );
274
275 node = wxPendingEvents->GetFirst();
276 }
277
278 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
279}
280
281int wxAppConsole::FilterEvent(wxEvent& WXUNUSED(event))
282{
283 // process the events normally by default
284 return -1;
285}
286
287// ----------------------------------------------------------------------------
288// exception handling
289// ----------------------------------------------------------------------------
290
291#if wxUSE_EXCEPTIONS
292
293void
294wxAppConsole::HandleEvent(wxEvtHandler *handler,
295 wxEventFunction func,
296 wxEvent& event) const
297{
298 // by default, simply call the handler
299 (handler->*func)(event);
300}
301
302bool
303wxAppConsole::OnExceptionInMainLoop()
304{
305 throw;
306
307 // some compilers are too stupid to know that we never return after throw
308#if defined(__DMC__) || (defined(_MSC_VER) && _MSC_VER < 1200)
309 return false;
310#endif
311}
312
313#endif // wxUSE_EXCEPTIONS
314
315// ----------------------------------------------------------------------------
316// cmd line parsing
317// ----------------------------------------------------------------------------
318
319#if wxUSE_CMDLINE_PARSER
320
321#define OPTION_VERBOSE _T("verbose")
322
323void wxAppConsole::OnInitCmdLine(wxCmdLineParser& parser)
324{
325 // the standard command line options
326 static const wxCmdLineEntryDesc cmdLineDesc[] =
327 {
328 {
329 wxCMD_LINE_SWITCH,
330 _T("h"),
331 _T("help"),
332 gettext_noop("show this help message"),
333 wxCMD_LINE_VAL_NONE,
334 wxCMD_LINE_OPTION_HELP
335 },
336
337#if wxUSE_LOG
338 {
339 wxCMD_LINE_SWITCH,
340 _T(""),
341 OPTION_VERBOSE,
342 gettext_noop("generate verbose log messages"),
343 wxCMD_LINE_VAL_NONE,
344 0x0
345 },
346#endif // wxUSE_LOG
347
348 // terminator
349 {
350 wxCMD_LINE_NONE,
351 _T(""),
352 _T(""),
353 _T(""),
354 wxCMD_LINE_VAL_NONE,
355 0x0
356 }
357 };
358
359 parser.SetDesc(cmdLineDesc);
360}
361
362bool wxAppConsole::OnCmdLineParsed(wxCmdLineParser& parser)
363{
364#if wxUSE_LOG
365 if ( parser.Found(OPTION_VERBOSE) )
366 {
367 wxLog::SetVerbose(TRUE);
368 }
369#endif // wxUSE_LOG
370
371 return TRUE;
372}
373
374bool wxAppConsole::OnCmdLineHelp(wxCmdLineParser& parser)
375{
376 parser.Usage();
377
378 return FALSE;
379}
380
381bool wxAppConsole::OnCmdLineError(wxCmdLineParser& parser)
382{
383 parser.Usage();
384
385 return FALSE;
386}
387
388#endif // wxUSE_CMDLINE_PARSER
389
390// ----------------------------------------------------------------------------
391// debugging support
392// ----------------------------------------------------------------------------
393
394/* static */
395bool wxAppConsole::CheckBuildOptions(const char *optionsSignature,
396 const char *componentName)
397{
398#if 0 // can't use wxLogTrace, not up and running yet
399 printf("checking build options object '%s' (ptr %p) in '%s'\n",
400 optionsSignature, optionsSignature, componentName);
401#endif
402
403 if ( strcmp(optionsSignature, WX_BUILD_OPTIONS_SIGNATURE) != 0 )
404 {
405 wxString lib = wxString::FromAscii(WX_BUILD_OPTIONS_SIGNATURE);
406 wxString prog = wxString::FromAscii(optionsSignature);
407 wxString progName = wxString::FromAscii(componentName);
408 wxString msg;
409
410 msg.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."),
411 lib.c_str(), progName.c_str(), prog.c_str());
412
413 wxLogFatalError(msg);
414
415 // normally wxLogFatalError doesn't return
416 return FALSE;
417 }
418#undef wxCMP
419
420 return TRUE;
421}
422
423#ifdef __WXDEBUG__
424
425void wxAppConsole::OnAssert(const wxChar *file,
426 int line,
427 const wxChar *cond,
428 const wxChar *msg)
429{
430 ShowAssertDialog(file, line, cond, msg, GetTraits());
431}
432
433#endif // __WXDEBUG__
434
435// ============================================================================
436// other classes implementations
437// ============================================================================
438
439// ----------------------------------------------------------------------------
440// wxConsoleAppTraitsBase
441// ----------------------------------------------------------------------------
442
443#if wxUSE_LOG
444
445wxLog *wxConsoleAppTraitsBase::CreateLogTarget()
446{
447 return new wxLogStderr;
448}
449
450#endif // wxUSE_LOG
451
452wxMessageOutput *wxConsoleAppTraitsBase::CreateMessageOutput()
453{
454 return new wxMessageOutputStderr;
455}
456
457#if wxUSE_FONTMAP
458
459wxFontMapper *wxConsoleAppTraitsBase::CreateFontMapper()
460{
461 return (wxFontMapper *)new wxFontMapperBase;
462}
463
464#endif // wxUSE_FONTMAP
465
466wxRendererNative *wxConsoleAppTraitsBase::CreateRenderer()
467{
468 // console applications don't use renderers
469 return NULL;
470}
471
472#ifdef __WXDEBUG__
473bool wxConsoleAppTraitsBase::ShowAssertDialog(const wxString& msg)
474{
475 return wxAppTraitsBase::ShowAssertDialog(msg);
476}
477#endif
478
479bool wxConsoleAppTraitsBase::HasStderr()
480{
481 // console applications always have stderr, even under Mac/Windows
482 return true;
483}
484
485void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject *object)
486{
487 delete object;
488}
489
490void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject * WXUNUSED(object))
491{
492 // nothing to do
493}
494
495#if wxUSE_SOCKETS
496GSocketGUIFunctionsTable* wxConsoleAppTraitsBase::GetSocketGUIFunctionsTable()
497{
498 return NULL;
499}
500#endif
501
502// ----------------------------------------------------------------------------
503// wxAppTraits
504// ----------------------------------------------------------------------------
505
506#ifdef __WXDEBUG__
507
508bool wxAppTraitsBase::ShowAssertDialog(const wxString& msg)
509{
510 return DoShowAssertDialog(msg);
511}
512
513#endif // __WXDEBUG__
514
515// ============================================================================
516// global functions implementation
517// ============================================================================
518
519void wxExit()
520{
521 if ( wxTheApp )
522 {
523 wxTheApp->Exit();
524 }
525 else
526 {
527 // what else can we do?
528 exit(-1);
529 }
530}
531
532void wxWakeUpIdle()
533{
534 if ( wxTheApp )
535 {
536 wxTheApp->WakeUpIdle();
537 }
538 //else: do nothing, what can we do?
539}
540
541#ifdef __WXDEBUG__
542
543// wxASSERT() helper
544bool wxAssertIsEqual(int x, int y)
545{
546 return x == y;
547}
548
549// break into the debugger
550void wxTrap()
551{
552#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
553 DebugBreak();
554#elif defined(__WXMAC__) && !defined(__DARWIN__)
555 #if __powerc
556 Debugger();
557 #else
558 SysBreak();
559 #endif
560#elif defined(__UNIX__)
561 raise(SIGTRAP);
562#else
563 // TODO
564#endif // Win/Unix
565}
566
567void wxAssert(int cond,
568 const wxChar *szFile,
569 int nLine,
570 const wxChar *szCond,
571 const wxChar *szMsg)
572{
573 if ( !cond )
574 wxOnAssert(szFile, nLine, szCond, szMsg);
575}
576
577// this function is called when an assert fails
578void wxOnAssert(const wxChar *szFile,
579 int nLine,
580 const wxChar *szCond,
581 const wxChar *szMsg)
582{
583 // FIXME MT-unsafe
584 static bool s_bInAssert = FALSE;
585
586 if ( s_bInAssert )
587 {
588 // He-e-e-e-elp!! we're trapped in endless loop
589 wxTrap();
590
591 s_bInAssert = FALSE;
592
593 return;
594 }
595
596 s_bInAssert = TRUE;
597
598 if ( !wxTheApp )
599 {
600 // by default, show the assert dialog box -- we can't customize this
601 // behaviour
602 ShowAssertDialog(szFile, nLine, szCond, szMsg);
603 }
604 else
605 {
606 // let the app process it as it wants
607 wxTheApp->OnAssert(szFile, nLine, szCond, szMsg);
608 }
609
610 s_bInAssert = FALSE;
611}
612
613#endif // __WXDEBUG__
614
615// ============================================================================
616// private functions implementation
617// ============================================================================
618
619#ifdef __WXDEBUG__
620
621static void LINKAGEMODE SetTraceMasks()
622{
623#if wxUSE_LOG
624 wxString mask;
625 if ( wxGetEnv(wxT("WXTRACE"), &mask) )
626 {
627 wxStringTokenizer tkn(mask, wxT(",;:"));
628 while ( tkn.HasMoreTokens() )
629 wxLog::AddTraceMask(tkn.GetNextToken());
630 }
631#endif // wxUSE_LOG
632}
633
634bool DoShowAssertDialog(const wxString& msg)
635{
636 // under MSW we can show the dialog even in the console mode
637#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
638 wxString msgDlg(msg);
639
640 // this message is intentionally not translated -- it is for
641 // developpers only
642 msgDlg += wxT("\nDo you want to stop the program?\n")
643 wxT("You can also choose [Cancel] to suppress ")
644 wxT("further warnings.");
645
646 switch ( ::MessageBox(NULL, msgDlg, _T("wxWindows Debug Alert"),
647 MB_YESNOCANCEL | MB_ICONSTOP ) )
648 {
649 case IDYES:
650 wxTrap();
651 break;
652
653 case IDCANCEL:
654 // stop the asserts
655 return true;
656
657 //case IDNO: nothing to do
658 }
659#else // !__WXMSW__
660 wxFprintf(stderr, wxT("%s\n"), msg.c_str());
661 fflush(stderr);
662
663 // TODO: ask the user to enter "Y" or "N" on the console?
664 wxTrap();
665#endif // __WXMSW__/!__WXMSW__
666
667 // continue with the asserts
668 return false;
669}
670
671// show the assert modal dialog
672static
673void ShowAssertDialog(const wxChar *szFile,
674 int nLine,
675 const wxChar *szCond,
676 const wxChar *szMsg,
677 wxAppTraits *traits)
678{
679 // this variable can be set to true to suppress "assert failure" messages
680 static bool s_bNoAsserts = FALSE;
681
682 wxString msg;
683 msg.reserve(2048);
684
685 // make life easier for people using VC++ IDE by using this format: like
686 // this, clicking on the message will take us immediately to the place of
687 // the failed assert
688 msg.Printf(wxT("%s(%d): assert \"%s\" failed"), szFile, nLine, szCond);
689
690 if ( szMsg )
691 {
692 msg << _T(": ") << szMsg;
693 }
694 else // no message given
695 {
696 msg << _T('.');
697 }
698
699#if wxUSE_THREADS
700 // if we are not in the main thread, output the assert directly and trap
701 // since dialogs cannot be displayed
702 if ( !wxThread::IsMain() )
703 {
704 msg += wxT(" [in child thread]");
705
706#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
707 msg << wxT("\r\n");
708 OutputDebugString(msg );
709#else
710 // send to stderr
711 wxFprintf(stderr, wxT("%s\n"), msg.c_str());
712 fflush(stderr);
713#endif
714 // He-e-e-e-elp!! we're asserting in a child thread
715 wxTrap();
716 }
717#endif // wxUSE_THREADS
718
719 if ( !s_bNoAsserts )
720 {
721 // send it to the normal log destination
722 wxLogDebug(_T("%s"), msg.c_str());
723
724 if ( traits )
725 {
726 // delegate showing assert dialog (if possible) to that class
727 s_bNoAsserts = traits->ShowAssertDialog(msg);
728 }
729 else // no traits object
730 {
731 // fall back to the function of last resort
732 s_bNoAsserts = DoShowAssertDialog(msg);
733 }
734 }
735}
736
737#endif // __WXDEBUG__
738