// Author: Vadim Zeitlin
// Modified by:
// Created: 19.06.2003 (extracted from common/appcmn.cpp)
-// RCS-ID: $Id$
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
-// License: wxWindows license
+// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
#endif
#ifndef WX_PRECOMP
- #ifdef __WXMSW__
+ #ifdef __WINDOWS__
#include "wx/msw/wrapwin.h" // includes windows.h for MessageBox()
#endif
#include "wx/list.h"
#include "wx/filename.h"
#include "wx/msgout.h"
#include "wx/scopedptr.h"
+#include "wx/sysopt.h"
#include "wx/tokenzr.h"
#include "wx/thread.h"
-#if wxUSE_EXCEPTIONS && wxUSE_STL
- #include <exception>
- #include <typeinfo>
-#endif
+#if wxUSE_STL
+ #if wxUSE_EXCEPTIONS
+ #include <exception>
+ #include <typeinfo>
+ #endif
+ #if wxUSE_INTL
+ #include <locale>
+ #endif
+#endif // wxUSE_STL
-#ifndef __WXPALMOS5__
-#if !defined(__WXMSW__) || defined(__WXMICROWIN__)
+#if !defined(__WINDOWS__) || defined(__WXMICROWIN__)
#include <signal.h> // for SIGTRAP used by wxTrap()
#endif //Win/Unix
#include <locale.h>
-#endif // ! __WXPALMOS5__
#if wxUSE_FONTMAP
#include "wx/fontmap.h"
#if wxDEBUG_LEVEL
#if wxUSE_STACKWALKER
#include "wx/stackwalk.h"
- #ifdef __WXMSW__
+ #ifdef __WINDOWS__
#include "wx/msw/debughlp.h"
#endif
#endif // wxUSE_STACKWALKER
// 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
+
+ wxEvtHandler::AddFilter(this);
}
wxAppConsoleBase::~wxAppConsoleBase()
{
+ wxEvtHandler::RemoveFilter(this);
+
+ // 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;
}
// 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;
+}
-#ifndef __WXPALMOS__
- if ( m_appName.empty() && argv && argv[0] )
+wxString wxAppConsoleBase::GetAppName() const
+{
+ wxString name = m_appName;
+ 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()
void wxAppConsoleBase::CleanUp()
{
- if ( m_mainLoop )
- {
- delete m_mainLoop;
- m_mainLoop = NULL;
- }
+ wxDELETE(m_mainLoop);
}
// ----------------------------------------------------------------------------
return MainLoop();
}
+void wxAppConsoleBase::OnLaunched()
+{
+}
+
int wxAppConsoleBase::OnExit()
{
#if wxUSE_CONFIG
return app ? app->GetTraits() : NULL;
}
+/* static */
+wxAppTraits& wxAppConsoleBase::GetValidTraits()
+{
+ static wxConsoleAppTraits s_traitsConsole;
+ wxAppTraits* const traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
+
+ return traits ? *traits : s_traitsConsole;
+}
+
// ----------------------------------------------------------------------------
// wxEventLoop redirection
// ----------------------------------------------------------------------------
{
wxEventLoopBaseTiedPtr mainLoop(&m_mainLoop, CreateMainLoop());
+ if (wxTheApp)
+ wxTheApp->OnLaunched();
+
return m_mainLoop ? m_mainLoop->Run() : -1;
}
bool wxAppConsoleBase::Yield(bool onlyIfNeeded)
{
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
+ if ( loop )
+ return loop->Yield(onlyIfNeeded);
- return loop && loop->Yield(onlyIfNeeded);
+ wxScopedPtr<wxEventLoopBase> tmpLoop(CreateMainLoop());
+ return tmpLoop->Yield(onlyIfNeeded);
}
void wxAppConsoleBase::WakeUpIdle()
wxLog::FlushActive();
#endif
+ // Garbage collect all objects previously scheduled for destruction.
+ DeletePendingObjects();
+
return event.MoreRequested();
}
int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event))
{
// process the events normally by default
- return -1;
+ return Event_Skip;
}
void wxAppConsoleBase::DelayPendingEventHandler(wxEvtHandler* toDelay)
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
}
-
- // Garbage collect all objects previously scheduled for destruction.
- DeletePendingObjects();
}
void wxAppConsoleBase::DeletePendingEvents()
bool wxAppConsoleBase::IsScheduledForDestruction(wxObject *object) const
{
- return wxPendingDelete.Member(object) != NULL;
+ return wxPendingDelete.Member(object);
}
void wxAppConsoleBase::ScheduleForDestruction(wxObject *object)
OnAssertFailure(file, line, NULL, cond, msg);
}
+// ----------------------------------------------------------------------------
+// Miscellaneous other methods
+// ----------------------------------------------------------------------------
+
+void wxAppConsoleBase::SetCLocale()
+{
+ // We want to use the user locale by default in GUI applications in order
+ // to show the numbers, dates &c in the familiar format -- and also accept
+ // this format on input (especially important for decimal comma/dot).
+ wxSetlocale(LC_ALL, "");
+}
+
// ============================================================================
// other classes implementations
// ============================================================================
// wxAppTraits
// ----------------------------------------------------------------------------
-#if wxUSE_INTL
-void wxAppTraitsBase::SetLocale()
-{
- wxSetlocale(LC_ALL, "");
- wxUpdateLocaleIsUtf8();
-}
-#endif
-
#if wxUSE_THREADS
void wxMutexGuiEnterImpl();
void wxMutexGuiLeaveImpl();
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);
wxString wxAppTraitsBase::GetAssertStackTrace()
{
#if wxDEBUG_LEVEL
+
+#if !defined(__WINDOWS__)
+ // 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 // !__WINDOWS__
+
+
wxString stackTrace;
class StackDump : public wxStackWalker
static const int maxLines = 20;
StackDump dump;
- dump.Walk(2, maxLines); // don't show OnAssert() call itself
+ dump.Walk(8, maxLines); // 8 is chosen to hide all OnAssert() calls
stackTrace = dump.GetStackTrace();
const int count = stackTrace.Freq(wxT('\n'));
return x == y;
}
+void wxAbort()
+{
+#ifdef __WXWINCE__
+ ExitThread(3);
+#else
+ abort();
+#endif
+}
+
#if wxDEBUG_LEVEL
// break into the debugger
+#ifndef wxTrap
+
void wxTrap()
{
-#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
+#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
DebugBreak();
#elif defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
Debugger();
#endif // Win/Unix
}
+#endif // wxTrap already defined as a macro
+
// default assert handler
static void
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") )
+ wxAbort();
+
// FIXME MT-unsafe
static int s_bInAssert = 0;
wxAssertHandler_t wxTheAssertHandler = wxDefaultAssertHandler;
+void wxSetDefaultAssertHandler()
+{
+ wxTheAssertHandler = wxDefaultAssertHandler;
+}
+
void wxOnAssert(const wxString& file,
int line,
const wxString& func,
#if wxDEBUG_LEVEL
+bool wxTrapInAssert = false;
+
static
bool DoShowAssertDialog(const wxString& msg)
{
- // under MSW we can show the dialog even in the console mode
-#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
+ // under Windows we can show the dialog even in the console mode
+#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
wxString msgDlg(msg);
// this message is intentionally not translated -- it is for developers
wxT("You can also choose [Cancel] to suppress ")
wxT("further warnings.");
- switch ( ::MessageBox(NULL, msgDlg.wx_str(), wxT("wxWidgets Debug Alert"),
+ switch ( ::MessageBox(NULL, msgDlg.t_str(), wxT("wxWidgets Debug Alert"),
MB_YESNOCANCEL | MB_ICONSTOP ) )
{
case IDYES:
- wxTrap();
+ // If we called wxTrap() directly from here, the programmer would
+ // see this function and a few more calls between his own code and
+ // it in the stack trace which would be perfectly useless and often
+ // confusing. So instead just set the flag here and let the macros
+ // defined in wx/debug.h call wxTrap() themselves, this ensures
+ // that the debugger will show the line in the user code containing
+ // the failing assert.
+ wxTrapInAssert = true;
break;
case IDCANCEL:
//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();
-#endif // __WXMSW__/!__WXMSW__
+#else // !__WINDOWS__
+ wxUnusedVar(msg);
+#endif // __WINDOWS__/!__WINDOWS__
- // continue with the asserts
+ // continue with the asserts by default
return false;
}
// 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