1 ///////////////////////////////////////////////////////////////////////////// 
   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 ///////////////////////////////////////////////////////////////////////////// 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // NB: this is needed even if wxUSE_LOG == 0 
  22 typedef unsigned long wxLogLevel
; 
  24 // the trace masks have been superseded by symbolic trace constants, they're 
  25 // for compatibility only and will be removed soon - do NOT use them 
  26 #if WXWIN_COMPATIBILITY_2_8 
  27     #define wxTraceMemAlloc 0x0001  // trace memory allocation (new/delete) 
  28     #define wxTraceMessages 0x0002  // trace window messages/X callbacks 
  29     #define wxTraceResAlloc 0x0004  // trace GDI resource allocation 
  30     #define wxTraceRefCount 0x0008  // trace various ref counting operations 
  33         #define wxTraceOleCalls 0x0100  // OLE interface calls 
  36     typedef unsigned long wxTraceMask
; 
  37 #endif // WXWIN_COMPATIBILITY_2_8 
  39 // ---------------------------------------------------------------------------- 
  41 // ---------------------------------------------------------------------------- 
  43 #include "wx/string.h" 
  44 #include "wx/strvararg.h" 
  46 // ---------------------------------------------------------------------------- 
  47 // forward declarations 
  48 // ---------------------------------------------------------------------------- 
  50 class WXDLLIMPEXP_FWD_BASE wxObject
; 
  53     class WXDLLIMPEXP_FWD_CORE wxFrame
; 
  58 #include "wx/arrstr.h" 
  62     #include <time.h>   // for time_t 
  64 #endif // ! __WXPALMOS5__ 
  66 #include "wx/dynarray.h" 
  67 #include "wx/hashmap.h" 
  70     #include "wx/thread.h" 
  71 #endif // wxUSE_THREADS 
  73 // wxUSE_LOG_DEBUG enables the debug log messages 
  74 #ifndef wxUSE_LOG_DEBUG 
  76         #define wxUSE_LOG_DEBUG 1 
  77     #else // !wxDEBUG_LEVEL 
  78         #define wxUSE_LOG_DEBUG 0 
  82 // wxUSE_LOG_TRACE enables the trace messages, they are disabled by default 
  83 #ifndef wxUSE_LOG_TRACE 
  85         #define wxUSE_LOG_TRACE 1 
  86     #else // !wxDEBUG_LEVEL 
  87         #define wxUSE_LOG_TRACE 0 
  89 #endif // wxUSE_LOG_TRACE 
  91 // wxLOG_COMPONENT identifies the component which generated the log record and 
  92 // can be #define'd to a user-defined value when compiling the user code to use 
  93 // component-based filtering (see wxLog::SetComponentLevel()) 
  94 #ifndef wxLOG_COMPONENT 
  95     // this is a variable and not a macro in order to allow the user code to 
  96     // just #define wxLOG_COMPONENT without #undef'ining it first 
  97     extern WXDLLIMPEXP_DATA_BASE(const char *) wxLOG_COMPONENT
; 
 100         #define wxLOG_COMPONENT "wx" 
 104 // ---------------------------------------------------------------------------- 
 106 // ---------------------------------------------------------------------------- 
 108 // different standard log levels (you may also define your own) 
 109 enum wxLogLevelValues
 
 111     wxLOG_FatalError
, // program can't continue, abort immediately 
 112     wxLOG_Error
,      // a serious error, user must be informed about it 
 113     wxLOG_Warning
,    // user is normally informed about it but may be ignored 
 114     wxLOG_Message
,    // normal message (i.e. normal output of a non GUI app) 
 115     wxLOG_Status
,     // informational: might go to the status line of GUI app 
 116     wxLOG_Info
,       // informational message (a.k.a. 'Verbose') 
 117     wxLOG_Debug
,      // never shown to the user, disabled in release mode 
 118     wxLOG_Trace
,      // trace messages are also only enabled in debug mode 
 119     wxLOG_Progress
,   // used for progress indicator (not yet) 
 120     wxLOG_User 
= 100, // user defined levels start here 
 124 // symbolic trace masks - wxLogTrace("foo", "some trace message...") will be 
 125 // discarded unless the string "foo" has been added to the list of allowed 
 126 // ones with AddTraceMask() 
 128 #define wxTRACE_MemAlloc wxT("memalloc") // trace memory allocation (new/delete) 
 129 #define wxTRACE_Messages wxT("messages") // trace window messages/X callbacks 
 130 #define wxTRACE_ResAlloc wxT("resalloc") // trace GDI resource allocation 
 131 #define wxTRACE_RefCount wxT("refcount") // trace various ref counting operations 
 134     #define wxTRACE_OleCalls wxT("ole")  // OLE interface calls 
 137 #include "wx/iosfwrap.h" 
 139 // ---------------------------------------------------------------------------- 
 140 // information about a log record, i.e. unit of log output 
 141 // ---------------------------------------------------------------------------- 
 143 class wxLogRecordInfo
 
 146     // default ctor creates an uninitialized object 
 149         memset(this, 0, sizeof(*this)); 
 152     // normal ctor, used by wxLogger specifies the location of the log 
 153     // statement; its time stamp and thread id are set up here 
 154     wxLogRecordInfo(const char *filename_
, 
 157                     const char *component_
) 
 159         filename 
= filename_
; 
 162         component 
= component_
; 
 164         timestamp 
= time(NULL
); 
 167         threadId 
= wxThread::GetCurrentId(); 
 168 #endif // wxUSE_THREADS 
 173     // we need to define copy ctor and assignment operator because of m_data 
 174     wxLogRecordInfo(const wxLogRecordInfo
& other
) 
 179     wxLogRecordInfo
& operator=(const wxLogRecordInfo
& other
) 
 181         if ( &other 
!= this ) 
 190     // dtor is non-virtual, this class is not meant to be derived from 
 197     // the file name and line number of the file where the log record was 
 198     // generated, if available or NULL and 0 otherwise 
 199     const char *filename
; 
 202     // the name of the function where the log record was generated (may be NULL 
 203     // if the compiler doesn't support __FUNCTION__) 
 206     // the name of the component which generated this message, may be NULL if 
 207     // not set (i.e. wxLOG_COMPONENT not defined) 
 208     const char *component
; 
 210     // time of record generation 
 214     // id of the thread which logged this record 
 215     wxThreadIdType threadId
; 
 216 #endif // wxUSE_THREADS 
 219     // store an arbitrary value in this record context 
 221     // wxWidgets always uses keys starting with "wx.", e.g. "wx.sys_error" 
 222     void StoreValue(const wxString
& key
, wxUIntPtr val
) 
 225             m_data 
= new ExtraData
; 
 227         m_data
->numValues
[key
] = val
; 
 230     void StoreValue(const wxString
& key
, const wxString
& val
) 
 233             m_data 
