X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b1d4dd7add411ebff1ce4a8d1d992e0e43ee26b1..02d5015b1cbb99d7a2e2ab7818cd46b2b4514957:/src/common/appcmn.cpp diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 70d6b43e57..e6a72a3d27 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/appcmn.cpp -// Purpose: wxAppBase methods common to all platforms +// Name: src/common/appcmn.cpp +// Purpose: wxAppConsole and wxAppBase methods common to all platforms // Author: Vadim Zeitlin // Modified by: // Created: 18.10.99 @@ -17,10 +17,6 @@ // headers // --------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "appbase.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -30,64 +26,67 @@ #ifndef WX_PRECOMP #include "wx/app.h" - #include "wx/intl.h" - #include "wx/list.h" - #if wxUSE_LOG - #include "wx/log.h" - #endif // wxUSE_LOG - #if wxUSE_GUI - #include "wx/msgdlg.h" - #endif // wxUSE_GUI + #include "wx/window.h" + #include "wx/bitmap.h" + #include "wx/log.h" + #include "wx/msgdlg.h" + #include "wx/confbase.h" + #include "wx/utils.h" #endif +#include "wx/apptrait.h" #include "wx/cmdline.h" -#include "wx/thread.h" -#include "wx/confbase.h" -#include "wx/tokenzr.h" -#include "wx/utils.h" +#include "wx/evtloop.h" #include "wx/msgout.h" +#include "wx/thread.h" +#include "wx/vidmode.h" +#include "wx/ptr_scpd.h" -#if wxUSE_GUI - #include "wx/artprov.h" -#endif // wxUSE_GUI - -#if !defined(__WXMSW__) || defined(__WXMICROWIN__) - #include // for SIGTRAP used by wxTrap() -#endif //Win/Unix +#ifdef __WXDEBUG__ + #if wxUSE_STACKWALKER + #include "wx/stackwalk.h" + #endif // wxUSE_STACKWALKER +#endif // __WXDEBUG__ #if defined(__WXMSW__) - #include "wx/msw/private.h" // includes windows.h for MessageBox() + #include "wx/msw/private.h" // includes windows.h for LOGFONT #endif -#if defined(__WXMAC__) - #include "wx/mac/private.h" // includes mac headers -#endif +#if wxUSE_FONTMAP + #include "wx/fontmap.h" +#endif // wxUSE_FONTMAP -// private functions prototypes -#ifdef __WXDEBUG__ - static void LINKAGEMODE SetTraceMasks(); -#endif // __WXDEBUG__ +// DLL options compatibility check: +#include "wx/build.h" +WX_CHECK_BUILD_OPTIONS("wxCore") -// =========================================================================== -// implementation -// =========================================================================== +WXDLLIMPEXP_DATA_CORE(wxList) wxPendingDelete; // ---------------------------------------------------------------------------- -// initialization and termination +// wxEventLoopPtr // ---------------------------------------------------------------------------- -wxAppBase::wxAppBase() -{ - wxTheApp = (wxApp *)this; +// this defines wxEventLoopPtr +wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop) -#if WXWIN_COMPATIBILITY_2_2 - m_wantDebugOutput = FALSE; -#endif // WXWIN_COMPATIBILITY_2_2 +// ============================================================================ +// wxAppBase implementation +// ============================================================================ -#if wxUSE_GUI +// ---------------------------------------------------------------------------- +// initialization +// ---------------------------------------------------------------------------- + +wxAppBase::wxAppBase() +{ m_topWindow = (wxWindow *)NULL; - m_useBestVisual = FALSE; - m_isActive = TRUE; + + m_useBestVisual = false; + m_forceTrueColour = false; + + m_isActive = true; + + m_mainLoop = NULL; // We don't want to exit the app if the user code shows a dialog from its // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete @@ -95,237 +94,134 @@ wxAppBase::wxAppBase() // OTOH, if we set it to No initially we'll have to overwrite it with Yes // when we enter our OnRun() because we do want the default behaviour from // then on. But this would be a problem if the user code calls - // SetExitOnFrameDelete(FALSE) from OnInit(). + // SetExitOnFrameDelete(false) from OnInit(). // // So we use the special "Later" value which is such that - // GetExitOnFrameDelete() returns FALSE for it but which we know we can + // GetExitOnFrameDelete() returns false for it but which we know we can // safely (i.e. without losing the effect of the users SetExitOnFrameDelete // call) overwrite in OnRun() m_exitOnFrameDelete = Later; -#endif // wxUSE_GUI - -#ifdef __WXDEBUG__ - SetTraceMasks(); -#endif -} - -wxAppBase::~wxAppBase() -{ - // this destructor is required for Darwin -} - -#if wxUSE_GUI - -bool wxAppBase::OnInitGui() -{ -#ifdef __WXUNIVERSAL__ - if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) - return FALSE; -#endif // __WXUNIVERSAL__ - - return TRUE; } -int wxAppBase::OnRun() +bool wxAppBase::Initialize(int& argcOrig, wxChar **argvOrig) { - // see the comment in ctor: if the initial value hasn't been changed, use - // the default Yes from now on - if ( m_exitOnFrameDelete == Later ) - { - m_exitOnFrameDelete = Yes; - } - //else: it has been changed, assume the user knows what he is doing + if ( !wxAppConsole::Initialize(argcOrig, argvOrig) ) + return false; - return MainLoop(); -} +#if wxUSE_THREADS + wxPendingEventsLocker = new wxCriticalSection; +#endif -#endif // wxUSE_GUI + wxInitializeStockLists(); -int wxAppBase::OnExit() -{ -#if wxUSE_CONFIG - // delete the config object if any (don't use Get() here, but Set() - // because Get() could create a new config object) - delete wxConfigBase::Set((wxConfigBase *) NULL); -#endif // wxUSE_CONFIG + wxBitmap::InitStandardHandlers(); -#ifdef __WXUNIVERSAL__ - delete wxTheme::Set(NULL); -#endif // __WXUNIVERSAL__ - - // use Set(NULL) and not Get() to avoid creating a message output object on - // demand when we just want to delete it - delete wxMessageOutput::Set(NULL); - - return 0; + return true; } // ---------------------------------------------------------------------------- -// customization hooks +// cleanup // ---------------------------------------------------------------------------- -#if wxUSE_LOG - -wxLog *wxAppBase::CreateLogTarget() -{ -#if wxUSE_GUI && wxUSE_LOGGUI && !defined(__WXMICROWIN__) - return new wxLogGui; -#else // !GUI - return new wxLogStderr; -#endif // wxUSE_GUI -} - -#endif // wxUSE_LOG - -wxMessageOutput *wxAppBase::CreateMessageOutput() +wxAppBase::~wxAppBase() { - // The standard way of printing help on command line arguments (app --help) - // is (according to common practice): - // - console apps: to stderr (on any platform) - // - GUI apps: stderr on Unix platforms (!) - // message box under Windows and others -#if wxUSE_GUI && !defined(__UNIX__) - // wxMessageOutputMessageBox doesn't work under Motif - #ifdef __WXMOTIF__ - return new wxMessageOutputLog; - #else - return new wxMessageOutputMessageBox; - #endif -#else // !wxUSE_GUI || __UNIX__ - return new wxMessageOutputStderr; -#endif + // this destructor is required for Darwin } -// --------------------------------------------------------------------------- -// wxAppBase -// ---------------------------------------------------------------------------- - -void wxAppBase::ProcessPendingEvents() +void wxAppBase::CleanUp() { - // ensure that we're the only thread to modify the pending events list - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + // clean up all the pending objects + DeletePendingObjects(); - if ( !wxPendingEvents ) + // and any remaining TLWs (they remove themselves from wxTopLevelWindows + // when destroyed, so iterate until none are left) + while ( !wxTopLevelWindows.empty() ) { - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); - return; + // do not use Destroy() here as it only puts the TLW in pending list + // but we want to delete them now + delete wxTopLevelWindows.GetFirst()->GetData(); } - // iterate until the list becomes empty - wxNode *node = wxPendingEvents->GetFirst(); - while (node) - { - wxEvtHandler *handler = (wxEvtHandler *)node->GetData(); - delete node; + // undo everything we did in Initialize() above + wxBitmap::CleanUpHandlers(); - // In ProcessPendingEvents(), new handlers might be add - // and we can safely leave the critical section here. - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); - handler->ProcessPendingEvents(); - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + wxStockGDI::DeleteAll(); - node = wxPendingEvents->GetFirst(); - } + wxDeleteStockLists(); + + delete wxTheColourDatabase; + wxTheColourDatabase = NULL; + + delete wxPendingEvents; + wxPendingEvents = NULL; + +#if wxUSE_THREADS + delete wxPendingEventsLocker; + wxPendingEventsLocker = NULL; - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); + #if wxUSE_VALIDATORS + // If we don't do the following, we get an apparent memory leak. + ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); + #endif // wxUSE_VALIDATORS +#endif // wxUSE_THREADS } // ---------------------------------------------------------------------------- -// misc +// various accessors // ---------------------------------------------------------------------------- -#if wxUSE_GUI - -void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus)) +wxWindow* wxAppBase::GetTopWindow() const { - if ( active == m_isActive ) - return; - - m_isActive = active; - - wxActivateEvent event(wxEVT_ACTIVATE_APP, active); - event.SetEventObject(this); - - (void)ProcessEvent(event); + wxWindow* window = m_topWindow; + if (window == NULL && wxTopLevelWindows.GetCount() > 0) + window = wxTopLevelWindows.GetFirst()->GetData(); + return window; } -#endif // wxUSE_GUI - -int wxAppBase::FilterEvent(wxEvent& WXUNUSED(event)) +wxVideoMode wxAppBase::GetDisplayMode() const { - // process the events normally by default - return -1; + return wxVideoMode(); } -// ---------------------------------------------------------------------------- -// cmd line parsing -// ---------------------------------------------------------------------------- - -bool wxAppBase::OnInit() +wxLayoutDirection wxAppBase::GetLayoutDirection() const { -#if wxUSE_CMDLINE_PARSER - wxCmdLineParser parser(argc, argv); - - OnInitCmdLine(parser); - - bool cont; - switch ( parser.Parse(FALSE /* don't show usage */) ) +#if wxUSE_INTL + const wxLocale *const locale = wxGetLocale(); + if ( locale ) { - case -1: - cont = OnCmdLineHelp(parser); - break; - - case 0: - cont = OnCmdLineParsed(parser); - break; + const wxLanguageInfo *const + info = wxLocale::GetLanguageInfo(locale->GetLanguage()); - default: - cont = OnCmdLineError(parser); - break; + if ( info ) + return info->LayoutDirection; } +#endif // wxUSE_INTL - if ( !cont ) - return FALSE; -#endif // wxUSE_CMDLINE_PARSER - - return TRUE; + // we don't know + return wxLayout_Default; } #if wxUSE_CMDLINE_PARSER -#define OPTION_VERBOSE _T("verbose") +// ---------------------------------------------------------------------------- +// GUI-specific command line options handling +// ---------------------------------------------------------------------------- + #define OPTION_THEME _T("theme") #define OPTION_MODE _T("mode") void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser) { + // first add the standard non GUI options + wxAppConsole::OnInitCmdLine(parser); + // the standard command line options - static const wxCmdLineEntryDesc cmdLineDesc[] = + static const wxCmdLineEntryDesc cmdLineGUIDesc[] = { - { - wxCMD_LINE_SWITCH, - _T("h"), - _T("help"), - gettext_noop("show this help message"), - wxCMD_LINE_VAL_NONE, - wxCMD_LINE_OPTION_HELP - }, - -#if wxUSE_LOG - { - wxCMD_LINE_SWITCH, - _T(""), - OPTION_VERBOSE, - gettext_noop("generate verbose log messages"), - wxCMD_LINE_VAL_NONE, - 0x0 - }, -#endif // wxUSE_LOG - #ifdef __WXUNIVERSAL__ { wxCMD_LINE_OPTION, - _T(""), + wxEmptyString, OPTION_THEME, gettext_noop("specify the theme to use"), wxCMD_LINE_VAL_STRING, @@ -339,7 +235,7 @@ void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser) // and not mgl/app.cpp { wxCMD_LINE_OPTION, - _T(""), + wxEmptyString, OPTION_MODE, gettext_noop("specify display mode to use (e.g. 640x480-16)"), wxCMD_LINE_VAL_STRING, @@ -350,26 +246,19 @@ void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser) // terminator { wxCMD_LINE_NONE, - _T(""), - _T(""), - _T(""), + wxEmptyString, + wxEmptyString, + wxEmptyString, wxCMD_LINE_VAL_NONE, 0x0 } }; - parser.SetDesc(cmdLineDesc); + parser.SetDesc(cmdLineGUIDesc); } bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser) { -#if wxUSE_LOG - if ( parser.Found(OPTION_VERBOSE) ) - { - wxLog::SetVerbose(TRUE); - } -#endif // wxUSE_LOG - #ifdef __WXUNIVERSAL__ wxString themeName; if ( parser.Found(OPTION_THEME, &themeName) ) @@ -378,8 +267,7 @@ bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser) if ( !theme ) { wxLogError(_("Unsupported theme '%s'."), themeName.c_str()); - - return FALSE; + return false; } // Delete the defaultly created theme and set the new theme. @@ -396,251 +284,388 @@ bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser) if ( wxSscanf(modeDesc.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3 ) { wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str()); - - return FALSE; + return false; } - if ( !SetDisplayMode(wxDisplayModeInfo(w, h, bpp)) ) - return FALSE; + if ( !SetDisplayMode(wxVideoMode(w, h, bpp)) ) + return false; } #endif // __WXMGL__ - return TRUE; + return wxAppConsole::OnCmdLineParsed(parser); } -bool wxAppBase::OnCmdLineHelp(wxCmdLineParser& parser) +#endif // wxUSE_CMDLINE_PARSER + +// ---------------------------------------------------------------------------- +// main event loop implementation +// ---------------------------------------------------------------------------- + +int wxAppBase::MainLoop() { - parser.Usage(); + wxEventLoopTiedPtr mainLoop(&m_mainLoop, new wxEventLoop); - return FALSE; + return m_mainLoop->Run(); } -bool wxAppBase::OnCmdLineError(wxCmdLineParser& parser) +void wxAppBase::ExitMainLoop() { - parser.Usage(); + // we should exit from the main event loop, not just any currently active + // (e.g. modal dialog) event loop + if ( m_mainLoop && m_mainLoop->IsRunning() ) + { + m_mainLoop->Exit(0); + } +} + +bool wxAppBase::Pending() +{ + // use the currently active message loop here, not m_mainLoop, because if + // we're showing a modal dialog (with its own event loop) currently the + // main event loop is not running anyhow + wxEventLoop * const loop = wxEventLoop::GetActive(); - return FALSE; + return loop && loop->Pending(); } -#endif // wxUSE_CMDLINE_PARSER +bool wxAppBase::Dispatch() +{ + // see comment in Pending() + wxEventLoop * const loop = wxEventLoop::GetActive(); + + return loop && loop->Dispatch(); +} // ---------------------------------------------------------------------------- -// debugging support +// OnXXX() hooks // ---------------------------------------------------------------------------- -/* static */ -bool wxAppBase::CheckBuildOptions(const wxBuildOptions& opts) +bool wxAppBase::OnInitGui() { -#define wxCMP(what) (what == opts.m_ ## what) - - bool -#ifdef __WXDEBUG__ - isDebug = TRUE; -#else - isDebug = FALSE; -#endif +#ifdef __WXUNIVERSAL__ + if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) + return false; +#endif // __WXUNIVERSAL__ - int verMaj = wxMAJOR_VERSION, - verMin = wxMINOR_VERSION; + return true; +} - if ( !(wxCMP(isDebug) && wxCMP(verMaj) && wxCMP(verMin)) ) +int wxAppBase::OnRun() +{ + // see the comment in ctor: if the initial value hasn't been changed, use + // the default Yes from now on + if ( m_exitOnFrameDelete == Later ) { - wxString msg; - wxString libDebug, progDebug; - - if (isDebug) - libDebug = wxT("debug"); - else - libDebug = wxT("no debug"); - - if (opts.m_isDebug) - progDebug = wxT("debug"); - else - progDebug = wxT("no debug"); - - 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)."), - verMaj, verMin, libDebug.c_str(), opts.m_verMaj, opts.m_verMin, progDebug.c_str()); - - wxLogFatalError(msg); - - // normally wxLogFatalError doesn't return - return FALSE; + m_exitOnFrameDelete = Yes; } -#undef wxCMP + //else: it has been changed, assume the user knows what he is doing - return TRUE; + return MainLoop(); } -#ifdef __WXDEBUG__ +int wxAppBase::OnExit() +{ +#ifdef __WXUNIVERSAL__ + delete wxTheme::Set(NULL); +#endif // __WXUNIVERSAL__ + + return wxAppConsole::OnExit(); +} -static void LINKAGEMODE SetTraceMasks() +void wxAppBase::Exit() { -#if wxUSE_LOG - wxString mask; - if ( wxGetEnv(wxT("WXTRACE"), &mask) ) - { - wxStringTokenizer tkn(mask, wxT(",")); - while ( tkn.HasMoreTokens() ) - wxLog::AddTraceMask(tkn.GetNextToken()); - } -#endif // wxUSE_LOG + ExitMainLoop(); } -// wxASSERT() helper -bool wxAssertIsEqual(int x, int y) +wxAppTraits *wxAppBase::CreateTraits() { - return x == y; + return new wxGUIAppTraits; } -// break into the debugger -void wxTrap() +// ---------------------------------------------------------------------------- +// misc +// ---------------------------------------------------------------------------- + +void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus)) { -#if defined(__WXMSW__) && !defined(__WXMICROWIN__) - DebugBreak(); -#elif defined(__WXMAC__) && !defined(__DARWIN__) -#if __powerc - Debugger(); -#else - SysBreak(); -#endif -#elif defined(__UNIX__) - raise(SIGTRAP); -#else - // TODO -#endif // Win/Unix + if ( active == m_isActive ) + return; + + m_isActive = active; + + wxActivateEvent event(wxEVT_ACTIVATE_APP, active); + event.SetEventObject(this); + + (void)ProcessEvent(event); } +// ---------------------------------------------------------------------------- +// idle handling +// ---------------------------------------------------------------------------- -void wxAssert(int cond, - const wxChar *szFile, - int nLine, - const wxChar *szCond, - const wxChar *szMsg) +void wxAppBase::DeletePendingObjects() { - if ( !cond ) - wxOnAssert(szFile, nLine, szCond, szMsg); + wxList::compatibility_iterator node = wxPendingDelete.GetFirst(); + while (node) + { + wxObject *obj = node->GetData(); + + // remove it from the list first so that if we get back here somehow + // during the object deletion (e.g. wxYield called from its dtor) we + // wouldn't try to delete it the second time + if ( wxPendingDelete.Member(obj) ) + wxPendingDelete.Erase(node); + + delete obj; + + // Deleting one object may have deleted other pending + // objects, so start from beginning of list again. + node = wxPendingDelete.GetFirst(); + } } - -// show the assert modal dialog -static -void ShowAssertDialog(const wxChar *szFile, - int nLine, - const wxChar *szCond, - const wxChar *szMsg) + +// Returns true if more time is needed. +bool wxAppBase::ProcessIdle() { - // this variable can be set to true to suppress "assert failure" messages - static bool s_bNoAsserts = FALSE; + wxIdleEvent event; + bool needMore = false; + wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); + while (node) + { + wxWindow* win = node->GetData(); + if (SendIdleEvents(win, event)) + needMore = true; + node = node->GetNext(); + } + + event.SetEventObject(this); + (void) ProcessEvent(event); + if (event.MoreRequested()) + needMore = true; + + wxUpdateUIEvent::ResetUpdateTime(); + + return needMore; +} - wxChar szBuf[4096]; +// Send idle event to window and all subwindows +bool wxAppBase::SendIdleEvents(wxWindow* win, wxIdleEvent& event) +{ + bool needMore = false; - // make life easier for people using VC++ IDE by using this format: like - // this, clicking on the message will take us immediately to the place of - // the failed assert - wxSnprintf(szBuf, WXSIZEOF(szBuf), - wxT("%s(%d): assert \"%s\" failed"), - szFile, nLine, szCond); + win->OnInternalIdle(); - if ( szMsg != NULL ) + if (wxIdleEvent::CanSend(win)) { - wxStrcat(szBuf, wxT(": ")); - wxStrcat(szBuf, szMsg); + event.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(event); + + if (event.MoreRequested()) + needMore = true; } - else // no message given + wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); + while ( node ) { - wxStrcat(szBuf, wxT(".")); + wxWindow *child = node->GetData(); + if (SendIdleEvents(child, event)) + needMore = true; + + node = node->GetNext(); } - if ( !s_bNoAsserts ) - { - // send it to the normal log destination - wxLogDebug(szBuf); - -#if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__) - // this message is intentionally not translated - it is for - // developpers only - wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings.")); - - // use the native message box if available: this is more robust than - // using our own -#if defined(__WXMSW__) && !defined(__WXMICROWIN__) - switch ( ::MessageBox(NULL, szBuf, _T("Debug"), - MB_YESNOCANCEL | MB_ICONSTOP ) ) - { - case IDYES: - wxTrap(); - break; + return needMore; +} - case IDCANCEL: - s_bNoAsserts = TRUE; - break; +void wxAppBase::OnIdle(wxIdleEvent& WXUNUSED(event)) +{ + // If there are pending events, we must process them: pending events + // are either events to the threads other than main or events posted + // with wxPostEvent() functions + // GRG: I have moved this here so that all pending events are processed + // before starting to delete any objects. This behaves better (in + // particular, wrt wxPostEvent) and is coherent with wxGTK's current + // behaviour. Changed Feb/2000 before 2.1.14 + ProcessPendingEvents(); + + // 'Garbage' collection of windows deleted with Close(). + DeletePendingObjects(); - //case IDNO: nothing to do - } -#else // !MSW - switch ( wxMessageBox(szBuf, wxT("Debug"), - wxYES_NO | wxCANCEL | wxICON_STOP ) ) - { - case wxYES: - wxTrap(); - break; +#if wxUSE_LOG + // flush the logged messages if any + wxLog::FlushActive(); +#endif // wxUSE_LOG - case wxCANCEL: - s_bNoAsserts = TRUE; - break; +} - //case wxNO: nothing to do - } -#endif // GUI or MSW +// ---------------------------------------------------------------------------- +// exceptions support +// ---------------------------------------------------------------------------- -#else // !GUI - wxTrap(); -#endif // GUI/!GUI - } +#if wxUSE_EXCEPTIONS + +bool wxAppBase::OnExceptionInMainLoop() +{ + throw; + + // some compilers are too stupid to know that we never return after throw +#if defined(__DMC__) || (defined(_MSC_VER) && _MSC_VER < 1200) + return false; +#endif } -// this function is called when an assert fails -void wxOnAssert(const wxChar *szFile, - int nLine, - const wxChar *szCond, - const wxChar *szMsg) +#endif // wxUSE_EXCEPTIONS + +// ---------------------------------------------------------------------------- +// wxGUIAppTraitsBase +// ---------------------------------------------------------------------------- + +#if wxUSE_LOG + +wxLog *wxGUIAppTraitsBase::CreateLogTarget() { - // FIXME MT-unsafe - static bool s_bInAssert = FALSE; +#if wxUSE_LOGGUI + return new wxLogGui; +#else + // we must have something! + return new wxLogStderr; +#endif +} - if ( s_bInAssert ) - { - // He-e-e-e-elp!! we're trapped in endless loop - wxTrap(); +#endif // wxUSE_LOG - s_bInAssert = FALSE; +wxMessageOutput *wxGUIAppTraitsBase::CreateMessageOutput() +{ + // The standard way of printing help on command line arguments (app --help) + // is (according to common practice): + // - console apps: to stderr (on any platform) + // - GUI apps: stderr on Unix platforms (!) + // message box under Windows and others +#ifdef __UNIX__ + return new wxMessageOutputStderr; +#else // !__UNIX__ + // wxMessageOutputMessageBox doesn't work under Motif + #ifdef __WXMOTIF__ + return new wxMessageOutputLog; + #else + return new wxMessageOutputMessageBox; + #endif +#endif // __UNIX__/!__UNIX__ +} - return; - } +#if wxUSE_FONTMAP - s_bInAssert = TRUE; +wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper() +{ + return new wxFontMapper; +} - if ( !wxTheApp ) - { - // by default, show the assert dialog box - we can't customize this - // behaviour - ShowAssertDialog(szFile, nLine, szCond, szMsg); - } - else +#endif // wxUSE_FONTMAP + +wxRendererNative *wxGUIAppTraitsBase::CreateRenderer() +{ + // use the default native renderer by default + return NULL; +} + +#ifdef __WXDEBUG__ + +bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) +{ +#if defined(__WXMSW__) || !wxUSE_MSGDLG + // under MSW we prefer to use the base class version using ::MessageBox() + // even if wxMessageBox() is available because it has less chances to + // double fault our app than our wxMessageBox() + return wxAppTraitsBase::ShowAssertDialog(msg); +#else // wxUSE_MSGDLG + wxString msgDlg = msg; + +#if wxUSE_STACKWALKER + // on Unix stack frame generation may take some time, depending on the + // size of the executable mainly... warn the user that we are working + wxFprintf(stderr, wxT("[Debug] Generating a stack trace... please wait")); + fflush(stderr); + + const wxString stackTrace = GetAssertStackTrace(); + if ( !stackTrace.empty() ) + msgDlg << _T("\n\nCall stack:\n") << stackTrace; +#endif // wxUSE_STACKWALKER + + // this message is intentionally not translated -- it is for + // developpers only + msgDlg += wxT("\nDo you want to stop the program?\n") + wxT("You can also choose [Cancel] to suppress ") + wxT("further warnings."); + + switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"), + wxYES_NO | wxCANCEL | wxICON_STOP ) ) { - // let the app process it as it wants - wxTheApp->OnAssert(szFile, nLine, szCond, szMsg); + case wxYES: + wxTrap(); + break; + + case wxCANCEL: + // no more asserts + return true; + + //case wxNO: nothing to do } - s_bInAssert = FALSE; + return false; +#endif // !wxUSE_MSGDLG/wxUSE_MSGDLG } -void wxAppBase::OnAssert(const wxChar *file, - int line, - const wxChar *cond, - const wxChar *msg) +#endif // __WXDEBUG__ + +bool wxGUIAppTraitsBase::HasStderr() +{ + // we consider that under Unix stderr always goes somewhere, even if the + // user doesn't always see it under GUI desktops +#ifdef __UNIX__ + return true; +#else + return false; +#endif +} + +void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject *object) +{ + if ( !wxPendingDelete.Member(object) ) + wxPendingDelete.Append(object); +} + +void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject *object) { - ShowAssertDialog(file, line, cond, msg); + wxPendingDelete.DeleteObject(object); } -#endif //WXDEBUG +#if wxUSE_SOCKETS + +#if defined(__WINDOWS__) + #include "wx/msw/gsockmsw.h" +#elif defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__) + #include "wx/unix/gsockunx.h" +#elif defined(__WXMAC__) + #include + #define OTUNIXERRORS 1 + #include + #include + #include + + #include "wx/mac/gsockmac.h" +#else + #error "Must include correct GSocket header here" +#endif +GSocketGUIFunctionsTable* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable() +{ +#if defined(__WXMAC__) && !defined(__DARWIN__) + // NB: wxMac CFM does not have any GUI-specific functions in gsocket.c and + // so it doesn't need this table at all + return NULL; +#else // !__WXMAC__ || __DARWIN__ + static GSocketGUIFunctionsTableConcrete table; + return &table; +#endif // !__WXMAC__ || __DARWIN__ +} + +#endif