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