= new ExtraData
; 
 235         m_data
->strValues
[key
] = val
; 
 239     // these functions retrieve the value of either numeric or string key, 
 240     // return false if not found 
 241     bool GetNumValue(const wxString
& key
, wxUIntPtr 
*val
) const 
 246         wxStringToNumHashMap::const_iterator it 
= m_data
->numValues
.find(key
); 
 247         if ( it 
== m_data
->numValues
.end() ) 
 255     bool GetStrValue(const wxString
& key
, wxString 
*val
) const 
 260         wxStringToStringHashMap::const_iterator it 
= m_data
->strValues
.find(key
); 
 261         if ( it 
== m_data
->strValues
.end() ) 
 270     void Copy(const wxLogRecordInfo
& other
) 
 272         memcpy(this, &other
, sizeof(*this)); 
 274            m_data 
= new ExtraData(*other
.m_data
); 
 277     // extra data associated with the log record: this is completely optional 
 278     // and can be used to pass information from the log function to the log 
 279     // sink (e.g. wxLogSysError() uses this to pass the error code) 
 282         wxStringToNumHashMap numValues
; 
 283         wxStringToStringHashMap strValues
; 
 290 #define wxLOG_KEY_TRACE_MASK "wx.trace_mask" 
 292 // ---------------------------------------------------------------------------- 
 293 // log record: a unit of log output 
 294 // ---------------------------------------------------------------------------- 
 298     wxLogRecord(wxLogLevel level_
, 
 299                 const wxString
& msg_
, 
 300                 const wxLogRecordInfo
& info_
) 
 309     wxLogRecordInfo info
; 
 312 // ---------------------------------------------------------------------------- 
 313 // derive from this class to redirect (or suppress, or ...) log messages 
 314 // normally, only a single instance of this class exists but it's not enforced 
 315 // ---------------------------------------------------------------------------- 
 317 class WXDLLIMPEXP_BASE wxLog
 
 323     // make dtor virtual for all derived classes 
 327     // log messages selection 
 328     // ---------------------- 
 330     // these functions allow to completely disable all log messages or disable 
 331     // log messages at level less important than specified for the current 
 334     // is logging enabled at all now? 
 335     static bool IsEnabled() 
 338         if ( !wxThread::IsMain() ) 
 339             return IsThreadLoggingEnabled(); 
 340 #endif // wxUSE_THREADS 
 345     // change the flag state, return the previous one 
 346     static bool EnableLogging(bool enable 
= true) 
 349         if ( !wxThread::IsMain() ) 
 350             return EnableThreadLogging(enable
); 
 351 #endif // wxUSE_THREADS 
 353         bool doLogOld 
= ms_doLog
; 
 358     // return the current global log level 
 359     static wxLogLevel 
GetLogLevel() { return ms_logLevel
; } 
 361     // set global log level: messages with level > logLevel will not be logged 
 362     static void SetLogLevel(wxLogLevel logLevel
) { ms_logLevel 
= logLevel
; } 
 364     // set the log level for the given component 
 365     static void SetComponentLevel(const wxString
& component
, wxLogLevel level
); 
 367     // return the effective log level for this component, falling back to 
 368     // parent component and to the default global log level if necessary 
 370     // NB: component argument is passed by value and not const reference in an 
 371     //     attempt to encourage compiler to avoid an extra copy: as we modify 
 372     //     the component internally, we'd create one anyhow and like this it 
 373     //     can be avoided if the string is a temporary anyhow 
 374     static wxLogLevel 
GetComponentLevel(wxString component
); 
 377     // is logging of messages from this component enabled at this level? 
 379     // usually always called with wxLOG_COMPONENT as second argument 
 380     static bool IsLevelEnabled(wxLogLevel level
, wxString component
) 
 382         return IsEnabled() && level 
<= GetComponentLevel(component
); 
 386     // enable/disable messages at wxLOG_Verbose level (only relevant if the 
 387     // current log level is greater or equal to it) 
 389     // notice that verbose mode can be activated by the standard command-line 
 390     // '--verbose' option 
 391     static void SetVerbose(bool bVerbose 
= true) { ms_bVerbose 
= bVerbose
; } 
 393     // check if verbose messages are enabled 
 394     static bool GetVerbose() { return ms_bVerbose
; } 
 400     // flush shows all messages if they're not logged immediately (FILE 
 401     // and iostream logs don't need it, but wxLogGui does to avoid showing 
 402     // 17 modal dialogs one after another) 
 403     virtual void Flush(); 
 405     // flush the active target if any and also output any pending messages from 
 406     // background threads 
 407     static void FlushActive(); 
 409     // only one sink is active at each moment get current log target, will call 
 410     // wxAppTraits::CreateLogTarget() to create one if none exists 
 411     static wxLog 
*GetActiveTarget(); 
 413     // change log target, logger may be NULL 
 414     static wxLog 
*SetActiveTarget(wxLog 
*logger
); 
 417     // change log target for the current thread only, shouldn't be called from 
 418     // the main thread as it doesn't use thread-specific log target 
 419     static wxLog 
*SetThreadActiveTarget(wxLog 
*logger
); 
 420 #endif // wxUSE_THREADS 
 422     // suspend the message flushing of the main target until the next call 
 423     // to Resume() - this is mainly for internal use (to prevent wxYield() 
 424     // from flashing the messages) 
 425     static void Suspend() { ms_suspendCount
++; } 
 427     // must be called for each Suspend()! 
 428     static void Resume() { ms_suspendCount
--; } 
 430     // should GetActiveTarget() try to create a new log object if the 
 432     static void DontCreateOnDemand(); 
 434     // Make GetActiveTarget() create a new log object again. 
 435     static void DoCreateOnDemand(); 
 437     // log the count of repeating messages instead of logging the messages 
 439     static void SetRepetitionCounting(bool bRepetCounting 
= true) 
 440         { ms_bRepetCounting 
= bRepetCounting
; } 
 442     // gets duplicate counting status 
 443     static bool GetRepetitionCounting() { return ms_bRepetCounting
; } 
 445     // add string trace mask 
 446     static void AddTraceMask(const wxString
& str
); 
 448     // add string trace mask 
 449     static void RemoveTraceMask(const wxString
& str
); 
 451     // remove all string trace masks 
 452     static void ClearTraceMasks(); 
 454     // get string trace masks: note that this is MT-unsafe if other threads can 
 455     // call AddTraceMask() concurrently 
 456     static const wxArrayString
