X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9fd239ad61686946e7c3455d24089a2d985a9561..d1427b705318677afe28b1291867f6930c8823a7:/src/common/log.cpp?ds=inline diff --git a/src/common/log.cpp b/src/common/log.cpp index 5c4b30f179..d1e30401d4 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -32,6 +32,7 @@ #include #include #include + #include #include #include @@ -40,6 +41,7 @@ #include #include +#include #include // other standard headers @@ -47,7 +49,7 @@ #include #include -#ifdef __WINDOWS__ +#ifdef __WXMSW__ #include #else //Unix #include @@ -83,12 +85,12 @@ static char s_szBuf[LOG_BUFFER_SIZE]; // generic log function -void wxLogGeneric(wxLogLevel level, wxTString strFormat, ...) +void wxLogGeneric(wxLogLevel level, const char *szFormat, ...) { if ( wxLog::GetActiveTarget() != NULL ) { va_list argptr; - va_start(argptr, strFormat); - vsprintf(s_szBuf, strFormat, argptr); + va_start(argptr, szFormat); + vsprintf(s_szBuf, szFormat, argptr); va_end(argptr); wxLog::OnLog(level, s_szBuf); @@ -96,12 +98,12 @@ void wxLogGeneric(wxLogLevel level, wxTString strFormat, ...) } #define IMPLEMENT_LOG_FUNCTION(level) \ - void wxLog##level(wxTString strFormat, ...) \ + void wxLog##level(const char *szFormat, ...) \ { \ if ( wxLog::GetActiveTarget() != NULL ) { \ va_list argptr; \ - va_start(argptr, strFormat); \ - vsprintf(s_szBuf, strFormat, argptr); \ + va_start(argptr, szFormat); \ + vsprintf(s_szBuf, szFormat, argptr); \ va_end(argptr); \ \ wxLog::OnLog(wxLOG_##level, s_szBuf); \ @@ -116,13 +118,13 @@ IMPLEMENT_LOG_FUNCTION(Info) IMPLEMENT_LOG_FUNCTION(Status) // same as info, but only if 'verbose' mode is on -void wxLogVerbose(wxTString strFormat, ...) +void wxLogVerbose(const char *szFormat, ...) { wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL && pLog->GetVerbose() ) { va_list argptr; - va_start(argptr, strFormat); - vsprintf(s_szBuf, strFormat, argptr); + va_start(argptr, szFormat); + vsprintf(s_szBuf, szFormat, argptr); va_end(argptr); wxLog::OnLog(wxLOG_Info, s_szBuf); @@ -130,7 +132,7 @@ void wxLogVerbose(wxTString strFormat, ...) } // debug functions -#ifdef __DEBUG__ +#ifdef __WXDEBUG__ #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ void wxLog##level(const char *szFormat, ...) \ { \ @@ -151,7 +153,7 @@ void wxLogVerbose(wxTString strFormat, ...) // we check that all of mask bits are set in the current mask, so // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something // if both bits are set. - if ( pLog != NULL && (pLog->GetTraceMask() & mask == mask) ) { + if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) { va_list argptr; va_start(argptr, szFormat); vsprintf(s_szBuf, szFormat, argptr); @@ -181,21 +183,21 @@ void wxLogSysErrorHelper(long lErrCode) wxLog::OnLog(wxLOG_Error, s_szBuf); } -void WXDLLEXPORT wxLogSysError(wxTString strFormat, ...) +void WXDLLEXPORT wxLogSysError(const char *szFormat, ...) { va_list argptr; - va_start(argptr, strFormat); - vsprintf(s_szBuf, strFormat, argptr); + va_start(argptr, szFormat); + vsprintf(s_szBuf, szFormat, argptr); va_end(argptr); wxLogSysErrorHelper(wxSysErrorCode()); } -void WXDLLEXPORT wxLogSysError(long lErrCode, wxTString strFormat, ...) +void WXDLLEXPORT wxLogSysError(long lErrCode, const char *szFormat, ...) { va_list argptr; - va_start(argptr, strFormat); - vsprintf(s_szBuf, strFormat, argptr); + va_start(argptr, szFormat); + vsprintf(s_szBuf, szFormat, argptr); va_end(argptr); wxLogSysErrorHelper(lErrCode); @@ -210,47 +212,47 @@ wxLog::wxLog() m_bHasMessages = FALSE; m_bVerbose = FALSE; m_szTimeFormat = "[%d/%b/%y %H:%M:%S] "; - m_ulTraceMask = (wxTraceMask)-1; // set all bits } -wxLog *wxLog::GetActiveTarget() -{ - if ( !ms_bInitialized ) { +wxLog *wxLog::GetActiveTarget() +{ + if ( ms_bAutoCreate && ms_pLogger == NULL ) { // prevent infinite recursion if someone calls wxLogXXX() from // wxApp::CreateLogTarget() - ms_bInitialized = TRUE; - - #ifdef WX_TEST_MINIMAL - ms_pLogger = new wxLogStderr; - #else - // ask the application to create a log target for us - ms_pLogger = wxTheApp->CreateLogTarget(); - #endif + static bool s_bInGetActiveTarget = FALSE; + if ( !s_bInGetActiveTarget ) { + s_bInGetActiveTarget = TRUE; + + #ifdef WX_TEST_MINIMAL + ms_pLogger = new wxLogStderr; + #else + // ask the application to create a log target for us + if ( wxTheApp != NULL ) + ms_pLogger = wxTheApp->CreateLogTarget(); + #endif - // do nothing if it fails - what can we do? + // do nothing if it fails - what can we do? + } } - return ms_pLogger; + return ms_pLogger; } wxLog *wxLog::SetActiveTarget(wxLog *pLogger) -{ +{ // flush the old messages before changing if ( ms_pLogger != NULL ) ms_pLogger->Flush(); - ms_bInitialized = TRUE; - - wxLog *pOldLogger = ms_pLogger; - ms_pLogger = pLogger; - return pOldLogger; + wxLog *pOldLogger = ms_pLogger; + ms_pLogger = pLogger; + return pOldLogger; } -void wxLog::DoLog(wxLogLevel level, const char *szString) +wxString wxLog::TimeStamp() const { wxString str; - // prepend a timestamp if not disabled if ( !IsEmpty(m_szTimeFormat) ) { char szBuf[128]; time_t timeNow; @@ -263,6 +265,14 @@ void wxLog::DoLog(wxLogLevel level, const char *szString) str = szBuf; } + return str; +} + +void wxLog::DoLog(wxLogLevel level, const char *szString) +{ + // prepend a timestamp if not disabled + wxString str = TimeStamp(); + switch ( level ) { case wxLOG_FatalError: DoLogString(str << _("Fatal error: ") << szString); @@ -291,26 +301,21 @@ void wxLog::DoLog(wxLogLevel level, const char *szString) case wxLOG_Trace: case wxLOG_Debug: - #ifdef __DEBUG__ - #ifdef __WIN32__ - // in addition to normal logging, also send the string to debugger - // (don't prepend "Debug" here: it will go to debug window anyhow) - ::OutputDebugString(str + szString + "\n\r"); - #endif //Win32 - DoLogString(str << (level == wxLOG_Trace ? "Trace" : "Debug") + #ifdef __WXDEBUG__ + DoLogString(str << (level == wxLOG_Trace ? _("Trace") : _("Debug")) << ": " << szString); #endif - + break; default: - wxFAIL_MSG("unknown log level in wxLog::DoLog"); + wxFAIL_MSG(_("unknown log level in wxLog::DoLog")); } } -void wxLog::DoLogString(const char *szString) +void wxLog::DoLogString(const char *WXUNUSED(szString)) { - wxFAIL_MSG("DoLogString must be overrided if it's called."); + wxFAIL_MSG(_("DoLogString must be overrided if it's called.")); } void wxLog::Flush() @@ -359,17 +364,18 @@ void wxLogStream::DoLogString(const char *szString) // ---------------------------------------------------------------------------- wxLogTextCtrl::wxLogTextCtrl(wxTextCtrl *pTextCtrl) // @@@ TODO: in wxGTK wxTextCtrl doesn't derive from streambuf -#ifndef __GTK__ + +// Also, in DLL mode in wxMSW, can't use it. +#if defined(NO_TEXT_WINDOW_STREAM) +#else : wxLogStream(new ostream(pTextCtrl)) -#endif //GTK +#endif { } wxLogTextCtrl::~wxLogTextCtrl() { - #ifndef __GTK__ - delete m_ostr; - #endif //GTK + delete m_ostr; } // ---------------------------------------------------------------------------- @@ -389,10 +395,10 @@ void wxLogGui::Flush() return; // @@@ ugly... - + // concatenate all strings (but not too many to not overfill the msg box) wxString str; - uint nLines = 0, + uint nLines = 0, nMsgCount = m_aMessages.Count(); // start from the most recent message @@ -448,22 +454,29 @@ void wxLogGui::DoLog(wxLogLevel level, const char *szString) case wxLOG_Trace: case wxLOG_Debug: - #ifdef __DEBUG__ - #ifdef __WIN32__ - OutputDebugString(szString); - OutputDebugString("\n\r"); - #else //!WIN32 - // send them to stderr - fprintf(stderr, level == wxLOG_Trace ? "Trace: %s\n" - : "Debug: %s\n", szString); - fflush(stderr); - #endif // WIN32 + #ifdef __WXDEBUG__ + { + wxString strTime = TimeStamp(); + + #ifdef __WIN32__ + // don't prepend debug/trace here: it goes to the debug window + // anyhow, but do put a timestamp + OutputDebugString(strTime + szString + "\n\r"); + #else //!WIN32 + // send them to stderr + fprintf(stderr, "%s %s: %s\n", + strTime.c_str(), + level == wxLOG_Trace ? _("Trace") : _("Debug"), + szString); + fflush(stderr); + #endif // WIN32 + } #endif break; case wxLOG_FatalError: // show this one immediately - wxMessageBox(szString, "Fatal error", wxICON_HAND); + wxMessageBox(szString, _("Fatal error"), wxICON_HAND); break; case wxLOG_Error: @@ -477,28 +490,33 @@ void wxLogGui::DoLog(wxLogLevel level, const char *szString) m_aMessages.Add(szString); break; - + default: - wxFAIL_MSG("unknown log level in wxLogGui::DoLog"); + wxFAIL_MSG(_("unknown log level in wxLogGui::DoLog")); } } // ---------------------------------------------------------------------------- -// wxLogWindow implementation +// wxLogWindow and wxLogFrame implementation // ---------------------------------------------------------------------------- // log frame class +// --------------- class wxLogFrame : public wxFrame { public: - // ctor - wxLogFrame(const char *szTitle); + // ctor & dtor + wxLogFrame(wxLogWindow *log, const char *szTitle); + virtual ~wxLogFrame(); // menu callbacks void OnClose(wxCommandEvent& event); + void OnCloseWindow(wxCloseEvent& event); void OnSave (wxCommandEvent& event); void OnClear(wxCommandEvent& event); + void OnIdle(wxIdleEvent&); + // accessors wxTextCtrl *TextCtrl() const { return m_pTextCtrl; } @@ -510,7 +528,11 @@ private: Menu_Clear }; - wxTextCtrl *m_pTextCtrl; + // instead of closing just hide the window to be able to Show() it later + void DoClose() { Show(FALSE); } + + wxTextCtrl *m_pTextCtrl; + wxLogWindow *m_log; DECLARE_EVENT_TABLE() }; @@ -521,18 +543,18 @@ BEGIN_EVENT_TABLE(wxLogFrame, wxFrame) EVT_MENU(Menu_Save, wxLogFrame::OnSave) EVT_MENU(Menu_Clear, wxLogFrame::OnClear) - EVT_CLOSE(wxLogFrame::OnClose) -END_EVENT_TABLE() + EVT_CLOSE(wxLogFrame::OnCloseWindow) + + EVT_IDLE(wxLogFrame::OnIdle) +END_EVENT_TABLE() -wxLogFrame::wxLogFrame(const char *szTitle) +wxLogFrame::wxLogFrame(wxLogWindow *log, const char *szTitle) : wxFrame(NULL, -1, szTitle) { - // we don't want to be a top-level frame because it would prevent the - // application termination when all other frames are closed - wxTopLevelWindows.DeleteObject(this); + m_log = log; // @@ kludge: wxSIMPLE_BORDER is simply to prevent wxWindows from creating - // a rich edit control instead of a normal one we want + // a rich edit control instead of a normal one we want in wxMSW m_pTextCtrl = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER | @@ -547,23 +569,38 @@ wxLogFrame::wxLogFrame(const char *szTitle) // create menu wxMenuBar *pMenuBar = new wxMenuBar; wxMenu *pMenu = new wxMenu; - pMenu->Append(Menu_Save, "&Save..."); - pMenu->Append(Menu_Clear, "C&lear"); + pMenu->Append(Menu_Save, _("&Save..."), _("Save log contents to file")); + pMenu->Append(Menu_Clear, _("C&lear"), _("Clear the log contents")); pMenu->AppendSeparator(); - pMenu->Append(Menu_Close, "&Close"); - pMenuBar->Append(pMenu, "&Log"); + pMenu->Append(Menu_Close, _("&Close"), _("Close this window")); + pMenuBar->Append(pMenu, _("&Log")); SetMenuBar(pMenuBar); - // @@ what about status bar? needed (for menu prompts)? + // status bar for menu prompts + CreateStatusBar(); + + m_log->OnFrameCreate(this); +} + +void wxLogFrame::OnClose(wxCommandEvent& WXUNUSED(event)) +{ + DoClose(); } -void wxLogFrame::OnClose(wxCommandEvent& event) +void wxLogFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event)) { - // just hide the window - Show(FALSE); + DoClose(); } -void wxLogFrame::OnSave(wxCommandEvent& event) +void wxLogFrame::OnIdle(wxIdleEvent& WXUNUSED(event)) +{ + // if we're the last frame to stay, delete log frame letting the + // application to close + if ( wxTopLevelWindows.Number() == 1 ) + Destroy(); +} + +void wxLogFrame::OnSave(wxCommandEvent& WXUNUSED(event)) { // get the file name // ----------------- @@ -576,13 +613,13 @@ void wxLogFrame::OnSave(wxCommandEvent& event) // open file // --------- wxFile file; - bool bOk; + bool bOk = FALSE; if ( wxFile::Exists(szFileName) ) { - bool bAppend; + bool bAppend = FALSE; wxString strMsg; strMsg.Printf(_("Append log to file '%s' " "(choosing [No] will overwrite it)?"), szFileName); - switch ( wxMessageBox(strMsg, "Question", wxYES_NO | wxCANCEL) ) { + switch ( wxMessageBox(strMsg, _("Question"), wxYES_NO | wxCANCEL) ) { case wxYES: bAppend = TRUE; break; @@ -595,7 +632,7 @@ void wxLogFrame::OnSave(wxCommandEvent& event) return; default: - wxFAIL_MSG("invalid message box return value"); + wxFAIL_MSG(_("invalid message box return value")); } if ( bAppend ) { @@ -611,36 +648,44 @@ void wxLogFrame::OnSave(wxCommandEvent& event) // retrieve text and save it // ------------------------- - -#ifdef __GTK__ +#ifdef __WXGTK__ // @@@@ TODO: no GetNumberOfLines and GetLineText in wxGTK yet - wxLogError("Sorry, this function is not implemented under GTK"); + wxLogError(_("Sorry, this function is not implemented under GTK")); #else int nLines = m_pTextCtrl->GetNumberOfLines(); for ( int nLine = 0; bOk && nLine < nLines; nLine++ ) { bOk = file.Write(m_pTextCtrl->GetLineText(nLine) + wxTextFile::GetEOL()); } #endif //GTK - + if ( bOk ) bOk = file.Close(); if ( !bOk ) { - wxLogError("Can't save log contents to file."); + wxLogError(_("Can't save log contents to file.")); return; } } -void wxLogFrame::OnClear(wxCommandEvent& event) +void wxLogFrame::OnClear(wxCommandEvent& WXUNUSED(event)) { m_pTextCtrl->Clear(); } -wxLogWindow::wxLogWindow(const wxTString& strTitle, bool bShow) +wxLogFrame::~wxLogFrame() +{ + m_log->OnFrameDelete(this); +} + +// wxLogWindow +// ----------- +wxLogWindow::wxLogWindow(const char *szTitle, bool bShow, bool bDoPass) { - m_pOldLog = wxLog::GetActiveTarget(); - m_pLogFrame = new wxLogFrame(strTitle); - + m_bPassMessages = bDoPass; + + m_pLogFrame = new wxLogFrame(this, szTitle); + m_pOldLog = wxLog::SetActiveTarget(this); + if ( bShow ) m_pLogFrame->Show(TRUE); } @@ -650,19 +695,29 @@ void wxLogWindow::Show(bool bShow) m_pLogFrame->Show(bShow); } +void wxLogWindow::Flush() +{ + if ( m_pOldLog != NULL ) + m_pOldLog->Flush(); + + m_bHasMessages = FALSE; +} + void wxLogWindow::DoLog(wxLogLevel level, const char *szString) { // first let the previous logger show it - if ( m_pOldLog != NULL ) { - // @@@ why can't we access protected wxLog method from here (we derive + if ( m_pOldLog != NULL && m_bPassMessages ) { + // @@@ why can't we access protected wxLog method from here (we derive // from wxLog)? gcc gives "DoLog is protected in this context", what // does this mean? Anyhow, the cast is harmless and let's us do what // we want. ((wxLogWindow *)m_pOldLog)->DoLog(level, szString); } - + // and this will format it nicely and call our DoLogString() wxLog::DoLog(level, szString); + + m_bHasMessages = TRUE; } void wxLogWindow::DoLogString(const char *szString) @@ -671,7 +726,7 @@ void wxLogWindow::DoLogString(const char *szString) wxTextCtrl *pText = m_pLogFrame->TextCtrl(); // remove selection (WriteText is in fact ReplaceSelection) - #ifdef __WINDOWS__ + #ifdef __WXMSW__ long nLen = pText->GetLastPosition(); pText->SetSelection(nLen, nLen); #endif // Windows @@ -683,9 +738,27 @@ void wxLogWindow::DoLogString(const char *szString) // @@@ TODO } +wxFrame *wxLogWindow::GetFrame() const +{ + return m_pLogFrame; +} + +void wxLogWindow::OnFrameCreate(wxFrame *frame) +{ +} + +void wxLogWindow::OnFrameDelete(wxFrame *frame) +{ + m_pLogFrame = NULL; +} + wxLogWindow::~wxLogWindow() { - m_pLogFrame->Close(TRUE); + // may be NULL if log frame already auto destroyed itself + delete m_pLogFrame; + + // delete the old log + delete m_pOldLog; } #endif //WX_TEST_MINIMAL @@ -698,7 +771,8 @@ wxLogWindow::~wxLogWindow() // static variables // ---------------------------------------------------------------------------- wxLog *wxLog::ms_pLogger = NULL; -bool wxLog::ms_bInitialized = FALSE; +bool wxLog::ms_bAutoCreate = TRUE; +wxTraceMask wxLog::ms_ulTraceMask = (wxTraceMask)0; // ---------------------------------------------------------------------------- // stdout error logging helper @@ -744,7 +818,7 @@ static void wxLogWrap(FILE *f, const char *pszPrefix, const char *psz) // get error code from syste unsigned long wxSysErrorCode() { - #ifdef __WINDOWS__ + #ifdef __WXMSW__ #ifdef __WIN32__ return ::GetLastError(); #else //WIN16 @@ -762,14 +836,14 @@ const char *wxSysErrorMsg(unsigned long nErrCode) if ( nErrCode == 0 ) nErrCode = wxSysErrorCode(); - #ifdef __WINDOWS__ + #ifdef __WXMSW__ #ifdef __WIN32__ static char s_szBuf[LOG_BUFFER_SIZE / 2]; // get error message from system LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, nErrCode, + NULL, nErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); @@ -780,7 +854,7 @@ const char *wxSysErrorMsg(unsigned long nErrCode) LocalFree(lpMsgBuf); // returned string is capitalized and ended with '\r\n' - bad - s_szBuf[0] = (char)tolower(s_szBuf[0]); + s_szBuf[0] = (char)wxToLower(s_szBuf[0]); size_t len = strlen(s_szBuf); if ( len > 0 ) { // truncate string @@ -802,13 +876,30 @@ const char *wxSysErrorMsg(unsigned long nErrCode) // debug helper // ---------------------------------------------------------------------------- -#ifdef __DEBUG__ +#ifdef __WXDEBUG__ + +void Trap() +{ + #ifdef __WXMSW__ + DebugBreak(); + #else // Unix + raise(SIGTRAP); + #endif // Win/Unix +} // this function is called when an assert fails void wxOnAssert(const char *szFile, int nLine, const char *szMsg) { // this variable can be set to true to suppress "assert failure" messages - static s_bNoAsserts = FALSE; + static bool s_bNoAsserts = FALSE; + static bool s_bInAssert = FALSE; + + if ( s_bInAssert ) { + // He-e-e-e-elp!! we're trapped in endless loop + Trap(); + } + + s_bInAssert = TRUE; char szBuf[LOG_BUFFER_SIZE]; sprintf(szBuf, _("Assert failed in file %s at line %d"), szFile, nLine); @@ -820,10 +911,10 @@ void wxOnAssert(const char *szFile, int nLine, const char *szMsg) strcat(szBuf, "."); } - // send it to the normal log destination - wxLogDebug(szBuf); - if ( !s_bNoAsserts ) { + // send it to the normal log destination + wxLogDebug(szBuf); + strcat(szBuf, _("\nDo you want to stop the program?" "\nYou can also choose [Cancel] to suppress " "further warnings.")); @@ -831,21 +922,19 @@ void wxOnAssert(const char *szFile, int nLine, const char *szMsg) switch ( wxMessageBox(szBuf, _("Debug"), wxYES_NO | wxCANCEL | wxICON_STOP ) ) { case wxYES: - #ifdef __WINDOWS__ - DebugBreak(); - #else // Unix - raise(SIGTRAP); - #endif // Win/Unix + Trap(); break; case wxCANCEL: s_bNoAsserts = TRUE; break; - + //case wxNO: nothing to do } } + + s_bInAssert = FALSE; } -#endif //DEBUG +#endif //WXDEBUG