X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7705c44f292e8ed629f4b49500c2b33b8d903657..769c3372a2bd68c45d1a4afc8462d3b7939decb1:/src/common/appbase.cpp diff --git a/src/common/appbase.cpp b/src/common/appbase.cpp index db26530d66..194d0793ac 100644 --- a/src/common/appbase.cpp +++ b/src/common/appbase.cpp @@ -6,7 +6,7 @@ // Created: 19.06.2003 (extracted from common/appcmn.cpp) // RCS-ID: $Id$ // Copyright: (c) 2003 Vadim Zeitlin -// License: wxWindows license +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -43,6 +43,7 @@ #include "wx/filename.h" #include "wx/msgout.h" #include "wx/scopedptr.h" +#include "wx/sysopt.h" #include "wx/tokenzr.h" #include "wx/thread.h" @@ -146,14 +147,17 @@ wxAppConsoleBase::wxAppConsoleBase() // In unicode mode the SetTraceMasks call can cause an apptraits to be // created, but since we are still in the constructor the wrong kind will // be created for GUI apps. Destroy it so it can be created again later. - delete m_traits; - m_traits = NULL; + wxDELETE(m_traits); #endif #endif } wxAppConsoleBase::~wxAppConsoleBase() { + // we're being destroyed and using this object from now on may not work or + // even crash so don't leave dangling pointers to it + ms_appInstance = NULL; + delete m_traits; } @@ -161,21 +165,45 @@ wxAppConsoleBase::~wxAppConsoleBase() // initialization/cleanup // ---------------------------------------------------------------------------- -bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **argv) +bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **WXUNUSED(argv)) { #if wxUSE_INTL GetTraits()->SetLocale(); #endif // wxUSE_INTL + return true; +} + +wxString wxAppConsoleBase::GetAppName() const +{ + wxString name = m_appName; #ifndef __WXPALMOS__ - if ( m_appName.empty() && argv && argv[0] ) + if ( name.empty() ) { - // the application name is, by default, the name of its executable file - wxFileName::SplitPath(argv[0], NULL, &m_appName, NULL); + if ( argv ) + { + // the application name is, by default, the name of its executable file + wxFileName::SplitPath(argv[0], NULL, &name, NULL); + } } #endif // !__WXPALMOS__ + return name; +} - return true; +wxString wxAppConsoleBase::GetAppDisplayName() const +{ + // use the explicitly provided display name, if any + if ( !m_appDisplayName.empty() ) + return m_appDisplayName; + + // if the application name was explicitly set, use it as is as capitalizing + // it won't always produce good results + if ( !m_appName.empty() ) + return m_appName; + + // if neither is set, use the capitalized version of the program file as + // it's the most reasonable default + return GetAppName().Capitalize(); } wxEventLoopBase *wxAppConsoleBase::CreateMainLoop() @@ -185,11 +213,7 @@ wxEventLoopBase *wxAppConsoleBase::CreateMainLoop() void wxAppConsoleBase::CleanUp() { - if ( m_mainLoop ) - { - delete m_mainLoop; - m_mainLoop = NULL; - } + wxDELETE(m_mainLoop); } // ---------------------------------------------------------------------------- @@ -321,8 +345,11 @@ bool wxAppConsoleBase::Dispatch() bool wxAppConsoleBase::Yield(bool onlyIfNeeded) { wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); + if ( loop ) + return loop->Yield(onlyIfNeeded); - return loop && loop->Yield(onlyIfNeeded); + wxScopedPtr tmpLoop(CreateMainLoop()); + return tmpLoop->Yield(onlyIfNeeded); } void wxAppConsoleBase::WakeUpIdle() @@ -340,6 +367,15 @@ bool wxAppConsoleBase::ProcessIdle() event.SetEventObject(this); ProcessEvent(event); +#if wxUSE_LOG + // flush the logged messages if any (do this after processing the events + // which could have logged new messages) + wxLog::FlushActive(); +#endif + + // Garbage collect all objects previously scheduled for destruction. + DeletePendingObjects(); + return event.MoreRequested(); } @@ -479,9 +515,6 @@ void wxAppConsoleBase::ProcessPendingEvents() wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } - - // Garbage collect all objects previously scheduled for destruction. - DeletePendingObjects(); } void wxAppConsoleBase::DeletePendingEvents() @@ -505,7 +538,7 @@ void wxAppConsoleBase::DeletePendingEvents() bool wxAppConsoleBase::IsScheduledForDestruction(wxObject *object) const { - return wxPendingDelete.Member(object) != NULL; + return wxPendingDelete.Member(object); } void wxAppConsoleBase::ScheduleForDestruction(wxObject *object) @@ -838,22 +871,19 @@ void WXDLLIMPEXP_BASE wxMutexGuiLeave() bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal) { #if wxDEBUG_LEVEL - wxString msg = msgOriginal; + wxString msg; #if wxUSE_STACKWALKER -#if !defined(__WXMSW__) - // 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); -#endif - const wxString stackTrace = GetAssertStackTrace(); if ( !stackTrace.empty() ) + { msg << wxT("\n\nCall stack:\n") << stackTrace; + + wxMessageOutputDebug().Output(msg); + } #endif // wxUSE_STACKWALKER - return DoShowAssertDialog(msg); + return DoShowAssertDialog(msgOriginal + msg); #else // !wxDEBUG_LEVEL wxUnusedVar(msgOriginal); @@ -865,6 +895,15 @@ bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal) wxString wxAppTraitsBase::GetAssertStackTrace() { #if wxDEBUG_LEVEL + +#if !defined(__WXMSW__) + // 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, "Collecting stack trace information, please wait..."); + fflush(stderr); +#endif // !__WXMSW__ + + wxString stackTrace; class StackDump : public wxStackWalker @@ -987,6 +1026,10 @@ wxDefaultAssertHandler(const wxString& file, const wxString& cond, const wxString& msg) { + // If this option is set, we should abort immediately when assert happens. + if ( wxSystemOptions::GetOptionInt("exit-on-assert") ) + abort(); + // FIXME MT-unsafe static int s_bInAssert = 0; @@ -1016,6 +1059,11 @@ wxDefaultAssertHandler(const wxString& file, wxAssertHandler_t wxTheAssertHandler = wxDefaultAssertHandler; +void wxSetDefaultAssertHandler() +{ + wxTheAssertHandler = wxDefaultAssertHandler; +} + void wxOnAssert(const wxString& file, int line, const wxString& func, @@ -1147,14 +1195,10 @@ bool DoShowAssertDialog(const wxString& msg) //case IDNO: nothing to do } #else // !__WXMSW__ - wxFprintf(stderr, wxT("%s\n"), msg.c_str()); - fflush(stderr); - - // TODO: ask the user to enter "Y" or "N" on the console? - wxTrap(); + wxUnusedVar(msg); #endif // __WXMSW__/!__WXMSW__ - // continue with the asserts + // continue with the asserts by default return false; } @@ -1197,27 +1241,15 @@ void ShowAssertDialog(const wxString& file, // since dialogs cannot be displayed if ( !wxThread::IsMain() ) { - msg += wxT(" [in child thread]"); - -#if defined(__WXMSW__) && !defined(__WXMICROWIN__) - msg << wxT("\r\n"); - OutputDebugString(msg.wx_str()); -#else - // send to stderr - wxFprintf(stderr, wxT("%s\n"), msg.c_str()); - fflush(stderr); -#endif - // He-e-e-e-elp!! we're asserting in a child thread - wxTrap(); + msg += wxString::Format(" [in thread %lx]", wxThread::GetCurrentId()); } - else #endif // wxUSE_THREADS + // log the assert in any case + wxMessageOutputDebug().Output(msg); + if ( !s_bNoAsserts ) { - // send it to the normal log destination - wxLogDebug(wxT("%s"), msg.c_str()); - if ( traits ) { // delegate showing assert dialog (if possible) to that class