& GetTraceMasks(); 
 458     // sets the time stamp string format: this is used as strftime() format 
 459     // string for the log targets which add time stamps to the messages; set 
 460     // it to empty string to disable time stamping completely. 
 461     static void SetTimestamp(const wxString
& ts
) { ms_timestamp 
= ts
; } 
 463     // disable time stamping of log messages 
 464     static void DisableTimestamp() { SetTimestamp(wxEmptyString
); } 
 467     // is this trace mask in the list? 
 468     static bool IsAllowedTraceMask(const wxString
& mask
); 
 470     // get the current timestamp format string (maybe empty) 
 471     static const wxString
& GetTimestamp() { return ms_timestamp
; } 
 475     // helpers: all functions in this section are mostly for internal use only, 
 476     // don't call them from your code even if they are not formally deprecated 
 478     // put the time stamp into the string if ms_timestamp != NULL (don't 
 479     // change it otherwise) 
 480     static void TimeStamp(wxString 
*str
); 
 482     // these methods should only be called from derived classes DoLogRecord(), 
 483     // DoLogTextAtLevel() and DoLogText() implementations respectively and 
 484     // shouldn't be called directly, use logging functions instead 
 485     void LogRecord(wxLogLevel level
, 
 487                    const wxLogRecordInfo
& info
) 
 489         DoLogRecord(level
, msg
, info
); 
 492     void LogTextAtLevel(wxLogLevel level
, const wxString
& msg
) 
 494         DoLogTextAtLevel(level
, msg
); 
 497     void LogText(const wxString
& msg
) 
 502     // this is a helper used by wxLogXXX() functions, don't call it directly 
 503     // and see DoLog() for function to overload in the derived classes 
 504     static void OnLog(wxLogLevel level
, 
 506                       const wxLogRecordInfo
& info
); 
 508     // version called when no information about the location of the log record 
 509     // generation is available (but the time stamp is), it mainly exists for 
 510     // backwards compatibility, don't use it in new code 
 511     static void OnLog(wxLogLevel level
, const wxString
& msg
, time_t t
); 
 513     // a helper calling the above overload with current time 
 514     static void OnLog(wxLogLevel level
, const wxString
& msg
) 
 516         OnLog(level
, msg
, time(NULL
)); 
 520     // this method exists for backwards compatibility only, don't use 
 521     bool HasPendingMessages() const { return true; } 
 523 #if WXWIN_COMPATIBILITY_2_6 
 524     // this function doesn't do anything any more, don't call it 
 525     static wxDEPRECATED_INLINE( 
 526         wxChar 
*SetLogBuffer(wxChar 
*, size_t = 0), return NULL
; 
 528 #endif // WXWIN_COMPATIBILITY_2_6 
 530     // don't use integer masks any more, use string trace masks instead 
 531 #if WXWIN_COMPATIBILITY_2_8 
 532     static wxDEPRECATED_INLINE( void SetTraceMask(wxTraceMask ulMask
), 
 533         ms_ulTraceMask 
= ulMask
; ) 
 535     // this one can't be marked deprecated as it's used in our own wxLogger 
 536     // below but it still is deprecated and shouldn't be used 
 537     static wxTraceMask 
GetTraceMask() { return ms_ulTraceMask
; } 
 538 #endif // WXWIN_COMPATIBILITY_2_8 
 541     // the logging functions that can be overridden: DoLogRecord() is called 
 542     // for every "record", i.e. a unit of log output, to be logged and by 
 543     // default formats the message and passes it to DoLogTextAtLevel() which in 
 544     // turn passes it to DoLogText() by default 
 546     // override this method if you want to change message formatting or do 
 548     virtual void DoLogRecord(wxLogLevel level
, 
 550                              const wxLogRecordInfo
& info
); 
 552     // override this method to redirect output to different channels depending 
 553     // on its level only; if even the level doesn't matter, override 
 554     // DoLogText() instead 
 555     virtual void DoLogTextAtLevel(wxLogLevel level
, const wxString
& msg
); 
 557     // this function is not pure virtual as it might not be needed if you do 
 558     // the logging in overridden DoLogRecord() or DoLogTextAtLevel() directly 
 559     // but if you do not override them in your derived class you must override 
 560     // this one as the default implementation of it simply asserts 
 561     virtual void DoLogText(const wxString
& msg
); 
 564     // the rest of the functions are for backwards compatibility only, don't 
 565     // use them in new code; if you're updating your existing code you need to 
 566     // switch to overriding DoLogRecord/Text() above (although as long as these 
 567     // functions exist, log classes using them will continue to work) 
 568 #if WXWIN_COMPATIBILITY_2_8 
 569     wxDEPRECATED_BUT_USED_INTERNALLY( 
 570         virtual void DoLog(wxLogLevel level
, const char *szString
, time_t t
) 
 573     wxDEPRECATED_BUT_USED_INTERNALLY( 
 574         virtual void DoLog(wxLogLevel level
, const wchar_t *wzString
, time_t t
) 
 577     // these shouldn't be used by new code 
 578     wxDEPRECATED_BUT_USED_INTERNALLY_INLINE( 
 579         virtual void DoLogString(const char *WXUNUSED(szString
), 
 581         wxEMPTY_PARAMETER_VALUE
 
 584     wxDEPRECATED_BUT_USED_INTERNALLY_INLINE( 
 585         virtual void DoLogString(const wchar_t *WXUNUSED(wzString
), 
 587         wxEMPTY_PARAMETER_VALUE
 
 589 #endif // WXWIN_COMPATIBILITY_2_8 
 592     // log a message indicating the number of times the previous message was 
 593     // repeated if previous repetition counter is strictly positive, does 
 594     // nothing otherwise; return the old value of repetition counter 
 595     unsigned LogLastRepeatIfNeeded(); 
 599     // called from FlushActive() to really log any buffered messages logged 
 600     // from the other threads 
 601     void FlushThreadMessages(); 
 603     // these functions are called for non-main thread only by IsEnabled() and 
 604     // EnableLogging() respectively 
 605     static bool IsThreadLoggingEnabled(); 
 606     static bool EnableThreadLogging(bool enable 
= true); 
 607 #endif // wxUSE_THREADS 
 609     // get the active log target for the main thread, auto-creating it if 
 612     // this is called from GetActiveTarget() and OnLog() when they're called 
 613     // from the main thread 
 614     static wxLog 
*GetMainThreadActiveTarget(); 
 616     // called from OnLog() if it's called from the main thread or if we have a 
 617     // (presumably MT-safe) thread-specific logger and by FlushThreadMessages() 
 618     // when it plays back the buffered messages logged from the other threads 
 619     void CallDoLogNow(wxLogLevel level
, 
 621                       const wxLogRecordInfo
& info
); 
 627     // if true, don't log the same message multiple times, only log it once 
 628     // with the number of times it was repeated 
 629     static bool        ms_bRepetCounting
; 
 631     static wxLog      
*ms_pLogger
;      // currently active log sink 
 632     static bool        ms_doLog
;        // false => all logging disabled 
 633     static bool        ms_bAutoCreate
;  // create new log targets on demand? 
 634     static bool        ms_bVerbose
;     // false => ignore LogInfo messages 
 636     static wxLogLevel  ms_logLevel
;     // limit logging to levels <= ms_logLevel 
 638     static size_t      ms_suspendCount
; // if positive, logs are not flushed 
 640     // format string for strftime(), if empty, time stamping log messages is 
 642     static wxString    ms_timestamp
; 
 644 #if WXWIN_COMPATIBILITY_2_8 
 645     static wxTraceMask ms_ulTraceMask
;   // controls wxLogTrace behaviour 
 646 #endif // WXWIN_COMPATIBILITY_2_8 
 649 // ---------------------------------------------------------------------------- 
 650 // "trivial" derivations of wxLog 
 651 // ---------------------------------------------------------------------------- 
 653 // log everything except for the debug/trace messages (which are passed to 
 654 // wxMessageOutputDebug) to a buffer 
 655 class WXDLLIMPEXP_BASE wxLogBuffer 
: public wxLog
 
 660     // get the string contents with all messages logged 
 661     const wxString
& GetBuffer() const { return m_str
; } 
 663     // show the buffer contents to the user in the best possible way (this uses 
 664     // wxMessageOutputMessageBox) and clear it 
 665     virtual void Flush(); 
 668     virtual void DoLogTextAtLevel(wxLogLevel level
, const wxString
& msg
); 
 673     wxDECLARE_NO_COPY_CLASS(wxLogBuffer
); 
 677 // log everything to a "FILE *", stderr by default 
 678 class WXDLLIMPEXP_BASE wxLogStderr 
: public wxLog
 
 681     // redirect log output to a FILE 
 682     wxLogStderr(FILE *fp 
= NULL
); 
 685     // implement sink function 
 686     virtual void DoLogText(const wxString
& msg
); 
 690     wxDECLARE_NO_COPY_CLASS(wxLogStderr
); 
 693 #if wxUSE_STD_IOSTREAM 
 695 // log everything to an "ostream", cerr by default 
 696 class WXDLLIMPEXP_BASE wxLogStream 
: public wxLog
 
 699     // redirect log output to an ostream 
 700     wxLogStream(wxSTD ostream 
*ostr 
= (wxSTD ostream 
*) NULL
); 
 703     // implement sink function 
 704     virtual void DoLogText(const wxString
& msg
); 
 706     // using ptr here to avoid including <iostream.h> from this file 
 707     wxSTD ostream 
*m_ostr
; 
 710 #endif // wxUSE_STD_IOSTREAM 
 712 // ---------------------------------------------------------------------------- 
 713 // /dev/null log target: suppress logging until this object goes out of scope 
 714 // ---------------------------------------------------------------------------- 
 722         // wxFile.Open() normally complains if file can't be opened, we don't 
 726         if ( !file.Open("bar") ) 
 727             ... process error ourselves ... 
 729         // ~wxLogNull called, old log sink restored 
 732 class WXDLLIMPEXP_BASE wxLogNull
 
 735     wxLogNull() : m_flagOld(wxLog::EnableLogging(false)) { } 
 736     ~wxLogNull() { (void)wxLog::EnableLogging(m_flagOld
); } 
 739     bool m_flagOld
; // the previous value of the wxLog::ms_doLog 
 742 // ---------------------------------------------------------------------------- 
 743 // chaining log target: installs itself as a log target and passes all 
 744 // messages to the real log target given to it in the ctor but also forwards 
 745 // them to the previously active one 
 747 // note that you don't have to call SetActiveTarget() with this class, it 
 748 // does it itself in its ctor 
 749 // ---------------------------------------------------------------------------- 
 751 class WXDLLIMPEXP_BASE wxLogChain 
: public wxLog
 
 754     wxLogChain(wxLog 
*logger
); 
 755     virtual ~wxLogChain(); 
 757     // change the new log target 
 758     void SetLog(wxLog 
*logger
); 
 760     // this can be used to temporarily disable (and then reenable) passing 
 761     // messages to the old logger (by default we do pass them) 
 762     void PassMessages(bool bDoPass
) { m_bPassMessages 
= bDoPass
; } 
 764     // are we passing the messages to the previous log target? 
 765     bool IsPassingMessages() const { return m_bPassMessages
; } 
 767     // return the previous log target (may be NULL) 
 768     wxLog 
*GetOldLog() const { return m_logOld
; } 
 770     // override base class version to flush the old logger as well 
 771     virtual void Flush(); 
 773     // call to avoid destroying the old log target 
 774     void DetachOldLog() { m_logOld 
= NULL
; } 
 777     // pass the record to the old logger if needed 
 778     virtual void DoLogRecord(wxLogLevel level
, 
 780                              const wxLogRecordInfo
& info
); 
 783     // the current log target 
 786     // the previous log target 
 789     // do we pass the messages to the old logger? 
 790     bool m_bPassMessages
; 
 792     wxDECLARE_NO_COPY_CLASS(wxLogChain
); 
 795 // a chain log target which uses itself as the new logger 
 797 #define wxLogPassThrough wxLogInterposer 
 799 class WXDLLIMPEXP_BASE wxLogInterposer 
: public wxLogChain
 
 805     wxDECLARE_NO_COPY_CLASS(wxLogInterposer
); 
 808 // a temporary interposer which doesn't destroy the old log target 
 809 // (calls DetachOldLog) 
 811 class WXDLLIMPEXP_BASE wxLogInterposerTemp 
: public wxLogChain
 
 814     wxLogInterposerTemp(); 
 817     wxDECLARE_NO_COPY_CLASS(wxLogInterposerTemp
); 
 821     // include GUI log targets: 
 822     #include "wx/generic/logg.h" 
 825 // ---------------------------------------------------------------------------- 
 827 // ---------------------------------------------------------------------------- 
 829 // wxLogger is a helper class used by wxLogXXX() functions implementation, 
 830 // don't use it directly as it's experimental and subject to change (OTOH it 
 831 // might become public in the future if it's deemed to be useful enough) 
 833 // contains information about the context from which a log message originates 
 834 // and provides Log() vararg method which forwards to wxLog::OnLog() and passes 
 835 // this context to it 
 839     // ctor takes the basic information about the log record 
 840     wxLogger(wxLogLevel level
, 
 841              const char *filename
, 
 844              const char *component
) 
 846           m_info(filename
, line
, func
, component
) 
 850     // store extra data in our log record and return this object itself (so 
 851     // that further calls to its functions could be chained) 
 852     template <typename T
> 
 853     wxLogger
& Store(const wxString
& key
, T val
) 
 855         m_info
.StoreValue(key
, val
); 
 859     // hack for "overloaded" wxLogXXX() functions: calling this method 
 860     // indicates that we may have an extra first argument preceding the format 
 861     // string and that if we do have it, we should store it in m_info using the 
 862     // given key (while by default 0 value will be used) 
 863     wxLogger
& MaybeStore(const wxString
& key
, wxUIntPtr value 
= 0) 
 865         wxASSERT_MSG( m_optKey
.empty(), "can only have one optional value" ); 
 868         m_info
.StoreValue(key
, value
); 
 873     // non-vararg function used by wxVLogXXX(): 
 875     // log the message at the level specified in the ctor if this log message 
 877     void LogV(const wxString
& format
, va_list argptr
) 
 879         // remember that fatal errors can't be disabled 
 880         if ( m_level 
== wxLOG_FatalError 
|| 
 881                 wxLog::IsLevelEnabled(m_level
, m_info
.component
) ) 
 882             DoCallOnLog(format
, argptr
); 
 885     // overloads used by functions with optional leading arguments (whose 
 886     // values are stored in the key passed to MaybeStore()) 
 887     void LogV(long num
, const wxString
& format
, va_list argptr
) 
 889         Store(m_optKey
, num
); 
 891         LogV(format
, argptr
); 
 894     void LogV(void *ptr
, const wxString
& format
, va_list argptr
) 
 896         Store(m_optKey
, wxPtrToUInt(ptr
)); 
 898         LogV(format
, argptr
); 
 901     void LogVTrace(const wxString
& mask
, const wxString
& format
, va_list argptr
) 
 903         if ( !wxLog::IsAllowedTraceMask(mask
) ) 
 906         Store(wxLOG_KEY_TRACE_MASK
, mask
); 
 908         LogV(format
, argptr
); 
 912     // vararg functions used by wxLogXXX(): 
 914     // will log the message at the level specified in the ctor 
 916     // notice that this function supposes that the caller already checked that 
 917     // the level was enabled and does no checks itself 
 918     WX_DEFINE_VARARG_FUNC_VOID
 
 921         1, (const wxFormatString
&), 
 925     // same as Log() but with an extra numeric or pointer parameters: this is 
 926     // used to pass an optional value by storing it in m_info under the name 
 927     // passed to MaybeStore() and is required to support "overloaded" versions 
 928     // of wxLogStatus() and wxLogSysError() 
 929     WX_DEFINE_VARARG_FUNC_VOID
 
 932         2, (long, const wxFormatString
&), 
 933         DoLogWithNum
, DoLogWithNumUtf8
 
 936     // unfortunately we can't use "void *" here as we get overload ambiguities 
 937     // with Log(wxFormatString, ...) when the first argument is a "char *" or 
 938     // "wchar_t *" then -- so we only allow passing wxObject here, which is 
 939     // ugly but fine in practice as this overload is only used by wxLogStatus() 
 940     // whose first argument is a wxFrame 
 941     WX_DEFINE_VARARG_FUNC_VOID
 
 944         2, (wxObject 
*, const wxFormatString
&), 
 945         DoLogWithPtr
, DoLogWithPtrUtf8
 
 948     // log the message at the level specified as its first argument 
 950     // as the macros don't have access to the level argument in this case, this 
 951     // function does check that the level is enabled itself 
 952     WX_DEFINE_VARARG_FUNC_VOID
 
 955         2, (wxLogLevel
, const wxFormatString
&), 
 956         DoLogAtLevel
, DoLogAtLevelUtf8
 
 959     // special versions for wxLogTrace() which is passed either string or 
 960     // integer mask as first argument determining whether the message should be 
 962     WX_DEFINE_VARARG_FUNC_VOID
 
 965         2, (const wxString
&, const wxFormatString
&), 
 966         DoLogTrace
, DoLogTraceUtf8
 
 969 #if WXWIN_COMPATIBILITY_2_8 
 970     WX_DEFINE_VARARG_FUNC_VOID
 
 973         2, (wxTraceMask
, const wxFormatString
&), 
 974         DoLogTraceMask
, DoLogTraceMaskUtf8
 
 976 #endif // WXWIN_COMPATIBILITY_2_8 
 979     // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 
 980     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 981                                1, (const wxString
&), 
 982                                (wxFormatString(f1
))) 
 983     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 984                                1, (const wxCStrData
&), 
 985                                (wxFormatString(f1
))) 
 986     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 988                                (wxFormatString(f1
))) 
 989     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 991                                (wxFormatString(f1
))) 
 993     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 994                                2, (long, const wxString
&), 
 995                                (f1
, wxFormatString(f2
))) 
 996     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
 997                                2, (long, const wxCStrData
&), 
 998                                (f1
, wxFormatString(f2
))) 
 999     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1000                                2, (long, const char *), 
1001                                (f1
, wxFormatString(f2
))) 
1002     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1003                                2, (long, const wchar_t *), 
1004                                (f1
, wxFormatString(f2
))) 
1006     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1007                                2, (wxObject 
*, const wxString
&), 
1008                                (f1
, wxFormatString(f2
))) 
1009     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1010                                2, (wxObject 
*, const wxCStrData
&), 
1011                                (f1
, wxFormatString(f2
))) 
1012     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1013                                2, (wxObject 
*, const char *), 
1014                                (f1
, wxFormatString(f2
))) 
1015     WX_VARARG_WATCOM_WORKAROUND(void, Log
, 
1016                                2, (wxObject 
*, const wchar_t *), 
1017                                (f1
, wxFormatString(f2
))) 
1019     WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel
, 
1020                                2, (wxLogLevel
, const wxString
&), 
1021                                (f1
, wxFormatString(f2
))) 
1022     WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel
, 
1023                                2, (wxLogLevel
, const wxCStrData
&), 
1024                                (f1
, wxFormatString(f2
))) 
1025     WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel
, 
1026                                2, (wxLogLevel
, const char *), 
1027                                (f1
, wxFormatString(f2
))) 
1028     WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel
, 
1029                                2, (wxLogLevel
, const wchar_t *), 
1030                                (f1
, wxFormatString(f2
))) 
1032     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1033                                2, (const wxString
&, const wxString
&), 
1034                                (f1
, wxFormatString(f2
))) 
1035     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1036                                2, (const wxString
&, const wxCStrData
&), 
1037                                (f1
, wxFormatString(f2
))) 
1038     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1039                                2, (const wxString
&, const char *), 
1040                                (f1
, wxFormatString(f2
))) 
1041     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1042                                2, (const wxString
&, const wchar_t *), 
1043                                (f1
, wxFormatString(f2
))) 
1045 #if WXWIN_COMPATIBILITY_2_8 
1046     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1047                                2, (wxTraceMask
, wxTraceMask
), 
1048                                (f1
, wxFormatString(f2
))) 
1049     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1050                                2, (wxTraceMask
, const wxCStrData
&), 
1051                                (f1
, wxFormatString(f2
))) 
1052     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1053                                2, (wxTraceMask
, const char *), 
1054                                (f1
, wxFormatString(f2
))) 
1055     WX_VARARG_WATCOM_WORKAROUND(void, LogTrace
, 
1056                                2, (wxTraceMask
, const wchar_t *), 
1057                                (f1
, wxFormatString(f2
))) 
1058 #endif // WXWIN_COMPATIBILITY_2_8 
1059 #endif // __WATCOMC__ 
1062 #if !wxUSE_UTF8_LOCALE_ONLY 
1063     void DoLog(const wxChar 
*format
, ...) 
1066         va_start(argptr
, format
); 
1067         DoCallOnLog(format
, argptr
); 
1071     void DoLogWithNum(long num
, const wxChar 
*format
, ...) 
1073         Store(m_optKey
, num
); 
1076         va_start(argptr
, format
); 
1077         DoCallOnLog(format
, argptr
); 
1081     void DoLogWithPtr(void *ptr
, const wxChar 
*format
, ...) 
1083         Store(m_optKey
, wxPtrToUInt(ptr
)); 
1086         va_start(argptr
, format
); 
1087         DoCallOnLog(format
, argptr
); 
1091     void DoLogAtLevel(wxLogLevel level
, const wxChar 
*format
, ...) 
1093         if ( !wxLog::IsLevelEnabled(level
, m_info
.component
) ) 
1097         va_start(argptr
, format
); 
1098         DoCallOnLog(level
, format
, argptr
); 
1102     void DoLogTrace(const wxString
& mask
, const wxChar 
*format
, ...) 
1104         if ( !wxLog::IsAllowedTraceMask(mask
) ) 
1107         Store(wxLOG_KEY_TRACE_MASK
, mask
); 
1110         va_start(argptr
, format
); 
1111         DoCallOnLog(format
, argptr
); 
1115 #if WXWIN_COMPATIBILITY_2_8 
1116     void DoLogTraceMask(wxTraceMask mask
, const wxChar 
*format
, ...) 
1118         if ( (wxLog::GetTraceMask() & mask
) != mask 
) 
1121         Store(wxLOG_KEY_TRACE_MASK
, mask
); 
1124         va_start(argptr
, format
); 
1125         DoCallOnLog(format
, argptr
); 
1128 #endif // WXWIN_COMPATIBILITY_2_8 
1129 #endif // !wxUSE_UTF8_LOCALE_ONLY 
1131 #if wxUSE_UNICODE_UTF8 
1132     void DoLogUtf8(const char *format
, ...) 
1135         va_start(argptr
, format
); 
1136         DoCallOnLog(format
, argptr
); 
1140     void DoLogWithNumUtf8(long num
, const char *format
, ...) 
1142         Store(m_optKey
, num
); 
1145         va_start(argptr
, format
); 
1146         DoCallOnLog(format
, argptr
); 
1150     void DoLogWithPtrUtf8(void *ptr
, const char *format
, ...) 
1152         Store(m_optKey
, wxPtrToUInt(ptr
)); 
1155         va_start(argptr
, format
); 
1156         DoCallOnLog(format
, argptr
); 
1160     void DoLogAtLevelUtf8(wxLogLevel level
, const char *format
, ...) 
1162         if ( !wxLog::IsLevelEnabled(level
, m_info
.component
) ) 
1166         va_start(argptr
, format
); 
1167         DoCallOnLog(level
, format
, argptr
); 
1171     void DoLogTraceUtf8(const wxString
& mask
, const char *format
, ...) 
1173         if ( !wxLog::IsAllowedTraceMask(mask
) ) 
1176         Store(wxLOG_KEY_TRACE_MASK
, mask
); 
1179         va_start(argptr
, format
); 
1180         DoCallOnLog(format
, argptr
); 
1184 #if WXWIN_COMPATIBILITY_2_8 
1185     void DoLogTraceMaskUtf8(wxTraceMask mask
, const char *format
, ...) 
1187         if ( (wxLog::GetTraceMask() & mask
) != mask 
) 
1190         Store(wxLOG_KEY_TRACE_MASK
, mask
); 
1193         va_start(argptr
, format
); 
1194         DoCallOnLog(format
, argptr
); 
1197 #endif // WXWIN_COMPATIBILITY_2_8 
1198 #endif // wxUSE_UNICODE_UTF8 
1200     void DoCallOnLog(wxLogLevel level
, const wxString
& format
, va_list argptr
) 
1202         wxLog::OnLog(level
, wxString::FormatV(format
, argptr
), m_info
); 
1205     void DoCallOnLog(const wxString
& format
, va_list argptr
) 
1207         DoCallOnLog(m_level
, format
, argptr
); 
1211     const wxLogLevel m_level
; 
1212     wxLogRecordInfo m_info
; 
1216     wxDECLARE_NO_COPY_CLASS(wxLogger
); 
1219 // ============================================================================ 
1221 // ============================================================================ 
1223 // ---------------------------------------------------------------------------- 
1224 // get error code/error message from system in a portable way 
1225 // ---------------------------------------------------------------------------- 
1227 // return the last system error code 
1228 WXDLLIMPEXP_BASE 
unsigned long wxSysErrorCode(); 
1230 // return the error message for given (or last if 0) error code 
1231 WXDLLIMPEXP_BASE 
const wxChar
* wxSysErrorMsg(unsigned long nErrCode 
= 0); 
1233 // ---------------------------------------------------------------------------- 
1234 // define wxLog<level>() functions which can be used by application instead of 
1235 // stdio, iostream &c for log messages for easy redirection 
1236 // ---------------------------------------------------------------------------- 
1239     The code below is unreadable because it (unfortunately unavoidably) 
1240     contains a lot of macro magic but all it does is to define wxLogXXX() such 
1241     that you can call them as vararg functions to log a message at the 
1242     corresponding level. 
1244     More precisely, it defines: 
1246         - wxLog{FatalError,Error,Warning,Message,Verbose,Debug}() functions 
1247         taking the format string and additional vararg arguments if needed. 
1248         - wxLogGeneric(wxLogLevel level, const wxString& format, ...) which 
1249         takes the log level explicitly. 
1250         - wxLogSysError(const wxString& format, ...) and wxLogSysError(long 
1251         err, const wxString& format, ...) which log a wxLOG_Error severity 
1252         message with the error message corresponding to the system error code 
1253         err or the last error. 
1254         - wxLogStatus(const wxString& format, ...) which logs the message into 
1255         the status bar of the main application window and its overload 
1256         wxLogStatus(wxFrame *frame, const wxString& format, ...) which logs it 
1257         into the status bar of the specified frame. 
1258         - wxLogTrace(Mask mask, const wxString& format, ...) which only logs 
1259         the message is the specified mask is enabled. This comes in two kinds: 
1260         Mask can be a wxString or a long. Both are deprecated. 
1262     In addition, wxVLogXXX() versions of all the functions above are also 
1263     defined. They take a va_list argument instead of "...". 
1266 // creates wxLogger object for the current location 
1267 #define wxMAKE_LOGGER(level) \ 
1268     wxLogger(wxLOG_##level, __FILE__, __LINE__, __WXFUNCTION__, wxLOG_COMPONENT) 
1270 // this macro generates the expression which logs whatever follows it in 
1271 // parentheses at the level specified as argument 
1272 #define wxDO_LOG(level) wxMAKE_LOGGER(level).Log 
1274 // this is the non-vararg equivalent 
1275 #define wxDO_LOGV(level, format, argptr) \ 
1276     wxMAKE_LOGGER(level).LogV(format, argptr) 
1278 // this macro declares wxLog<level>() macro which logs whatever follows it if 
1279 // logging at specified level is enabled (notice that if it is false, the 
1280 // following arguments are not even evaluated which is good as it avoids 
1281 // unnecessary overhead) 
1283 // Note: the strange if/else construct is needed to make the following code 
1286 //              wxLogError("!!!"); 
1290 //       work as expected, without it the second "else" would match the "if" 
1291 //       inside wxLogError(). Unfortunately code like 
1294 //              wxLogError("!!!"); 
1296 //       now provokes "suggest explicit braces to avoid ambiguous 'else'" 
1297 //       warnings from g++ 4.3 and later with -Wparentheses on but they can be 
1298 //       easily fixed by adding curly braces around wxLogError() and at least 
1299 //       the code still does do the right thing. 
1300 #define wxDO_LOG_IF_ENABLED(level)                                            \ 
1301     if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) )             \ 
1306 // wxLogFatalError() is special as it can't be disabled 
1307 #define wxLogFatalError wxDO_LOG(FatalError) 
1308 #define wxVLogFatalError(format, argptr) wxDO_LOGV(FatalError, format, argptr) 
1310 #define wxLogError wxDO_LOG_IF_ENABLED(Error) 
1311 #define wxVLogError(format, argptr) wxDO_LOGV(Error, format, argptr) 
1313 #define wxLogWarning wxDO_LOG_IF_ENABLED(Warning) 
1314 #define wxVLogWarning(format, argptr) wxDO_LOGV(Warning, format, argptr) 
1316 #define wxLogMessage wxDO_LOG_IF_ENABLED(Message) 
1317 #define wxVLogMessage(format, argptr) wxDO_LOGV(Message, format, argptr) 
1319 // this one is special as it only logs if we're in verbose mode 
1320 #define wxLogVerbose                                                          \ 
1321     if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) &&              \ 
1322             wxLog::GetVerbose()) )                                            \ 
1326 #define wxVLogVerbose(format, argptr)                                         \ 
1327     if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) &&              \ 
1328             wxLog::GetVerbose()) )                                            \ 
1331         wxDO_LOGV(Info, format, argptr) 
1333 // deprecated synonyms for wxLogVerbose() and wxVLogVerbose() 
1334 #define wxLogInfo wxLogVerbose 
1335 #define wxVLogInfo wxVLogVerbose 
1338 // another special case: the level is passed as first argument of the function 
1339 // and so is not available to the macro 
1341 // notice that because of this, arguments of wxLogGeneric() are currently 
1342 // always evaluated, unlike for the other log functions 
1343 #define wxLogGeneric wxMAKE_LOGGER(Max).LogAtLevel 
1344 #define wxVLogGeneric(level, format, argptr) \ 
1345     if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) )             \ 
1348         wxDO_LOGV(level, format, argptr) 
1351 // wxLogSysError() needs to stash the error code value in the log record info 
1352 // so it needs special handling too; additional complications arise because the 
1353 // error code may or not be present as the first argument 
1355 // notice that we unfortunately can't avoid the call to wxSysErrorCode() even 
1356 // though it may be unneeded if an explicit error code is passed to us because 
1357 // the message might not be logged immediately (e.g. it could be queued for 
1358 // logging from the main thread later) and so we can't to wait until it is 
1359 // logged to determine whether we have last error or not as it will be too late 
1360 // and it will have changed already by then (in fact it even changes when 
1361 // wxString::Format() is called because of vsnprintf() inside it so it can 
1362 // change even much sooner) 
1363 #define wxLOG_KEY_SYS_ERROR_CODE "wx.sys_error" 
1365 #define wxLogSysError                                                         \ 
1366     if ( !wxLog::IsLevelEnabled(wxLOG_Error, wxLOG_COMPONENT) )               \ 
1369         wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE,             \ 
1370                                         wxSysErrorCode()).Log 
1372 // unfortunately we can't have overloaded macros so we can't define versions 
1373 // both with and without error code argument and have to rely on LogV() 
1374 // overloads in wxLogger to select between them 
1375 #define wxVLogSysError \ 
1376     wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \ 
1377                                     wxSysErrorCode()).LogV 
1380     // wxLogStatus() is similar to wxLogSysError() as it allows to optionally 
1381     // specify the frame to which the message should go 
1382     #define wxLOG_KEY_FRAME "wx.frame" 
1384     #define wxLogStatus                                                       \ 
1385         if ( !wxLog::IsLevelEnabled(wxLOG_Status, wxLOG_COMPONENT) )          \ 
1388             wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).Log 
1390     #define wxVLogStatus(format, argptr) \ 
1391         wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).LogV 
1397 #undef wxUSE_LOG_DEBUG 
1398 #define wxUSE_LOG_DEBUG 0 
1400 #undef wxUSE_LOG_TRACE 
1401 #define wxUSE_LOG_TRACE 0 
1403 #if defined(__WATCOMC__) || defined(__MINGW32__) 
1404     // Mingw has similar problem with wxLogSysError: 
1405     #define WX_WATCOM_OR_MINGW_ONLY_CODE( x )  x 
1407     #define WX_WATCOM_OR_MINGW_ONLY_CODE( x ) 
1410 // define macros for defining log functions which do nothing at all 
1412 // WX_WATCOM_ONLY_CODE is needed to work around 
1413 // http://bugzilla.openwatcom.org/show_bug.cgi?id=351 
1414 #define wxDEFINE_EMPTY_LOG_FUNCTION(level)                                  \ 
1415     WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxFormatString&))     \ 
1416     WX_WATCOM_ONLY_CODE(                                                    \ 
1417         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const char*))           \ 
1418         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wchar_t*))        \ 
1419         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxCStrData&))     \ 
1421     inline void wxVLog##level(const wxFormatString& WXUNUSED(format),       \ 
1422                               va_list WXUNUSED(argptr)) { }                 \ 
1424 #define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass)                       \ 
1425     WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxFormatString&)) \ 
1426     WX_WATCOM_OR_MINGW_ONLY_CODE(                                           \ 
1427         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const char*)) \ 
1428         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wchar_t*)) \ 
1429         WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxCStrData&)) \ 
1431     inline void wxVLog##level(argclass WXUNUSED(arg),                       \ 
1432                               const wxFormatString& WXUNUSED(format),       \ 
1433                               va_list WXUNUSED(argptr)) {} 
1435 wxDEFINE_EMPTY_LOG_FUNCTION(FatalError
); 
1436 wxDEFINE_EMPTY_LOG_FUNCTION(Error
); 
1437 wxDEFINE_EMPTY_LOG_FUNCTION(SysError
); 
1438 wxDEFINE_EMPTY_LOG_FUNCTION2(SysError
, long); 
1439 wxDEFINE_EMPTY_LOG_FUNCTION(Warning
); 
1440 wxDEFINE_EMPTY_LOG_FUNCTION(Message
); 
1441 wxDEFINE_EMPTY_LOG_FUNCTION(Info
); 
1442 wxDEFINE_EMPTY_LOG_FUNCTION(Verbose
); 
1444 wxDEFINE_EMPTY_LOG_FUNCTION2(Generic
, wxLogLevel
); 
1447     wxDEFINE_EMPTY_LOG_FUNCTION(Status
); 
1448     wxDEFINE_EMPTY_LOG_FUNCTION2(Status
, wxFrame 
*); 
1451 // Empty Class to fake wxLogNull 
1452 class WXDLLIMPEXP_BASE wxLogNull
 
