bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal) { #if wxDEBUG_LEVEL wxString msg = msgOriginal; #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 << _T("\n\nCall stack:\n") << stackTrace; #endif // wxUSE_STACKWALKER return DoShowAssertDialog(msg); #else // !wxDEBUG_LEVEL wxUnusedVar(msgOriginal); return false; #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL }
bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) { // 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() // // under DFB the message dialog is not always functional right now // // and finally we can't use wxMessageBox() if it wasn't compiled in, of // course #if defined(__WXMSW__) || defined(__WXDFB__) || !wxUSE_MSGDLG return wxAppTraitsBase::ShowAssertDialog(msg); #else // wxUSE_MSGDLG #if wxDEBUG_LEVEL 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 ) ) { case wxYES: wxTrap(); break; case wxCANCEL: // no more asserts return true; //case wxNO: nothing to do } #else // !wxDEBUG_LEVEL // this function always exists (for ABI compatibility) but is never called // if debug level is 0 and so can simply do nothing then wxUnusedVar(msg); #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL return false; #endif // !wxUSE_MSGDLG/wxUSE_MSGDLG }
bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) { #if wxDEBUG_LEVEL // 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() // // under DFB the message dialog is not always functional right now // // and finally we can't use wxMessageBox() if it wasn't compiled in, of // course #if !defined(__WXMSW__) && !defined(__WXDFB__) && wxUSE_MSGDLG // we can't (safely) show the GUI dialog from another thread, only do it // for the asserts in the main thread if ( wxIsMainThread() ) { wxString msgDlg = msg; #if wxUSE_STACKWALKER const wxString stackTrace = GetAssertStackTrace(); if ( !stackTrace.empty() ) msgDlg << wxT("\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 ) ) { case wxYES: wxTrap(); break; case wxCANCEL: // no more asserts return true; //case wxNO: nothing to do } return false; } #endif // wxUSE_MSGDLG #endif // wxDEBUG_LEVEL return wxAppTraitsBase::ShowAssertDialog(msg); }
bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal) { #if wxDEBUG_LEVEL wxString msg; #if wxUSE_STACKWALKER const wxString stackTrace = GetAssertStackTrace(); if ( !stackTrace.empty() ) { msg << wxT("\n\nCall stack:\n") << stackTrace; wxMessageOutputDebug().Output(msg); } #endif // wxUSE_STACKWALKER return DoShowAssertDialog(msgOriginal + msg); #else // !wxDEBUG_LEVEL wxUnusedVar(msgOriginal); return false; #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL }
// show the assert modal dialog static void ShowAssertDialog(const wxChar *szFile, int nLine, const wxChar *szCond, const wxChar *szMsg, wxAppTraits *traits) { // this variable can be set to true to suppress "assert failure" messages static bool s_bNoAsserts = false; wxString msg; msg.reserve(2048); // 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 msg.Printf(wxT("%s(%d): assert \"%s\" failed"), szFile, nLine, szCond); if ( szMsg ) { msg << _T(": ") << szMsg; } else // no message given { msg << _T('.'); } #if wxUSE_STACKWALKER const wxString stackTrace = GetAssertStackTrace(); if ( !stackTrace.empty() ) { msg << _T("\n\nCall stack:\n") << stackTrace; } #endif // wxUSE_STACKWALKER #if wxUSE_THREADS // if we are not in the main thread, output the assert directly and trap // since dialogs cannot be displayed if ( !wxThread::IsMain() ) { msg += wxT(" [in child thread]"); #if defined(__WXMSW__) && !defined(__WXMICROWIN__) msg << wxT("\r\n"); OutputDebugString(msg ); #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(); } else #endif // wxUSE_THREADS if ( !s_bNoAsserts ) { // send it to the normal log destination wxLogDebug(_T("%s"), msg.c_str()); if ( traits ) { // delegate showing assert dialog (if possible) to that class s_bNoAsserts = traits->ShowAssertDialog(msg); } else // no traits object { // fall back to the function of last resort s_bNoAsserts = DoShowAssertDialog(msg); } } }
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."); #ifdef __WXMAC__ // in order to avoid reentrancy problems, use the lowest alert API available CFOptionFlags exitButton; wxMacCFStringHolder cfText(msgDlg); OSStatus err = CFUserNotificationDisplayAlert( 0, kAlertStopAlert, NULL, NULL, NULL, CFSTR("wxWidgets Debug Alert"), cfText, CFSTR("Yes"), CFSTR("No"), CFSTR("Cancel"), &exitButton ); if ( err == noErr ) { switch( exitButton ) { case 0 : // yes wxTrap(); break; case 2 : // cancel // no more asserts return true; case 1 : // no -> nothing to do break ; } } #else switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"), wxYES_NO | wxCANCEL | wxICON_STOP ) ) { case wxYES: wxTrap(); break; case wxCANCEL: // no more asserts return true; //case wxNO: nothing to do } #endif return false; #endif // !wxUSE_MSGDLG/wxUSE_MSGDLG }