+/*
+ The code below is unreadable because it (unfortunately unavoidably)
+ contains a lot of macro magic but all it does is to define wxLogXXX() such
+ that you can call them as vararg functions to log a message at the
+ corresponding level.
+
+ More precisely, it defines:
+
+ - wxLog{FatalError,Error,Warning,Message,Verbose,Debug}() functions
+ taking the format string and additional vararg arguments if needed.
+ - wxLogGeneric(wxLogLevel level, const wxString& format, ...) which
+ takes the log level explicitly.
+ - wxLogSysError(const wxString& format, ...) and wxLogSysError(long
+ err, const wxString& format, ...) which log a wxLOG_Error severity
+ message with the error message corresponding to the system error code
+ err or the last error.
+ - wxLogStatus(const wxString& format, ...) which logs the message into
+ the status bar of the main application window and its overload
+ wxLogStatus(wxFrame *frame, const wxString& format, ...) which logs it
+ into the status bar of the specified frame.
+ - wxLogTrace(Mask mask, const wxString& format, ...) which only logs
+ the message is the specified mask is enabled. This comes in two kinds:
+ Mask can be a wxString or a long. Both are deprecated.
+
+ In addition, wxVLogXXX() versions of all the functions above are also
+ defined. They take a va_list argument instead of "...".
+ */
+
+// creates wxLogger object for the current location
+#define wxMAKE_LOGGER(level) \
+ wxLogger(wxLOG_##level, __FILE__, __LINE__, __WXFUNCTION__, wxLOG_COMPONENT)
+
+// this macro generates the expression which logs whatever follows it in
+// parentheses at the level specified as argument
+#define wxDO_LOG(level) wxMAKE_LOGGER(level).Log
+
+// this is the non-vararg equivalent
+#define wxDO_LOGV(level, format, argptr) \
+ wxMAKE_LOGGER(level).LogV(format, argptr)
+
+// this macro declares wxLog<level>() macro which logs whatever follows it if
+// logging at specified level is enabled (notice that if it is false, the
+// following arguments are not even evaluated which is good as it avoids
+// unnecessary overhead)
+//
+// Note: the strange if/else construct is needed to make the following code
+//
+// if ( cond )
+// wxLogError("!!!");
+// else
+// ...
+//
+// work as expected, without it the second "else" would match the "if"
+// inside wxLogError(). Unfortunately code like
+//
+// if ( cond )
+// wxLogError("!!!");
+//
+// now provokes "suggest explicit braces to avoid ambiguous 'else'"
+// warnings from g++ 4.3 and later with -Wparentheses on but they can be
+// easily fixed by adding curly braces around wxLogError() and at least
+// the code still does do the right thing.
+#define wxDO_LOG_IF_ENABLED(level) \
+ if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxDO_LOG(level)
+
+// wxLogFatalError() is special as it can't be disabled
+#define wxLogFatalError wxDO_LOG(FatalError)
+#define wxVLogFatalError(format, argptr) wxDO_LOGV(FatalError, format, argptr)
+
+#define wxLogError wxDO_LOG_IF_ENABLED(Error)
+#define wxVLogError(format, argptr) wxDO_LOGV(Error, format, argptr)
+
+#define wxLogWarning wxDO_LOG_IF_ENABLED(Warning)
+#define wxVLogWarning(format, argptr) wxDO_LOGV(Warning, format, argptr)
+
+#define wxLogMessage wxDO_LOG_IF_ENABLED(Message)
+#define wxVLogMessage(format, argptr) wxDO_LOGV(Message, format, argptr)
+
+// this one is special as it only logs if we're in verbose mode
+#define wxLogVerbose \
+ if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
+ wxLog::GetVerbose()) ) \
+ {} \
+ else \
+ wxDO_LOG(Info)
+#define wxVLogVerbose(format, argptr) \
+ if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
+ wxLog::GetVerbose()) ) \
+ {} \
+ else \
+ wxDO_LOGV(Info, format, argptr)
+
+// deprecated synonyms for wxLogVerbose() and wxVLogVerbose()
+#define wxLogInfo wxLogVerbose
+#define wxVLogInfo wxVLogVerbose
+
+
+// another special case: the level is passed as first argument of the function
+// and so is not available to the macro
+//
+// notice that because of this, arguments of wxLogGeneric() are currently
+// always evaluated, unlike for the other log functions
+#define wxLogGeneric wxMAKE_LOGGER(Max).LogAtLevel
+#define wxVLogGeneric(level, format, argptr) \
+ if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxDO_LOGV(level, format, argptr)
+
+
+// wxLogSysError() needs to stash the error code value in the log record info
+// so it needs special handling too; additional complications arise because the
+// error code may or not be present as the first argument
+//
+// notice that we unfortunately can't avoid the call to wxSysErrorCode() even
+// though it may be unneeded if an explicit error code is passed to us because
+// the message might not be logged immediately (e.g. it could be queued for
+// logging from the main thread later) and so we can't to wait until it is
+// logged to determine whether we have last error or not as it will be too late
+// and it will have changed already by then (in fact it even changes when
+// wxString::Format() is called because of vsnprintf() inside it so it can
+// change even much sooner)
+#define wxLOG_KEY_SYS_ERROR_CODE "wx.sys_error"
+
+#define wxLogSysError \
+ if ( !wxLog::IsLevelEnabled(wxLOG_Error, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
+ wxSysErrorCode()).Log
+
+// unfortunately we can't have overloaded macros so we can't define versions
+// both with and without error code argument and have to rely on LogV()
+// overloads in wxLogger to select between them
+#define wxVLogSysError \
+ wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
+ wxSysErrorCode()).LogV
+
+#if wxUSE_GUI
+ // wxLogStatus() is similar to wxLogSysError() as it allows to optionally
+ // specify the frame to which the message should go
+ #define wxLOG_KEY_FRAME "wx.frame"
+
+ #define wxLogStatus \
+ if ( !wxLog::IsLevelEnabled(wxLOG_Status, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).Log
+
+ #define wxVLogStatus(format, argptr) \
+ wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).LogV
+#endif // wxUSE_GUI
+
+
+#else // !wxUSE_LOG
+
+#undef wxUSE_LOG_DEBUG
+#define wxUSE_LOG_DEBUG 0
+
+#undef wxUSE_LOG_TRACE
+#define wxUSE_LOG_TRACE 0
+
+#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
+
+// define macros for defining log functions which do nothing at all
+//
+// WX_WATCOM_ONLY_CODE is needed to work around
+// http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+#define wxDEFINE_EMPTY_LOG_FUNCTION(level) \
+ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxFormatString&)) \
+ WX_WATCOM_ONLY_CODE( \
+ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const char*)) \
+ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wchar_t*)) \
+ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxCStrData&)) \
+ ) \
+ inline void wxVLog##level(const wxFormatString& WXUNUSED(format), \
+ va_list WXUNUSED(argptr)) { } \
+
+#define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass) \
+ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxFormatString&)) \
+ 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&)) \
+ ) \
+ inline void wxVLog##level(argclass WXUNUSED(arg), \
+ const wxFormatString& WXUNUSED(format), \
+ va_list WXUNUSED(argptr)) {}
+
+wxDEFINE_EMPTY_LOG_FUNCTION(FatalError);
+wxDEFINE_EMPTY_LOG_FUNCTION(Error);
+wxDEFINE_EMPTY_LOG_FUNCTION(SysError);
+wxDEFINE_EMPTY_LOG_FUNCTION2(SysError, long);
+wxDEFINE_EMPTY_LOG_FUNCTION(Warning);
+wxDEFINE_EMPTY_LOG_FUNCTION(Message);
+wxDEFINE_EMPTY_LOG_FUNCTION(Info);
+wxDEFINE_EMPTY_LOG_FUNCTION(Verbose);
+
+wxDEFINE_EMPTY_LOG_FUNCTION2(Generic, wxLogLevel);
+
+#if wxUSE_GUI
+ wxDEFINE_EMPTY_LOG_FUNCTION(Status);
+ wxDEFINE_EMPTY_LOG_FUNCTION2(Status, wxFrame *);
+#endif // wxUSE_GUI
+
+// Empty Class to fake wxLogNull
+class WXDLLIMPEXP_BASE wxLogNull
+{
+public:
+ wxLogNull() { }
+};
+
+// Dummy macros to replace some functions.
+#define wxSysErrorCode() (unsigned long)0
+#define wxSysErrorMsg( X ) (const wxChar*)NULL
+
+// Fake symbolic trace masks... for those that are used frequently
+#define wxTRACE_OleCalls wxEmptyString // OLE interface calls
+
+#endif // wxUSE_LOG/!wxUSE_LOG
+
+
+// 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
+ #define wxLogDebug wxDO_LOG_IF_ENABLED(Debug)
+ #define wxVLogDebug(format, argptr) wxDO_LOGV(Debug, format, argptr)
+#else // !wxUSE_LOG_DEBUG
+ #define wxVLogDebug(fmt, valist) wxLogNop()
+
+ #ifdef HAVE_VARIADIC_MACROS
+ #define wxLogDebug(fmt, ...) wxLogNop()
+ #else // !HAVE_VARIADIC_MACROS
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug, 1, (const wxFormatString&))
+ #endif
+#endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
+
+#if wxUSE_LOG_TRACE
+ #define wxLogTrace \
+ if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxMAKE_LOGGER(Trace).LogTrace
+ #define wxVLogTrace \
+ if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
+ {} \
+ else \
+ wxMAKE_LOGGER(Trace).LogVTrace
+#else // !wxUSE_LOG_TRACE
+ #define wxVLogTrace(mask, fmt, valist) wxLogNop()
+
+ #ifdef HAVE_VARIADIC_MACROS
+ #define wxLogTrace(mask, fmt, ...) wxLogNop()
+ #else // !HAVE_VARIADIC_MACROS
+ #if WXWIN_COMPATIBILITY_2_8
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (wxTraceMask, const wxFormatString&))
+ #endif
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wxString&, const wxFormatString&))
+ #ifdef __WATCOMC__
+ // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const char*, const char*))
+ WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wchar_t*, const wchar_t*))
+ #endif
+ #endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS
+#endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE
+
+// wxLogFatalError helper: show the (fatal) error to the user in a safe way,
+// i.e. without using wxMessageBox() for example because it could crash
+void WXDLLIMPEXP_BASE
+wxSafeShowMessage(const wxString& title, const wxString& text);