1458 // Dummy macros to replace some functions. 
1459 #define wxSysErrorCode() (unsigned long)0 
1460 #define wxSysErrorMsg( X ) (const wxChar*)NULL 
1462 // Fake symbolic trace masks... for those that are used frequently 
1463 #define wxTRACE_OleCalls wxEmptyString // OLE interface calls 
1465 #endif // wxUSE_LOG/!wxUSE_LOG 
1468 // debug functions can be completely disabled in optimized builds 
1470 // if these log functions are disabled, we prefer to define them as (empty) 
1471 // variadic macros as this completely removes them and their argument 
1472 // evaluation from the object code but if this is not supported by compiler we 
1473 // use empty inline functions instead (defining them as nothing would result in 
1474 // compiler warnings) 
1476 // note that making wxVLogDebug/Trace() themselves (empty inline) functions is 
1477 // a bad idea as some compilers are stupid enough to not inline even empty 
1478 // functions if their parameters are complicated enough, but by defining them 
1479 // as an empty inline function we ensure that even dumbest compilers optimise 
1482     // but Borland gives "W8019: Code has no effect" for wxLogNop() so we need 
1483     // to define it differently for it to avoid these warnings (same problem as 
1484     // with wxUnusedVar()) 
1485     #define wxLogNop() { } 
1487     inline void wxLogNop() { } 
1491     #define wxLogDebug wxDO_LOG_IF_ENABLED(Debug) 
1492     #define wxVLogDebug(format, argptr) wxDO_LOGV(Debug, format, argptr) 
1493 #else // !wxUSE_LOG_DEBUG 
1494     #define wxVLogDebug(fmt, valist) wxLogNop() 
1496     #ifdef HAVE_VARIADIC_MACROS 
1497         #define wxLogDebug(fmt, ...) wxLogNop() 
1498     #else // !HAVE_VARIADIC_MACROS 
1499         WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug
, 1, (const wxFormatString
&)) 
1501 #endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG 
1504     #define wxLogTrace                                                        \ 
1505         if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) )           \ 
1508             wxMAKE_LOGGER(Trace).LogTrace 
1509     #define wxVLogTrace                                                       \ 
1510         if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) )           \ 
1513             wxMAKE_LOGGER(Trace).LogVTrace 
1514 #else  // !wxUSE_LOG_TRACE 
1515     #define wxVLogTrace(mask, fmt, valist) wxLogNop() 
1517     #ifdef HAVE_VARIADIC_MACROS 
1518         #define wxLogTrace(mask, fmt, ...) wxLogNop() 
1519     #else // !HAVE_VARIADIC_MACROS 
1520         #if WXWIN_COMPATIBILITY_2_8 
1521         WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace
, 2, (wxTraceMask
, const wxFormatString
&)) 
1523         WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace
, 2, (const wxString
&, const wxFormatString
&)) 
1525         // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 
1526         WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace
, 2, (const char*, const char*)) 
1527         WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace
, 2, (const wchar_t*, const wchar_t*)) 
1529     #endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS 
1530 #endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE 
1532 // wxLogFatalError helper: show the (fatal) error to the user in a safe way, 
1533 // i.e. without using wxMessageBox() for example because it could crash 
1534 void WXDLLIMPEXP_BASE
 
