#include "wx/defs.h"
// ----------------------------------------------------------------------------
-// common constants for use in wxUSE_LOG/!wxUSE_LOG
+// types
// ----------------------------------------------------------------------------
-// the trace masks have been superceded by symbolic trace constants, they're
-// for compatibility only andwill be removed soon - do NOT use them
+// NB: this is needed even if wxUSE_LOG == 0
+typedef unsigned long wxLogLevel;
-// meaning of different bits of the trace mask (which allows selectively
-// enable/disable some trace messages)
-#define wxTraceMemAlloc 0x0001 // trace memory allocation (new/delete)
-#define wxTraceMessages 0x0002 // trace window messages/X callbacks
-#define wxTraceResAlloc 0x0004 // trace GDI resource allocation
-#define wxTraceRefCount 0x0008 // trace various ref counting operations
+// the trace masks have been superseded by symbolic trace constants, they're
+// for compatibility only and will be removed soon - do NOT use them
+#if WXWIN_COMPATIBILITY_2_8
+ #define wxTraceMemAlloc 0x0001 // trace memory allocation (new/delete)
+ #define wxTraceMessages 0x0002 // trace window messages/X callbacks
+ #define wxTraceResAlloc 0x0004 // trace GDI resource allocation
+ #define wxTraceRefCount 0x0008 // trace various ref counting operations
-#ifdef __WXMSW__
- #define wxTraceOleCalls 0x0100 // OLE interface calls
-#endif
+ #ifdef __WXMSW__
+ #define wxTraceOleCalls 0x0100 // OLE interface calls
+ #endif
-// ----------------------------------------------------------------------------
-// types
-// ----------------------------------------------------------------------------
-
-// NB: these types are needed even if wxUSE_LOG == 0
-typedef unsigned long wxTraceMask;
-typedef unsigned long wxLogLevel;
+ typedef unsigned long wxTraceMask;
+#endif // WXWIN_COMPATIBILITY_2_8
// ----------------------------------------------------------------------------
// headers
#include "wx/arrstr.h"
+#ifndef __WXPALMOS5__
#ifndef __WXWINCE__
#include <time.h> // for time_t
#endif
+#endif // ! __WXPALMOS5__
#include "wx/dynarray.h"
+// wxUSE_LOG_DEBUG enables the debug log messages
#ifndef wxUSE_LOG_DEBUG
-# ifdef __WXDEBUG__
-# define wxUSE_LOG_DEBUG 1
-# else // !__WXDEBUG__
-# define wxUSE_LOG_DEBUG 0
-# endif
+ #if wxDEBUG_LEVEL
+ #define wxUSE_LOG_DEBUG 1
+ #else // !wxDEBUG_LEVEL
+ #define wxUSE_LOG_DEBUG 0
+ #endif
#endif
+// wxUSE_LOG_TRACE enables the trace messages, they are disabled by default
+#ifndef wxUSE_LOG_TRACE
+ #if wxDEBUG_LEVEL
+ #define wxUSE_LOG_TRACE 1
+ #else // !wxDEBUG_LEVEL
+ #define wxUSE_LOG_TRACE 0
+ #endif
+#endif // wxUSE_LOG_TRACE
+
// ----------------------------------------------------------------------------
// forward declarations
// ----------------------------------------------------------------------------
#if wxUSE_GUI
- class WXDLLIMPEXP_CORE wxTextCtrl;
- class WXDLLIMPEXP_CORE wxLogFrame;
- class WXDLLIMPEXP_CORE wxFrame;
- class WXDLLIMPEXP_CORE wxWindow;
+ class WXDLLIMPEXP_FWD_CORE wxFrame;
#endif // wxUSE_GUI
// ----------------------------------------------------------------------------
// gets duplicate counting status
static bool GetRepetitionCounting() { return ms_bRepetCounting; }
- // trace mask (see wxTraceXXX constants for details)
- static void SetTraceMask(wxTraceMask ulMask) { ms_ulTraceMask = ulMask; }
-
// add string trace mask
- static void AddTraceMask(const wxString& str)
- { ms_aTraceMasks.push_back(str); }
+ static void AddTraceMask(const wxString& str);
// add string trace mask
static void RemoveTraceMask(const wxString& str);
// remove all string trace masks
static void ClearTraceMasks();
- // get string trace masks
- static const wxArrayString &GetTraceMasks() { return ms_aTraceMasks; }
+ // get string trace masks: note that this is MT-unsafe if other threads can
+ // call AddTraceMask() concurrently
+ static const wxArrayString& GetTraceMasks() { return ms_aTraceMasks; }
+
+ // sets the time stamp string format: this is used as strftime() format
+ // string for the log targets which add time stamps to the messages; set
+ // it to empty string to disable time stamping completely.
+ static void SetTimestamp(const wxString& ts) { ms_timestamp = ts; }
- // sets the timestamp string: this is used as strftime() format string
- // for the log targets which add time stamps to the messages - set it
- // to NULL to disable time stamping completely.
- static void SetTimestamp(const wxChar *ts) { ms_timestamp = ts; }
+ // disable time stamping of log messages
+ static void DisableTimestamp() { SetTimestamp(wxEmptyString); }
// accessors
// gets the verbose status
static bool GetVerbose() { return ms_bVerbose; }
- // get trace mask
- static wxTraceMask GetTraceMask() { return ms_ulTraceMask; }
-
// is this trace mask in the list?
static bool IsAllowedTraceMask(const wxString& mask);
static wxLogLevel GetLogLevel() { return ms_logLevel; }
// get the current timestamp format string (may be NULL)
- static const wxChar *GetTimestamp() { return ms_timestamp; }
+ static const wxString& GetTimestamp() { return ms_timestamp; }
// helpers
// change it otherwise)
static void TimeStamp(wxString *str);
+ // this method should only be called from derived classes DoLog()
+ // implementations and shouldn't be called directly, use logging functions
+ // instead
+ void Log(wxLogLevel level, const wxString& msg, time_t t)
+ {
+ DoLog(level, msg, t);
+ }
+
// make dtor virtual for all derived classes
virtual ~wxLog();
wxDEPRECATED( static wxChar *SetLogBuffer(wxChar *buf, size_t size = 0) );
#endif
+ // don't use integer masks any more, use string trace masks instead
+#if WXWIN_COMPATIBILITY_2_8
+ wxDEPRECATED_INLINE( static void SetTraceMask(wxTraceMask ulMask),
+ ms_ulTraceMask = ulMask; )
+ wxDEPRECATED_BUT_USED_INTERNALLY_INLINE( static wxTraceMask GetTraceMask(),
+ return ms_ulTraceMask; )
+#endif // WXWIN_COMPATIBILITY_2_8
+
protected:
- // the logging functions that can be overriden
+ // the logging functions that can be overridden
// default DoLog() prepends the time stamp and a prefix corresponding
// to the message to szString and then passes it to DoLogString()
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
#if WXWIN_COMPATIBILITY_2_8
// these shouldn't be used by new code
- virtual void DoLog(wxLogLevel WXUNUSED(level),
- const char *WXUNUSED(szString), time_t WXUNUSED(t)) {}
- virtual void DoLog(wxLogLevel WXUNUSED(level),
- const wchar_t *WXUNUSED(szString), time_t WXUNUSED(t)) {}
-#endif
+ wxDEPRECATED_BUT_USED_INTERNALLY(
+ virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
+ );
+
+ wxDEPRECATED_BUT_USED_INTERNALLY(
+ virtual void DoLog(wxLogLevel level, const wchar_t *wzString, time_t t)
+ );
+#endif // WXWIN_COMPATIBILITY_2_8
void LogString(const wxString& szString, time_t t)
{ DoLogString(szString, t); }
time_t WXUNUSED(t)) {}
virtual void DoLogString(const wchar_t *WXUNUSED(szString),
time_t WXUNUSED(t)) {}
+#endif // WXWIN_COMPATIBILITY_2_8
+
+ // this macro should be used in the derived classes to avoid warnings about
+ // hiding the other DoLog() overloads when overriding DoLog(wxString) --
+ // but don't use it with MSVC which doesn't give this warning but does give
+ // warning when a deprecated function is overridden
+#if WXWIN_COMPATIBILITY_2_8 && !defined(__VISUALC__)
+ #define wxSUPPRESS_DOLOG_HIDE_WARNING() \
+ virtual void DoLog(wxLogLevel, const char *, time_t) { } \
+ virtual void DoLog(wxLogLevel, const wchar_t *, time_t) { }
+
+ #define wxSUPPRESS_DOLOGSTRING_HIDE_WARNING() \
+ virtual void DoLogString(const char *, time_t) { } \
+ virtual void DoLogString(const wchar_t *, time_t) { }
+#else
+ #define wxSUPPRESS_DOLOG_HIDE_WARNING()
+ #define wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
#endif
- // log a line containing the number of times the previous message was
- // repeated
- // returns: the number
- static unsigned DoLogNumberOfRepeats();
+ // log a message indicating the number of times the previous message was
+ // repeated if ms_prevCounter > 0, does nothing otherwise; return the old
+ // value of ms_prevCounter
+ unsigned LogLastRepeatIfNeeded();
private:
+ // implement of LogLastRepeatIfNeeded(): it assumes that the
+ // caller had already locked ms_prevCS
+ unsigned LogLastRepeatIfNeededUnlocked();
+
// static variables
// ----------------
- // traditional behaviour or counting repetitions
+ // if true, don't log the same message multiple times, only log it once
+ // with the number of times it was repeated
static bool ms_bRepetCounting;
+
static wxString ms_prevString; // previous message that was logged
- // how many times the previous message was logged
- static unsigned ms_prevCounter;
+ static unsigned ms_prevCounter; // how many times it was repeated
static time_t ms_prevTimeStamp;// timestamp of the previous message
static wxLogLevel ms_prevLevel; // level of the previous message
// format string for strftime(), if NULL, time stamping log messages is
// disabled
- static const wxChar *ms_timestamp;
+ static wxString ms_timestamp;
+#if WXWIN_COMPATIBILITY_2_8
static wxTraceMask ms_ulTraceMask; // controls wxLogTrace behaviour
- static wxArrayString ms_aTraceMasks; // more powerful filter for wxLogTrace
+#endif // WXWIN_COMPATIBILITY_2_8
+
+ // currently enabled trace masks
+ static wxArrayString ms_aTraceMasks;
};
// ----------------------------------------------------------------------------
// "trivial" derivations of wxLog
// ----------------------------------------------------------------------------
-// log everything to a buffer
+// log everything except for the debug/trace messages (which are passed to
+// wxMessageOutputDebug) to a buffer
class WXDLLIMPEXP_BASE wxLogBuffer : public wxLog
{
public:
virtual void Flush();
protected:
+#if wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
+
+ wxSUPPRESS_DOLOG_HIDE_WARNING()
+#endif // wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
+
virtual void DoLogString(const wxString& szString, time_t t);
+ wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
+
private:
wxString m_str;
- DECLARE_NO_COPY_CLASS(wxLogBuffer)
+ wxDECLARE_NO_COPY_CLASS(wxLogBuffer);
};
{
public:
// redirect log output to a FILE
- wxLogStderr(FILE *fp = (FILE *) NULL);
+ wxLogStderr(FILE *fp = NULL);
protected:
// implement sink function
virtual void DoLogString(const wxString& szString, time_t t);
+ wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
+
FILE *m_fp;
- DECLARE_NO_COPY_CLASS(wxLogStderr)
+ wxDECLARE_NO_COPY_CLASS(wxLogStderr);
};
#if wxUSE_STD_IOSTREAM
// implement sink function
virtual void DoLogString(const wxString& szString, time_t t);
+ wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
+
// using ptr here to avoid including <iostream.h> from this file
wxSTD ostream *m_ostr;
};
// override base class version to flush the old logger as well
virtual void Flush();
+ // call to avoid destroying the old log target
+ void DetachOldLog() { m_logOld = NULL; }
+
protected:
// pass the chain to the old logger if needed
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
+ wxSUPPRESS_DOLOG_HIDE_WARNING()
+
private:
// the current log target
wxLog *m_logNew;
// do we pass the messages to the old logger?
bool m_bPassMessages;
- DECLARE_NO_COPY_CLASS(wxLogChain)
+ wxDECLARE_NO_COPY_CLASS(wxLogChain);
};
// a chain log target which uses itself as the new logger
-class WXDLLIMPEXP_BASE wxLogPassThrough : public wxLogChain
+
+#define wxLogPassThrough wxLogInterposer
+
+class WXDLLIMPEXP_BASE wxLogInterposer : public wxLogChain
+{
+public:
+ wxLogInterposer();
+
+private:
+ wxDECLARE_NO_COPY_CLASS(wxLogInterposer);
+};
+
+// a temporary interposer which doesn't destroy the old log target
+// (calls DetachOldLog)
+
+class WXDLLIMPEXP_BASE wxLogInterposerTemp : public wxLogChain
{
public:
- wxLogPassThrough();
+ wxLogInterposerTemp();
private:
- DECLARE_NO_COPY_CLASS(wxLogPassThrough)
+ wxDECLARE_NO_COPY_CLASS(wxLogInterposerTemp);
};
#if wxUSE_GUI
#else // !wxUSE_LOG
+#undef wxUSE_LOG_DEBUG
+#define wxUSE_LOG_DEBUG 0
+
+#undef wxUSE_LOG_TRACE
+#define wxUSE_LOG_TRACE 0
+
#ifdef __WATCOMC__
// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
#define WX_WATCOM_ONLY_CODE( x ) x
#define WX_WATCOM_ONLY_CODE( x )
#endif
+#if defined(__WATCOMC__) || defined(__MINGW32__)
+ // Mingw has similar problem with wxLogSysError:
+ #define WX_WATCOM_OR_MINGW_ONLY_CODE( x ) x
+#else
+ #define WX_WATCOM_OR_MINGW_ONLY_CODE( x )
+#endif
+
// log functions do nothing at all
#define DECLARE_LOG_FUNCTION(level) \
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxString&)) \
#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxString&)) \
- WX_WATCOM_ONLY_CODE( \
+ WX_WATCOM_OR_MINGW_ONLY_CODE( \
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const char*)) \
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wchar_t*)) \
WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxCStrData&)) \
#if wxUSE_GUI
// this one is the same as previous except that it allows to explicitly
- class WXDLLEXPORT wxFrame;
+ class WXDLLIMPEXP_FWD_CORE wxFrame;
// specify the frame to which the output should go
DECLARE_LOG_FUNCTION2_EXP(Status, wxFrame *, pFrame, WXDLLIMPEXP_CORE);
#endif // wxUSE_GUI
DECLARE_LOG_FUNCTION2(SysError, unsigned long, lErrCode);
#endif
-// debug functions do nothing in release mode
-#if wxUSE_LOG && wxUSE_LOG_DEBUG
+
+// debug functions can be completely disabled in optimized builds
+
+// if these log functions are disabled, we prefer to define them as (empty)
+// variadic macros as this completely removes them and their argument
+// evaluation from the object code but if this is not supported by compiler we
+// use empty inline functions instead (defining them as nothing would result in
+// compiler warnings)
+//
+// note that making wxVLogDebug/Trace() themselves (empty inline) functions is
+// a bad idea as some compilers are stupid enough to not inline even empty
+// functions if their parameters are complicated enough, but by defining them
+// as an empty inline function we ensure that even dumbest compilers optimise
+// them away
+#ifdef __BORLANDC__
+ // but Borland gives "W8019: Code has no effect" for wxLogNop() so we need
+ // to define it differently for it to avoid these warnings (same problem as
+ // with wxUnusedVar())
+ #define wxLogNop() { }
+#else
+ inline void wxLogNop() { }
+#endif
+
+#if wxUSE_LOG_DEBUG
DECLARE_LOG_FUNCTION(Debug);
+#else // !wxUSE_LOG_DEBUG
+ #define wxVLogDebug(fmt, valist) wxLogNop()
- // there is no more unconditional LogTrace: it is not different from
- // LogDebug and it creates overload ambiguities
- //DECLARE_LOG_FUNCTION(Trace);
+ #ifdef HAVE_VARIADIC_MACROS
+ #define wxLogDebug(fmt, ...) wxLogNop()
+ #else // !HAVE_VARIADIC_MACROS
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug, 1, (const wxString&))
+ #endif
+#endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
+#if wxUSE_LOG_TRACE
// this version only logs the message if the mask had been added to the
// list of masks with AddTraceMask()
DECLARE_LOG_FUNCTION2(Trace, const wxString&, mask);
// and this one does nothing if all of level bits are not set in
// wxLog::GetActive()->GetTraceMask() -- it's deprecated in favour of
// string identifiers
+#if WXWIN_COMPATIBILITY_2_8
DECLARE_LOG_FUNCTION2(Trace, wxTraceMask, mask);
#ifdef __WATCOMC__
// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
DECLARE_LOG_FUNCTION2(Trace, int, mask);
#endif
-#else //!debug || !wxUSE_LOG
- // these functions do nothing in release builds, but don't define them as
- // nothing as it could result in different code structure in debug and
- // release and this could result in trouble when these macros are used
- // inside if/else
- //
- // note that making wxVLogDebug/Trace() themselves (empty inline) functions
- // is a bad idea as some compilers are stupid enough to not inline even
- // empty functions if their parameters are complicated enough, but by
- // defining them as an empty inline function we ensure that even dumbest
- // compilers optimise them away
- inline void wxLogNop() { }
+#endif // WXWIN_COMPATIBILITY_2_8
- #define wxVLogDebug(fmt, valist) wxLogNop()
+#else // !wxUSE_LOG_TRACE
#define wxVLogTrace(mask, fmt, valist) wxLogNop()
#ifdef HAVE_VARIADIC_MACROS
- // unlike the inline functions below, this completely removes the
- // wxLogXXX calls from the object file:
- #define wxLogDebug(fmt, ...) wxLogNop()
#define wxLogTrace(mask, fmt, ...) wxLogNop()
#else // !HAVE_VARIADIC_MACROS
- //inline void wxLogDebug(const wxString& fmt, ...) {}
- WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug, 1, (const wxString&))
- //inline void wxLogTrace(wxTraceMask, const wxString& fmt, ...) {}
- //inline void wxLogTrace(const wxString&, const wxString& fmt, ...) {}
+ #if WXWIN_COMPATIBILITY_2_8
WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (wxTraceMask, const wxString&))
+ #endif
WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wxString&, const wxString&))
#ifdef __WATCOMC__
// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wchar_t*, const wchar_t*))
#endif
#endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS
-#endif // debug/!debug
+#endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE
#if defined(__VISUALC__) && __VISUALC__ < 1300
#pragma warning(default:4003)
// debug only logging functions: use them with API name and error code
// ----------------------------------------------------------------------------
-#ifdef __WXDEBUG__
+#if wxUSE_LOG_DEBUG
// make life easier for people using VC++ IDE: clicking on the message
// will take us immediately to the place of the failed API
#ifdef __VISUALC__
#define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())
-#else //!debug
+#else // !wxUSE_LOG_DEBUG
#define wxLogApiError(api, err) wxLogNop()
#define wxLogLastError(api) wxLogNop()
-#endif //debug/!debug
+#endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
// wxCocoa has additiional trace masks
#if defined(__WXCOCOA__)