1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/log.cpp 
   3 // Purpose:     Assorted wxLogXXX functions, and wxLog (sink for logs) 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  33     #include "wx/arrstr.h" 
  35     #include "wx/string.h" 
  39 #include "wx/apptrait.h" 
  40 #include "wx/datetime.h" 
  42 #include "wx/msgout.h" 
  43 #include "wx/textfile.h" 
  44 #include "wx/thread.h" 
  45 #include "wx/wxchar.h" 
  47 // other standard headers 
  57 #include "wx/msw/wince/time.h" 
  60 #if defined(__WINDOWS__) 
  61     #include "wx/msw/private.h" // includes windows.h 
  64 // ---------------------------------------------------------------------------- 
  65 // non member functions 
  66 // ---------------------------------------------------------------------------- 
  68 // define this to enable wrapping of log messages 
  69 //#define LOG_PRETTY_WRAP 
  71 #ifdef  LOG_PRETTY_WRAP 
  72   static void wxLogWrap(FILE *f
, const char *pszPrefix
, const char *psz
); 
  75 // ============================================================================ 
  77 // ============================================================================ 
  79 // ---------------------------------------------------------------------------- 
  80 // implementation of Log functions 
  82 // NB: unfortunately we need all these distinct functions, we can't make them 
  83 //     macros and not all compilers inline vararg functions. 
  84 // ---------------------------------------------------------------------------- 
  86 // generic log function 
  87 void wxVLogGeneric(wxLogLevel level
, const wxString
& format
, va_list argptr
) 
  89     if ( wxLog::IsEnabled() ) { 
  90         wxLog::OnLog(level
, wxString::FormatV(format
, argptr
), time(NULL
)); 
  94 #if !wxUSE_UTF8_LOCALE_ONLY 
  95 void wxDoLogGenericWchar(wxLogLevel level
, const wxChar 
*format
, ...) 
  98     va_start(argptr
, format
); 
  99     wxVLogGeneric(level
, format
, argptr
); 
 102 #endif // wxUSE_UTF8_LOCALE_ONLY 
 104 #if wxUSE_UNICODE_UTF8 
 105 void wxDoLogGenericUtf8(wxLogLevel level
, const char *format
, ...) 
 108     va_start(argptr
, format
); 
 109     wxVLogGeneric(level
, format
, argptr
); 
 112 #endif // wxUSE_UNICODE_UTF8 
 114 #if !wxUSE_UTF8_LOCALE_ONLY 
 115     #define IMPLEMENT_LOG_FUNCTION_WCHAR(level)                         \ 
 116       void wxDoLog##level##Wchar(const wxChar *format, ...)             \ 
 119         va_start(argptr, format);                                       \ 
 120         wxVLog##level(format, argptr);                                  \ 
 124     #define IMPLEMENT_LOG_FUNCTION_WCHAR(level) 
 127 #if wxUSE_UNICODE_UTF8 
 128     #define IMPLEMENT_LOG_FUNCTION_UTF8(level)                          \ 
 129       void wxDoLog##level##Utf8(const char *format, ...)                \ 
 132         va_start(argptr, format);                                       \ 
 133         wxVLog##level(format, argptr);                                  \ 
 137     #define IMPLEMENT_LOG_FUNCTION_UTF8(level) 
 140 #define IMPLEMENT_LOG_FUNCTION(level)                               \ 
 141   void wxVLog##level(const wxString& format, va_list argptr)        \ 
 143     if ( wxLog::IsEnabled() ) {                                     \ 
 144       wxLog::OnLog(wxLOG_##level,                                   \ 
 145                    wxString::FormatV(format, argptr), time(NULL));  \ 
 148   IMPLEMENT_LOG_FUNCTION_WCHAR(level)                               \ 
 149   IMPLEMENT_LOG_FUNCTION_UTF8(level) 
 151 IMPLEMENT_LOG_FUNCTION(Error
) 
 152 IMPLEMENT_LOG_FUNCTION(Warning
) 
 153 IMPLEMENT_LOG_FUNCTION(Message
) 
 154 IMPLEMENT_LOG_FUNCTION(Info
) 
 155 IMPLEMENT_LOG_FUNCTION(Status
) 
 157 void wxSafeShowMessage(const wxString
& title
, const wxString
& text
) 
 160     ::MessageBox(NULL
, text
, title
, MB_OK 
| MB_ICONSTOP
); 
 162     wxFprintf(stderr
, _T("%s: %s\n"), title
.c_str(), text
.c_str()); 
 167 // fatal errors can't be suppressed nor handled by the custom log target and 
 168 // always terminate the program 
 169 void wxVLogFatalError(const wxString
& format
, va_list argptr
) 
 171     wxSafeShowMessage(_T("Fatal Error"), wxString::FormatV(format
, argptr
)); 
 180 #if !wxUSE_UTF8_LOCALE_ONLY 
 181 void wxDoLogFatalErrorWchar(const wxChar 
*format
, ...) 
 184     va_start(argptr
, format
); 
 185     wxVLogFatalError(format
, argptr
); 
 187     // some compilers warn about unreachable code and it shouldn't matter 
 188     // for the others anyhow... 
 191 #endif // wxUSE_UTF8_LOCALE_ONLY 
 193 #if wxUSE_UNICODE_UTF8 
 194 void wxDoLogFatalErrorUtf8(const char *format
, ...) 
 197     va_start(argptr
, format
); 
 198     wxVLogFatalError(format
, argptr
); 
 200     // some compilers warn about unreachable code and it shouldn't matter 
 201     // for the others anyhow... 
 204 #endif // wxUSE_UNICODE_UTF8 
 206 // same as info, but only if 'verbose' mode is on 
 207 void wxVLogVerbose(const wxString
& format
, va_list argptr
) 
 209     if ( wxLog::IsEnabled() ) { 
 210         if ( wxLog::GetActiveTarget() != NULL 
&& wxLog::GetVerbose() ) { 
 211             wxLog::OnLog(wxLOG_Info
, 
 212                          wxString::FormatV(format
, argptr
), time(NULL
)); 
 217 #if !wxUSE_UTF8_LOCALE_ONLY 
 218 void wxDoLogVerboseWchar(const wxChar 
*format
, ...) 
 221     va_start(argptr
, format
); 
 222     wxVLogVerbose(format
, argptr
); 
 225 #endif // !wxUSE_UTF8_LOCALE_ONLY 
 227 #if wxUSE_UNICODE_UTF8 
 228 void wxDoLogVerboseUtf8(const char *format
, ...) 
 231     va_start(argptr
, format
); 
 232     wxVLogVerbose(format
, argptr
); 
 235 #endif // wxUSE_UNICODE_UTF8 
 240 #if !wxUSE_UTF8_LOCALE_ONLY 
 241     #define IMPLEMENT_LOG_DEBUG_FUNCTION_WCHAR(level)                   \ 
 242       void wxDoLog##level##Wchar(const wxChar *format, ...)             \ 
 245         va_start(argptr, format);                                       \ 
 246         wxVLog##level(format, argptr);                                  \ 
 250     #define IMPLEMENT_LOG_DEBUG_FUNCTION_WCHAR(level) 
 253 #if wxUSE_UNICODE_UTF8 
 254     #define IMPLEMENT_LOG_DEBUG_FUNCTION_UTF8(level)                    \ 
 255       void wxDoLog##level##Utf8(const char *format, ...)                \ 
 258         va_start(argptr, format);                                       \ 
 259         wxVLog##level(format, argptr);                                  \ 
 263     #define IMPLEMENT_LOG_DEBUG_FUNCTION_UTF8(level) 
 266 #define IMPLEMENT_LOG_DEBUG_FUNCTION(level)                         \ 
 267   void wxVLog##level(const wxString& format, va_list argptr)        \ 
 269     if ( wxLog::IsEnabled() ) {                                     \ 
 270       wxLog::OnLog(wxLOG_##level,                                   \ 
 271                    wxString::FormatV(format, argptr), time(NULL));  \ 
 274   IMPLEMENT_LOG_DEBUG_FUNCTION_WCHAR(level)                         \ 
 275   IMPLEMENT_LOG_DEBUG_FUNCTION_UTF8(level) 
 278   void wxVLogTrace(const wxString
& mask
, const wxString
& format
, va_list argptr
) 
 280     if ( wxLog::IsEnabled() && wxLog::IsAllowedTraceMask(mask
) ) { 
 282       msg 
<< _T("(") << mask 
<< _T(") ") << wxString::FormatV(format
, argptr
); 
 284       wxLog::OnLog(wxLOG_Trace
, msg
, time(NULL
)); 
 288 #if !wxUSE_UTF8_LOCALE_ONLY 
 289   void wxDoLogTraceWchar(const wxString
& mask
, const wxChar 
*format
, ...) 
 292     va_start(argptr
, format
); 
 293     wxVLogTrace(mask
, format
, argptr
); 
 296 #endif // !wxUSE_UTF8_LOCALE_ONLY 
 298 #if wxUSE_UNICODE_UTF8 
 299   void wxDoLogTraceUtf8(const wxString
& mask
, const char *format
, ...) 
 302     va_start(argptr
, format
); 
 303     wxVLogTrace(mask
, format
, argptr
); 
 306 #endif // wxUSE_UNICODE_UTF8 
 308   void wxVLogTrace(wxTraceMask mask
, const wxString
& format
, va_list argptr
) 
 310     // we check that all of mask bits are set in the current mask, so 
 311     // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something 
 312     // if both bits are set. 
 313     if ( wxLog::IsEnabled() && ((wxLog::GetTraceMask() & mask
) == mask
) ) { 
 314       wxLog::OnLog(wxLOG_Trace
, wxString::FormatV(format
, argptr
), time(NULL
)); 
 318 #if !wxUSE_UTF8_LOCALE_ONLY 
 319   void wxDoLogTraceWchar(wxTraceMask mask
, const wxChar 
*format
, ...) 
 322     va_start(argptr
, format
); 
 323     wxVLogTrace(mask
, format
, argptr
); 
 326 #endif // !wxUSE_UTF8_LOCALE_ONLY 
 328 #if wxUSE_UNICODE_UTF8 
 329   void wxDoLogTraceUtf8(wxTraceMask mask
, const char *format
, ...) 
 332     va_start(argptr
, format
); 
 333     wxVLogTrace(mask
, format
, argptr
); 
 336 #endif // wxUSE_UNICODE_UTF8 
 339   // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 
 340   void wxDoLogTrace(int mask
, const wxChar 
*format
, ...) 
 343     va_start(argptr
, format
); 
 344     wxVLogTrace(mask
, format
, argptr
); 
 348   void wxDoLogTrace(const char *mask
, const wxChar 
*format
, ...) 
 351     va_start(argptr
, format
); 
 352     wxVLogTrace(mask
, format
, argptr
); 
 356   void wxDoLogTrace(const wchar_t *mask
, const wxChar 
*format
, ...) 
 359     va_start(argptr
, format
); 
 360     wxVLogTrace(mask
, format
, argptr
); 
 364   void wxVLogTrace(int mask
, const wxString
& format
, va_list argptr
) 
 365     { wxVLogTrace((wxTraceMask
)mask
, format
, argptr
); } 
 366   void wxVLogTrace(const char *mask
, const wxString
& format
, va_list argptr
) 
 367     { wxVLogTrace(wxString(mask
), format
, argptr
); } 
 368   void wxVLogTrace(const wchar_t *mask
, const wxString
& format
, va_list argptr
) 
 369     { wxVLogTrace(wxString(mask
), format
, argptr
); } 
 370 #endif // __WATCOMC__ 
 373   #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) 
 376 IMPLEMENT_LOG_DEBUG_FUNCTION(Debug
) 
 377 IMPLEMENT_LOG_DEBUG_FUNCTION(Trace
) 
 379 // wxLogSysError: one uses the last error code, for other  you must give it 
 382 // return the system error message description 
 383 static inline wxString 
wxLogSysErrorHelper(long err
) 
 385     return wxString::Format(_(" (error %ld: %s)"), err
, wxSysErrorMsg(err
)); 
 388 void WXDLLEXPORT 
wxVLogSysError(const wxString
& format
, va_list argptr
) 
 390     wxVLogSysError(wxSysErrorCode(), format
, argptr
); 
 393 #if !wxUSE_UTF8_LOCALE_ONLY 
 394 void WXDLLEXPORT 
wxDoLogSysErrorWchar(const wxChar 
*format
, ...) 
 397     va_start(argptr
, format
); 
 398     wxVLogSysError(format
, argptr
); 
 401 #endif // !wxUSE_UTF8_LOCALE_ONLY 
 403 #if wxUSE_UNICODE_UTF8 
 404 void WXDLLEXPORT 
wxDoLogSysErrorUtf8(const char *format
, ...) 
 407     va_start(argptr
, format
); 
 408     wxVLogSysError(format
, argptr
); 
 411 #endif // wxUSE_UNICODE_UTF8 
 413 void WXDLLEXPORT 
wxVLogSysError(long err
, const wxString
& format
, va_list argptr
) 
 415     if ( wxLog::IsEnabled() ) { 
 416         wxLog::OnLog(wxLOG_Error
, 
 417                      wxString::FormatV(format
, argptr
) + wxLogSysErrorHelper(err
), 
 422 #if !wxUSE_UTF8_LOCALE_ONLY 
 423 void WXDLLEXPORT 
wxDoLogSysErrorWchar(long lErrCode
, const wxChar 
*format
, ...) 
 426     va_start(argptr
, format
); 
 427     wxVLogSysError(lErrCode
, format
, argptr
); 
 430 #endif // !wxUSE_UTF8_LOCALE_ONLY 
 432 #if wxUSE_UNICODE_UTF8 
 433 void WXDLLEXPORT 
wxDoLogSysErrorUtf8(long lErrCode
, const char *format
, ...) 
 436     va_start(argptr
, format
); 
 437     wxVLogSysError(lErrCode
, format
, argptr
); 
 440 #endif // wxUSE_UNICODE_UTF8 
 443 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 
 444 void WXDLLEXPORT 
wxDoLogSysError(unsigned long lErrCode
, const wxChar 
*format
, ...) 
 447     va_start(argptr
, format
); 
 448     wxVLogSysError(lErrCode
, format
, argptr
); 
 452 void WXDLLEXPORT 
wxVLogSysError(unsigned long err
, const wxChar 
*format
, va_list argptr
) 
 453     { wxVLogSysError((long)err
, format
, argptr
); } 
 454 #endif // __WATCOMC__ 
 456 // ---------------------------------------------------------------------------- 
 457 // wxLog class implementation 
 458 // ---------------------------------------------------------------------------- 
 461 unsigned wxLog::DoLogNumberOfRepeats() 
 463     long retval 
= ms_prevCounter
; 
 464     wxLog 
*pLogger 
= GetActiveTarget(); 
 465     if ( pLogger 
&& ms_prevCounter 
> 0 ) 
 469         msg
.Printf(wxPLURAL("The previous message repeated once.", 
 470                             "The previous message repeated %lu times.", 
 474         msg
.Printf(wxT("The previous message was repeated.")); 
 477         ms_prevString
.clear(); 
 478         pLogger
->DoLog(ms_prevLevel
, msg
.c_str(), ms_prevTimeStamp
); 
 485     if ( ms_prevCounter 
> 0 ) 
 487         // looks like the repeat count has not been logged yet, 
 488         // so let's do it now 
 489         wxLog::DoLogNumberOfRepeats(); 
 494 void wxLog::OnLog(wxLogLevel level
, const wxChar 
*szString
, time_t t
) 
 496     if ( IsEnabled() && ms_logLevel 
>= level 
) 
 498         wxLog 
*pLogger 
= GetActiveTarget(); 
 501             if ( GetRepetitionCounting() && ms_prevString 
== szString 
) 
 507                 if ( GetRepetitionCounting() ) 
 509                     DoLogNumberOfRepeats(); 
 511                 ms_prevString 
= szString
; 
 512                 ms_prevLevel 
= level
; 
 513                 ms_prevTimeStamp 
= t
; 
 514                 pLogger
->DoLog(level
, szString
, t
); 
 520 // deprecated function 
 521 #if WXWIN_COMPATIBILITY_2_6 
 523 wxChar 
*wxLog::SetLogBuffer(wxChar 
* WXUNUSED(buf
), size_t WXUNUSED(size
)) 
 528 #endif // WXWIN_COMPATIBILITY_2_6 
 530 wxLog 
*wxLog::GetActiveTarget() 
 532     if ( ms_bAutoCreate 
&& ms_pLogger 
== NULL 
) { 
 533         // prevent infinite recursion if someone calls wxLogXXX() from 
 534         // wxApp::CreateLogTarget() 
 535         static bool s_bInGetActiveTarget 
= false; 
 536         if ( !s_bInGetActiveTarget 
) { 
 537             s_bInGetActiveTarget 
= true; 
 539             // ask the application to create a log target for us 
 540             if ( wxTheApp 
!= NULL 
) 
 541                 ms_pLogger 
= wxTheApp
->GetTraits()->CreateLogTarget(); 
 543                 ms_pLogger 
= new wxLogStderr
; 
 545             s_bInGetActiveTarget 
= false; 
 547             // do nothing if it fails - what can we do? 
 554 wxLog 
*wxLog::SetActiveTarget(wxLog 
*pLogger
) 
 556     if ( ms_pLogger 
!= NULL 
) { 
 557         // flush the old messages before changing because otherwise they might 
 558         // get lost later if this target is not restored 
 562     wxLog 
*pOldLogger 
= ms_pLogger
; 
 563     ms_pLogger 
= pLogger
; 
 568 void wxLog::DontCreateOnDemand() 
 570     ms_bAutoCreate 
= false; 
 572     // this is usually called at the end of the program and we assume that it 
 573     // is *always* called at the end - so we free memory here to avoid false 
 574     // memory leak reports from wxWin  memory tracking code 
 578 void wxLog::RemoveTraceMask(const wxString
& str
) 
 580     int index 
= ms_aTraceMasks
.Index(str
); 
 581     if ( index 
!= wxNOT_FOUND 
) 
 582         ms_aTraceMasks
.RemoveAt((size_t)index
); 
 585 void wxLog::ClearTraceMasks() 
 587     ms_aTraceMasks
.Clear(); 
 590 void wxLog::TimeStamp(wxString 
*str
) 
 597         (void)time(&timeNow
); 
 600         wxStrftime(buf
, WXSIZEOF(buf
), 
 601                     ms_timestamp
, wxLocaltime_r(&timeNow
, &tm
)); 
 604         *str 
<< buf 
<< wxT(": "); 
 606 #endif // wxUSE_DATETIME 
 609 void wxLog::DoLog(wxLogLevel level
, const wxChar 
*szString
, time_t t
) 
 612         case wxLOG_FatalError
: 
 613             DoLogString(wxString(_("Fatal error: ")) + szString
, t
); 
 614             DoLogString(_("Program aborted."), t
); 
 624             DoLogString(wxString(_("Error: ")) + szString
, t
); 
 628             DoLogString(wxString(_("Warning: ")) + szString
, t
); 
 635         default:    // log unknown log levels too 
 636                 DoLogString(szString
, t
); 
 643                 wxString msg 
= level 
== wxLOG_Trace 
? wxT("Trace: ") 
 653 void wxLog::DoLogString(const wxChar 
*WXUNUSED(szString
), time_t WXUNUSED(t
)) 
 655     wxFAIL_MSG(wxT("DoLogString must be overriden if it's called.")); 
 660     // nothing to do here 
 663 /*static*/ bool wxLog::IsAllowedTraceMask(const wxChar 
*mask
) 
 665     for ( wxArrayString::iterator it 
= ms_aTraceMasks
.begin(), 
 666                                   en 
= ms_aTraceMasks
.end(); 
 673 // ---------------------------------------------------------------------------- 
 674 // wxLogBuffer implementation 
 675 // ---------------------------------------------------------------------------- 
 677 void wxLogBuffer::Flush() 
 679     if ( !m_str
.empty() ) 
 681         wxMessageOutputBest out
; 
 682         out
.Printf(_T("%s"), m_str
.c_str()); 
 687 void wxLogBuffer::DoLog(wxLogLevel level
, const wxChar 
*szString
, time_t t
) 
 694             // don't put debug messages in the buffer, we don't want to show 
 695             // them to the user in a msg box, log them immediately 
 701                 wxMessageOutputDebug dbgout
; 
 702                 dbgout
.Printf(_T("%s\n"), str
.c_str()); 
 704 #endif // __WXDEBUG__ 
 708             wxLog::DoLog(level
, szString
, t
); 
 712 void wxLogBuffer::DoLogString(const wxChar 
*szString
, time_t WXUNUSED(t
)) 
 714     m_str 
<< szString 
<< _T("\n"); 
 717 // ---------------------------------------------------------------------------- 
 718 // wxLogStderr class implementation 
 719 // ---------------------------------------------------------------------------- 
 721 wxLogStderr::wxLogStderr(FILE *fp
) 
 729 void wxLogStderr::DoLogString(const wxChar 
*szString
, time_t WXUNUSED(t
)) 
 736     wxFputc(_T('\n'), m_fp
); 
 739     // under GUI systems such as Windows or Mac, programs usually don't have 
 740     // stderr at all, so show the messages also somewhere else, typically in 
 741     // the debugger window so that they go at least somewhere instead of being 
 743     if ( m_fp 
== stderr 
) 
 745         wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
 746         if ( traits 
&& !traits
->HasStderr() ) 
 748             wxMessageOutputDebug dbgout
; 
 749             dbgout
.Printf(_T("%s\n"), str
.c_str()); 
 754 // ---------------------------------------------------------------------------- 
 755 // wxLogStream implementation 
 756 // ---------------------------------------------------------------------------- 
 758 #if wxUSE_STD_IOSTREAM 
 759 #include "wx/ioswrap.h" 
 760 wxLogStream::wxLogStream(wxSTD ostream 
*ostr
) 
 763         m_ostr 
= &wxSTD cerr
; 
 768 void wxLogStream::DoLogString(const wxChar 
*szString
, time_t WXUNUSED(t
)) 
 772     (*m_ostr
) << wxConvertWX2MB(str
) << wxConvertWX2MB(szString
) << wxSTD endl
; 
 774 #endif // wxUSE_STD_IOSTREAM 
 776 // ---------------------------------------------------------------------------- 
 778 // ---------------------------------------------------------------------------- 
 780 wxLogChain::wxLogChain(wxLog 
*logger
) 
 782     m_bPassMessages 
= true; 
 785     m_logOld 
= wxLog::SetActiveTarget(this); 
 788 wxLogChain::~wxLogChain() 
 792     if ( m_logNew 
!= this ) 
 796 void wxLogChain::SetLog(wxLog 
*logger
) 
 798     if ( m_logNew 
!= this ) 
 804 void wxLogChain::Flush() 
 809     // be careful to avoid infinite recursion 
 810     if ( m_logNew 
&& m_logNew 
!= this ) 
 814 void wxLogChain::DoLog(wxLogLevel level
, const wxChar 
*szString
, time_t t
) 
 816     // let the previous logger show it 
 817     if ( m_logOld 
&& IsPassingMessages() ) 
 819         // bogus cast just to access protected DoLog 
 820         ((wxLogChain 
*)m_logOld
)->DoLog(level
, szString
, t
); 
 823     if ( m_logNew 
&& m_logNew 
!= this ) 
 826         ((wxLogChain 
*)m_logNew
)->DoLog(level
, szString
, t
); 
 830 // ---------------------------------------------------------------------------- 
 832 // ---------------------------------------------------------------------------- 
 835     // "'this' : used in base member initializer list" - so what? 
 836     #pragma warning(disable:4355) 
 839 wxLogPassThrough::wxLogPassThrough() 
 845     #pragma warning(default:4355) 
 848 // ============================================================================ 
 849 // Global functions/variables 
 850 // ============================================================================ 
 852 // ---------------------------------------------------------------------------- 
 854 // ---------------------------------------------------------------------------- 
 856 bool            wxLog::ms_bRepetCounting 
= false; 
 857 wxString        
wxLog::ms_prevString
; 
 858 unsigned int    wxLog::ms_prevCounter 
= 0; 
 859 time_t          wxLog::ms_prevTimeStamp
= 0; 
 860 wxLogLevel      
wxLog::ms_prevLevel
; 
 862 wxLog          
*wxLog::ms_pLogger      
= (wxLog 
*)NULL
; 
 863 bool            wxLog::ms_doLog        
= true; 
 864 bool            wxLog::ms_bAutoCreate  
= true; 
 865 bool            wxLog::ms_bVerbose     
= false; 
 867 wxLogLevel      
wxLog::ms_logLevel     
= wxLOG_Max
;  // log everything by default 
 869 size_t          wxLog::ms_suspendCount 
= 0; 
 871 const wxChar   
*wxLog::ms_timestamp    
= wxT("%X");  // time only, no date 
 873 wxTraceMask     
wxLog::ms_ulTraceMask  
= (wxTraceMask
)0; 
 874 wxArrayString   
wxLog::ms_aTraceMasks
; 
 876 // ---------------------------------------------------------------------------- 
 877 // stdout error logging helper 
 878 // ---------------------------------------------------------------------------- 
 880 // helper function: wraps the message and justifies it under given position 
 881 // (looks more pretty on the terminal). Also adds newline at the end. 
 883 // TODO this is now disabled until I find a portable way of determining the 
 884 //      terminal window size (ok, I found it but does anybody really cares?) 
 885 #ifdef LOG_PRETTY_WRAP 
 886 static void wxLogWrap(FILE *f
, const char *pszPrefix
, const char *psz
) 
 888     size_t nMax 
= 80; // FIXME 
 889     size_t nStart 
= strlen(pszPrefix
); 
 893     while ( *psz 
!= '\0' ) { 
 894         for ( n 
= nStart
; (n 
< nMax
) && (*psz 
!= '\0'); n
++ ) 
 898         if ( *psz 
!= '\0' ) { 
 900             for ( n 
= 0; n 
< nStart
; n
++ ) 
 903             // as we wrapped, squeeze all white space 
 904             while ( isspace(*psz
) ) 
 911 #endif  //LOG_PRETTY_WRAP 
 913 // ---------------------------------------------------------------------------- 
 914 // error code/error message retrieval functions 
 915 // ---------------------------------------------------------------------------- 
 917 // get error code from syste 
 918 unsigned long wxSysErrorCode() 
 920 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 921     return ::GetLastError(); 
 927 // get error message from system 
 928 const wxChar 
*wxSysErrorMsg(unsigned long nErrCode
) 
 931         nErrCode 
= wxSysErrorCode(); 
 933 #if defined(__WXMSW__) && !defined(__WXMICROWIN__) 
 934     static wxChar s_szBuf
[1024]; 
 936     // get error message from system 
 940             FORMAT_MESSAGE_ALLOCATE_BUFFER 
| FORMAT_MESSAGE_FROM_SYSTEM
, 
 943             MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), 
 949         // if this happens, something is seriously wrong, so don't use _() here 
 951         wxSprintf(s_szBuf
, _T("unknown error %lx"), nErrCode
); 
 956     // copy it to our buffer and free memory 
 957     // Crashes on SmartPhone (FIXME) 
 958 #if !defined(__SMARTPHONE__) /* of WinCE */ 
 961         wxStrncpy(s_szBuf
, (const wxChar 
*)lpMsgBuf
, WXSIZEOF(s_szBuf
) - 1); 
 962         s_szBuf
[WXSIZEOF(s_szBuf
) - 1] = wxT('\0'); 
 966         // returned string is capitalized and ended with '\r\n' - bad 
 967         s_szBuf
[0] = (wxChar
)wxTolower(s_szBuf
[0]); 
 968         size_t len 
= wxStrlen(s_szBuf
); 
 971             if ( s_szBuf
[len 
- 2] == wxT('\r') ) 
 972                 s_szBuf
[len 
- 2] = wxT('\0'); 
 976 #endif // !__SMARTPHONE__ 
 978         s_szBuf
[0] = wxT('\0'); 
 984         static wchar_t s_wzBuf
[1024]; 
 985         wxConvCurrent
->MB2WC(s_wzBuf
, strerror((int)nErrCode
), 
 986                              WXSIZEOF(s_wzBuf
) - 1); 
 989         return strerror((int)nErrCode
); 
 991 #endif  // __WXMSW__/!__WXMSW__