1535 wxSafeShowMessage(const wxString
& title
, const wxString
& text
); 
1537 // ---------------------------------------------------------------------------- 
1538 // debug only logging functions: use them with API name and error code 
1539 // ---------------------------------------------------------------------------- 
1542     // make life easier for people using VC++ IDE: clicking on the message 
1543     // will take us immediately to the place of the failed API 
1545     #define wxLogApiError(api, rc)                                            \ 
1546         wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."),       \ 
1547                    __FILE__, __LINE__, api,                                   \ 
1548                    (long)rc, wxSysErrorMsg(rc)) 
1550     #define wxLogApiError(api, rc)                                            \ 
1551         wxLogDebug(wxT("In file %s at line %d: '%s' failed with ")            \ 
1552                    wxT("error 0x%08lx (%s)."),                                \ 
1553                    __FILE__, __LINE__, api,                                   \ 
1554                    (long)rc, wxSysErrorMsg(rc)) 
1555 #endif // VC++/!VC++ 
1557     #define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode()) 
1559 #else // !wxUSE_LOG_DEBUG 
1560     #define wxLogApiError(api, err) wxLogNop() 
1561     #define wxLogLastError(api) wxLogNop() 
1562 #endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG 
1564 // wxCocoa has additiional trace masks 
1565 #if defined(__WXCOCOA__) 
1566 #include "wx/cocoa/log.h" 
1569 #ifdef WX_WATCOM_ONLY_CODE 
1570     #undef WX_WATCOM_ONLY_CODE 
1573 // macro which disables debug logging in release builds: this is done by 
1574 // default by wxIMPLEMENT_APP() so usually it doesn't need to be used explicitly 
1575 #if defined(NDEBUG) && wxUSE_LOG_DEBUG 
1576     #define wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD() \ 
1577         wxLog::SetLogLevel(wxLOG_Info) 
1579     #define wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD() 
1580 #endif // NDEBUG/!NDEBUG 
1582 #endif  // _WX_LOG_H_