diff --git a/docs/doxygen/overviews/log.h b/docs/doxygen/overviews/log.h index f39f4cbcc3..d8cb23e9f7 100644 --- a/docs/doxygen/overviews/log.h +++ b/docs/doxygen/overviews/log.h @@ -71,10 +71,12 @@ argument list pointer. Here are all of them: as the first argument. @li wxLogDebug is @b the right function for debug output. It only does anything at all in the debug mode (when the preprocessor symbol __WXDEBUG__ is - defined) and expands to nothing in release mode (otherwise). @b Tip: under - Windows, you must either run the program under debugger or use a 3rd party - program such as DebugView to actually see the debug output. - - DebugView: http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx + defined) and expands to nothing in release mode (otherwise). + + @b Tip: under Windows, you must either run the program under debugger or + use a 3rd party program such as DebugView + (http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx) + to actually see the debug output. @li wxLogTrace as wxLogDebug only does something in debug build. The reason for making it a separate function from it is that usually there are a lot of trace messages, so it might make sense to separate them from other debug @@ -133,12 +135,16 @@ the active target with a call to @e SetActiveTarget() and it will be used automatically by all subsequent calls to @e wxLogXXX() functions. To create a new log target class you only need to derive it from wxLog and -implement one (or both) of @e DoLog() and @e DoLogString() in it. The second -one is enough if you're happy with the standard wxLog message formatting -(prepending "Error:" or "Warning:", timestamping @&c) but just want to send -the messages somewhere else. The first one may be overridden to do whatever -you want but you have to distinguish between the different message types -yourself. +override one or several of wxLog::DoLogRecord(), wxLog::DoLogTextAtLevel() and +wxLog::DoLogText() in it. The first one is the most flexible and allows you to +change the formatting of the messages, dynamically filter and redirect them and +so on -- all log messages, except for those generated by wxLogFatalError(), +pass by this function. wxLog::DoLogTextAtLevel() should be overridden if you +simply want to redirect the log messages somewhere else, without changing their +formatting. Finally, it is enough to override wxLog::DoLogText() if you only +want to redirect the log messages and the destination doesn't depend on the +message log level. + There are some predefined classes deriving from wxLog and which might be helpful to see how you can create a new log target class and, of course, may diff --git a/include/wx/hashmap.h b/include/wx/hashmap.h index 325c072196..252df7885d 100644 --- a/include/wx/hashmap.h +++ b/include/wx/hashmap.h @@ -748,5 +748,8 @@ WX_DECLARE_HASH_MAP_WITH_DECL( long, long, wxIntegerHash, wxIntegerEqual, WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxString, wxStringToStringHashMap, class WXDLLIMPEXP_BASE ); +WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxUIntPtr, wxStringToNumHashMap, + class WXDLLIMPEXP_BASE ); + #endif // _WX_HASHMAP_H_ diff --git a/include/wx/log.h b/include/wx/log.h index 29c404668b..60b6e8b620 100644 --- a/include/wx/log.h +++ b/include/wx/log.h @@ -54,6 +54,7 @@ typedef unsigned long wxLogLevel; #endif // ! __WXPALMOS5__ #include "wx/dynarray.h" +#include "wx/hashmap.h" #if wxUSE_THREADS #include "wx/thread.h" @@ -124,19 +125,66 @@ enum wxLogLevelValues // information about a log record, i.e. unit of log output // ---------------------------------------------------------------------------- -struct wxLogRecordInfo +class wxLogRecordInfo { +public: + // default ctor creates an uninitialized object wxLogRecordInfo() { - timestamp = 0; - -#if wxUSE_THREADS - threadId = 0; -#endif // wxUSE_THREADS + memset(this, 0, sizeof(this)); } - // default copy ctor, assignment operator and dtor are ok + // normal ctor, used by wxLogger specifies the location of the log + // statement; its time stamp and thread id are set up here + wxLogRecordInfo(const char *filename_, + int line_, + const char *func_) + { + filename = filename_; + func = func_; + line = line_; + timestamp = time(NULL); + +#if wxUSE_THREADS + threadId = wxThread::GetCurrentId(); +#endif // wxUSE_THREADS + + m_data = NULL; + } + + // we need to define copy ctor and assignment operator because of m_data + wxLogRecordInfo(const wxLogRecordInfo& other) + { + Copy(other); + } + + wxLogRecordInfo& operator=(const wxLogRecordInfo& other) + { + if ( &other != this ) + { + delete m_data; + Copy(other); + } + + return *this; + } + + // dtor is non-virtual, this class is not meant to be derived from + ~wxLogRecordInfo() + { + delete m_data; + } + + + // the file name and line number of the file where the log record was + // generated, if available or NULL and 0 otherwise + const char *filename; + int line; + + // the name of the function where the log record was generated (may be NULL + // if the compiler doesn't support __FUNCTION__) + const char *func; // time of record generation time_t timestamp; @@ -145,8 +193,81 @@ struct wxLogRecordInfo // id of the thread which logged this record wxThreadIdType threadId; #endif // wxUSE_THREADS + + + // store an arbitrary value in this record context + // + // wxWidgets always uses keys starting with "wx.", e.g. "wx.sys_error" + void StoreValue(const wxString& key, wxUIntPtr val) + { + if ( !m_data ) + m_data = new ExtraData; + + m_data->numValues[key] = val; + } + + void StoreValue(const wxString& key, const wxString& val) + { + if ( !m_data ) + m_data = new ExtraData; + + m_data->strValues[key] = val; + } + + + // these functions retrieve the value of either numeric or string key, + // return false if not found + bool GetNumValue(const wxString& key, wxUIntPtr *val) const + { + if ( !m_data ) + return false; + + wxStringToNumHashMap::const_iterator it = m_data->numValues.find(key); + if ( it == m_data->numValues.end() ) + return false; + + *val = it->second; + + return true; + } + + bool GetStrValue(const wxString& key, wxString *val) const + { + if ( !m_data ) + return false; + + wxStringToStringHashMap::const_iterator it = m_data->strValues.find(key); + if ( it == m_data->strValues.end() ) + return false; + + *val = it->second; + + return true; + } + +private: + void Copy(const wxLogRecordInfo& other) + { + memcpy(this, &other, sizeof(wxLogRecordInfo)); + if ( other.m_data ) + m_data = new ExtraData(*other.m_data); + } + + // extra data associated with the log record: this is completely optional + // and can be used to pass information from the log function to the log + // sink (e.g. wxLogSysError() uses this to pass the error code) + struct ExtraData + { + wxStringToNumHashMap numValues; + wxStringToStringHashMap strValues; + }; + + // NULL if not used + ExtraData *m_data; }; +#define wxLOG_KEY_TRACE_MASK "wx.trace_mask" + // ---------------------------------------------------------------------------- // derive from this class to redirect (or suppress, or ...) log messages // normally, only a single instance of this class exists but it's not enforced @@ -338,7 +459,7 @@ protected: // for every "record", i.e. a unit of log output, to be logged and by // default formats the message and passes it to DoLogTextAtLevel() which in // turn passes it to DoLogText() by default - + // override this method if you want to change message formatting or do // dynamic filtering virtual void DoLogRecord(wxLogLevel level, @@ -599,15 +720,333 @@ private: #include "wx/generic/logg.h" #endif // wxUSE_GUI +// ---------------------------------------------------------------------------- +// wxLogger +// ---------------------------------------------------------------------------- + +// wxLogger is a helper class used by wxLogXXX() functions implementation, +// don't use it directly as it's experimental and subject to change (OTOH it +// might become public in the future if it's deemed to be useful enough) + +// contains information about the context from which a log message originates +// and provides Log() vararg method which forwards to wxLog::OnLog() and passes +// this context to it +class wxLogger +{ +public: + // ctor takes the basic information about the log record + wxLogger(wxLogLevel level, + const char *filename, + int line, + const char *func) + : m_level(level), + m_info(filename, line, func) + { + } + + // store extra data in our log record and return this object itself (so + // that further calls to its functions could be chained) + template + wxLogger& Store(const wxString& key, T val) + { + m_info.StoreValue(key, val); + return *this; + } + + // hack for "overloaded" wxLogXXX() functions: calling this method + // indicates that we may have an extra first argument preceding the format + // string and that if we do have it, we should store it in m_info using the + // given key (while by default 0 value will be used) + wxLogger& MaybeStore(const wxString& key) + { + wxASSERT_MSG( m_optKey.empty(), "can only have one optional value" ); + m_optKey = key; + + m_info.StoreValue(key, 0); + return *this; + } + + + // non-vararg function used by wxVLogXXX(): + + // log the message at the level specified in the ctor if this log message + // is enabled + void LogV(const wxString& format, va_list argptr) + { + // remember that fatal errors can't be disabled + if ( m_level == wxLOG_FatalError || wxLog::IsLevelEnabled(m_level) ) + DoCallOnLog(format, argptr); + } + + // overloads used by functions with optional leading arguments (whose + // values are stored in the key passed to MaybeStore()) + void LogV(long num, const wxString& format, va_list argptr) + { + Store(m_optKey, num); + + LogV(format, argptr); + } + + void LogV(void *ptr, const wxString& format, va_list argptr) + { + Store(m_optKey, wxPtrToUInt(ptr)); + + LogV(format, argptr); + } + + + // vararg functions used by wxLogXXX(): + + // will log the message at the level specified in the ctor + // + // notice that this function supposes that the caller already checked that + // the level was enabled and does no checks itself + WX_DEFINE_VARARG_FUNC_VOID + ( + Log, + 1, (const wxFormatString&), + DoLog, DoLogUtf8 + ) + + // same as Log() but with an extra numeric or pointer parameters: this is + // used to pass an optional value by storing it in m_info under the name + // passed to MaybeStore() and is required to support "overloaded" versions + // of wxLogStatus() and wxLogSysError() + WX_DEFINE_VARARG_FUNC_VOID + ( + Log, + 2, (long, const wxFormatString&), + DoLogWithNum, DoLogWithNumUtf8 + ) + + WX_DEFINE_VARARG_FUNC_VOID + ( + Log, + 2, (void *, const wxFormatString&), + DoLogWithPtr, DoLogWithPtrUtf8 + ) + + // log the message at the level specified as its first argument + // + // as the macros don't have access to the level argument in this case, this + // function does check that the level is enabled itself + WX_DEFINE_VARARG_FUNC_VOID + ( + LogAtLevel, + 2, (wxLogLevel, const wxFormatString&), + DoLogAtLevel, DoLogAtLevelUtf8 + ) + + // special versions for wxLogTrace() which is passed either string or + // integer (TODO) mask as first argument determining whether the message + // should be logged or not + WX_DEFINE_VARARG_FUNC_VOID + ( + LogTrace, + 2, (const wxString&, const wxFormatString&), + DoLogTrace, DoLogTraceUtf8 + ) + +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 1, (const wxString&), + (wxFormatString(f1))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 1, (const wxCStrData&), + (wxFormatString(f1))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 1, (const char*), + (wxFormatString(f1))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 1, (const wchar_t*), + (wxFormatString(f1))) + + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (long, const wxString&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (long, const wxCStrData&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (long, const char *), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (long, const wchar_t *), + (f1, wxFormatString(f2))) + + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (void *, const wxString&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (void *, const wxCStrData&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (void *, const char *), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, Log, + 2, (void *, const wchar_t *), + (f1, wxFormatString(f2))) + + WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel, + 2, (wxLogLevel, const wxString&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel, + 2, (wxLogLevel, const wxCStrData&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel, + 2, (wxLogLevel, const char *), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel, + 2, (wxLogLevel, const wchar_t *), + (f1, wxFormatString(f2))) + + WX_VARARG_WATCOM_WORKAROUND(void, LogTrace, + 2, (const wxString&, const wxString&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogTrace, + 2, (const wxString&, const wxCStrData&), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogTrace, + 2, (const wxString&, const char *), + (f1, wxFormatString(f2))) + WX_VARARG_WATCOM_WORKAROUND(void, LogTrace, + 2, (const wxString&, const wchar_t *), + (f1, wxFormatString(f2))) +#endif // __WATCOMC__ + +private: +#if !wxUSE_UTF8_LOCALE_ONLY + void DoLog(const wxChar *format, ...) + { + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogWithNum(long num, const wxChar *format, ...) + { + Store(m_optKey, num); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogWithPtr(void *ptr, const wxChar *format, ...) + { + Store(m_optKey, wxPtrToUInt(ptr)); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogAtLevel(wxLogLevel level, const wxChar *format, ...) + { + if ( !wxLog::IsLevelEnabled(level) ) + return; + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(level, format, argptr); + va_end(argptr); + } + + void DoLogTrace(const wxString& mask, const wxChar *format, ...) + { + if ( !wxLog::IsAllowedTraceMask(mask) ) + return; + + Store(wxLOG_KEY_TRACE_MASK, mask); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } +#endif // !wxUSE_UTF8_LOCALE_ONLY + +#if wxUSE_UNICODE_UTF8 + void DoLogUtf8(const char *format, ...) + { + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogWithNumUtf8(long num, const char *format, ...) + { + Store(m_optKey, num); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogWithPtrUtf8(void *ptr, const char *format, ...) + { + Store(m_optKey, wxPtrToUInt(ptr)); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } + + void DoLogAtLevelUtf8(wxLogLevel level, const char *format, ...) + { + if ( !wxLog::IsLevelEnabled(level) ) + return; + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(level, format, argptr); + va_end(argptr); + } + + void DoLogTraceUtf8(const wxString& mask, const char *format, ...) + { + if ( !wxLog::IsAllowedTraceMask(mask) ) + return; + + Store(wxLOG_KEY_TRACE_MASK, mask); + + va_list argptr; + va_start(argptr, format); + DoCallOnLog(format, argptr); + va_end(argptr); + } +#endif // wxUSE_UNICODE_UTF8 + + void DoCallOnLog(wxLogLevel level, const wxString& format, va_list argptr) + { + wxLog::OnLog(level, wxString::FormatV(format, argptr), m_info); + } + + void DoCallOnLog(const wxString& format, va_list argptr) + { + wxLog::OnLog(m_level, wxString::FormatV(format, argptr), m_info); + } + + + const wxLogLevel m_level; + wxLogRecordInfo m_info; + + wxString m_optKey; + + wxDECLARE_NO_COPY_CLASS(wxLogger); +}; + // ============================================================================ // global functions // ============================================================================ -// ---------------------------------------------------------------------------- -// Log functions should be used by application instead of stdio, iostream &c -// for log messages for easy redirection -// ---------------------------------------------------------------------------- - // ---------------------------------------------------------------------------- // get error code/error message from system in a portable way // ---------------------------------------------------------------------------- @@ -619,76 +1058,152 @@ WXDLLIMPEXP_BASE unsigned long wxSysErrorCode(); WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); // ---------------------------------------------------------------------------- -// define wxLog +// define wxLog() functions which can be used by application instead of +// stdio, iostream &c for log messages for easy redirection // ---------------------------------------------------------------------------- -#define DECLARE_LOG_FUNCTION(level) \ - extern void WXDLLIMPEXP_BASE \ - wxDoLog##level##Wchar(const wxChar *format, ...); \ - extern void WXDLLIMPEXP_BASE \ - wxDoLog##level##Utf8(const char *format, ...); \ - WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ - 1, (const wxFormatString&), \ - wxDoLog##level##Wchar, wxDoLog##level##Utf8) \ - DECLARE_LOG_FUNCTION_WATCOM(level) \ - extern void WXDLLIMPEXP_BASE wxVLog##level(const wxString& format, \ - va_list argptr) +/* + 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. -#ifdef __WATCOMC__ - // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351; - // can't use WX_WATCOM_ONLY_CODE here because the macro would expand to - // something too big for Borland C++ to handle - #define DECLARE_LOG_FUNCTION_WATCOM(level) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 1, (const wxString&), \ - (wxFormatString(f1))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 1, (const wxCStrData&), \ - (wxFormatString(f1))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 1, (const char*), \ - (wxFormatString(f1))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 1, (const wchar_t*), \ - (wxFormatString(f1))) -#else - #define DECLARE_LOG_FUNCTION_WATCOM(level) -#endif + 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__) + +// 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() 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) ) \ + {} \ + 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::GetVerbose()) ) \ + {} \ + else \ + wxDO_LOG(Info) +#define wxVLogVerbose(format, argptr) \ + if ( !(wxLog::IsLevelEnabled(wxLOG_Info) && wxLog::GetVerbose()) ) \ + {} \ + else \ + wxDO_LOGV(Info, format, argptr) + +// deprecated synonyms for wxLogVerbose() and wxVLogVerbose() +#define wxLogInfo wxLogVerbose +#define wxVLogInfo wxVLogVerbose -#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \ - extern void expdecl wxDoLog##level##Wchar(argclass arg, \ - const wxChar *format, ...); \ - extern void expdecl wxDoLog##level##Utf8(argclass arg, \ - const char *format, ...); \ - WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ - 2, (argclass, const wxFormatString&), \ - wxDoLog##level##Wchar, wxDoLog##level##Utf8) \ - DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl) \ - extern void expdecl wxVLog##level(argclass arg, \ - const wxString& format, \ - va_list argptr) +// 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) ) \ + {} \ + else \ + wxDO_LOGV(level, format, argptr) -#ifdef __WATCOMC__ - // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351; - // can't use WX_WATCOM_ONLY_CODE here because the macro would expand to - // something too big for Borland C++ to handle - #define DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 2, (argclass, const wxString&), \ - (f1, wxFormatString(f2))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 2, (argclass, const wxCStrData&), \ - (f1, wxFormatString(f2))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 2, (argclass, const char*), \ - (f1, wxFormatString(f2))) \ - WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level, \ - 2, (argclass, const wchar_t*), \ - (f1, wxFormatString(f2))) -#else - #define DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl) -#endif + +// 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 +#define wxLOG_KEY_SYS_ERROR_CODE "wx.sys_error" + +#define wxLogSysError \ + if ( !wxLog::IsLevelEnabled(wxLOG_Error) ) \ + {} \ + else \ + wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE).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).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) ) \ + {} \ + 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 @@ -699,13 +1214,6 @@ WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 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 -#else - #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 @@ -713,8 +1221,11 @@ WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); #define WX_WATCOM_OR_MINGW_ONLY_CODE( x ) #endif -// log functions do nothing at all -#define DECLARE_LOG_FUNCTION(level) \ +// 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 wxString&)) \ WX_WATCOM_ONLY_CODE( \ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const char*)) \ @@ -724,7 +1235,7 @@ WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); inline void wxVLog##level(const wxString& WXUNUSED(format), \ va_list WXUNUSED(argptr)) { } \ -#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \ +#define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass) \ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxString&)) \ WX_WATCOM_OR_MINGW_ONLY_CODE( \ WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const char*)) \ @@ -735,6 +1246,22 @@ WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); const wxString& 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 { @@ -751,51 +1278,6 @@ public: #endif // wxUSE_LOG/!wxUSE_LOG -#define DECLARE_LOG_FUNCTION2(level, argclass, arg) \ - DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, WXDLLIMPEXP_BASE) - -// VC6 produces a warning if we a macro expanding to nothing to -// DECLARE_LOG_FUNCTION2: -#if defined(__VISUALC__) && __VISUALC__ < 1300 - #pragma warning(push) - // "not enough actual parameters for macro 'DECLARE_LOG_FUNCTION2_EXP'" - #pragma warning(disable:4003) -#endif - -// a generic function for all levels (level is passes as parameter) -DECLARE_LOG_FUNCTION2(Generic, wxLogLevel, level); - -// one function per each level -DECLARE_LOG_FUNCTION(FatalError); -DECLARE_LOG_FUNCTION(Error); -DECLARE_LOG_FUNCTION(Warning); -DECLARE_LOG_FUNCTION(Message); -DECLARE_LOG_FUNCTION(Info); -DECLARE_LOG_FUNCTION(Verbose); - -// this function sends the log message to the status line of the top level -// application frame, if any -DECLARE_LOG_FUNCTION(Status); - -#if wxUSE_GUI - // this one is the same as previous except that it allows to explicitly - 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 - -// additional one: as wxLogError, but also logs last system call error code -// and the corresponding error message if available -DECLARE_LOG_FUNCTION(SysError); - -// and another one which also takes the error code (for those broken APIs -// that don't set the errno (like registry APIs in Win32)) -DECLARE_LOG_FUNCTION2(SysError, long, lErrCode); -#ifdef __WATCOMC__ -// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 -DECLARE_LOG_FUNCTION2(SysError, unsigned long, lErrCode); -#endif - // debug functions can be completely disabled in optimized builds @@ -820,7 +1302,8 @@ DECLARE_LOG_FUNCTION2(SysError, unsigned long, lErrCode); #endif #if wxUSE_LOG_DEBUG - DECLARE_LOG_FUNCTION(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() @@ -832,26 +1315,11 @@ DECLARE_LOG_FUNCTION2(SysError, unsigned long, lErrCode); #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); -#ifdef __WATCOMC__ - // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 - DECLARE_LOG_FUNCTION2(Trace, const char*, mask); - DECLARE_LOG_FUNCTION2(Trace, const wchar_t*, mask); -#endif - - // 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 -#endif // WXWIN_COMPATIBILITY_2_8 - + #define wxLogTrace \ + if ( !wxLog::IsLevelEnabled(wxLOG_Trace) ) \ + {} \ + else \ + wxMAKE_LOGGER(Trace).LogTrace #else // !wxUSE_LOG_TRACE #define wxVLogTrace(mask, fmt, valist) wxLogNop() @@ -870,10 +1338,6 @@ DECLARE_LOG_FUNCTION2(SysError, unsigned long, lErrCode); #endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS #endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE -#if defined(__VISUALC__) && __VISUALC__ < 1300 - #pragma warning(pop) -#endif - // 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 diff --git a/include/wx/platform.h b/include/wx/platform.h index a1a2537981..6e07657e07 100644 --- a/include/wx/platform.h +++ b/include/wx/platform.h @@ -338,18 +338,22 @@ /* - This macro can be used to test the Open Watcom version. + Define Watcom-specific macros. */ #ifndef __WATCOMC__ # define wxWATCOM_VERSION(major,minor) 0 # define wxCHECK_WATCOM_VERSION(major,minor) 0 # define wxONLY_WATCOM_EARLIER_THAN(major,minor) 0 -#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 -# error "Only Open Watcom is supported in this release" +# define WX_WATCOM_ONLY_CODE( x ) #else +# if __WATCOMC__ < 1200 +# error "Only Open Watcom is supported in this release" +# endif + # define wxWATCOM_VERSION(major,minor) ( major * 100 + minor * 10 + 1100 ) # define wxCHECK_WATCOM_VERSION(major,minor) ( __WATCOMC__ >= wxWATCOM_VERSION(major,minor) ) # define wxONLY_WATCOM_EARLIER_THAN(major,minor) ( __WATCOMC__ < wxWATCOM_VERSION(major,minor) ) +# define WX_WATCOM_ONLY_CODE( x ) x #endif /* diff --git a/interface/wx/log.h b/interface/wx/log.h index 4492e375fd..42ef240c14 100644 --- a/interface/wx/log.h +++ b/interface/wx/log.h @@ -37,8 +37,23 @@ typedef unsigned long wxLogLevel; /** Information about a log record (unit of the log output). */ -struct wxLogRecordInfo +class wxLogRecordInfo { +public: + /// The name of the file where this log message was generated. + const char *filename; + + /// The line number at which this log message was generated. + int line; + + /** + The name of the function where the log record was generated. + + This field may be @NULL if the compiler doesn't support @c __FUNCTION__ + (but most modern compilers do). + */ + const char *func; + /// Time when the log message was generated. time_t timestamp; @@ -587,19 +602,23 @@ public: @section log_derivingyours Deriving your own log target - There are two functions which must be implemented by any derived class to - actually process the log messages: DoLog() and DoLogString(). - The second function receives a string which just has to be output in some way - and the easiest way to write a new log target is to override just this function - in the derived class. + There are several methods which may be overridden in the derived class to + customize log messages handling: DoLogRecord(), DoLogTextAtLevel() and + DoLogText(). - If more control over the output format is needed, then the first function must - be overridden which allows to construct custom messages depending on the log level - or even do completely different things depending on the message severity - (for example, throw away all messages except warnings and errors, show warnings - on the screen and forward the error messages to the user's (or programmer's) cell - phone - maybe depending on whether the timestamp tells us if it is day or - night in the current time zone). + The last method is the simplest one: you should override it if you simply + want to redirect the log output elsewhere, without taking into account the + level of the message. If you do want to handle messages of different levels + differently, then you should override DoLogTextAtLevel(). + + Finally, if more control over the output format is needed, then the first + function must be overridden as it allows to construct custom messages + depending on the log level or even do completely different things depending + on the message severity (for example, throw away all messages except + warnings and errors, show warnings on the screen and forward the error + messages to the user's (or programmer's) cell phone -- maybe depending on + whether the timestamp tells us if it is day or night in the current time + zone). There also functions to support message buffering. Why are they needed? Some of wxLog implementations, most notably the standard wxLogGui class, @@ -609,9 +628,7 @@ public: Flush() shows them all and clears the buffer contents. This function doesn't do anything if the buffer is already empty. - See also: - @li Flush() - @li FlushActive() + @see FlushActive() @section log_tracemasks Using trace masks diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index b334211622..248f717fcc 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -1521,10 +1521,9 @@ void MyFrame::OnNotifMsgShow(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnNotifMsgHide(wxCommandEvent& WXUNUSED(event)) { - if ( m_notifMsg ) + if ( m_notifMsg && !m_notifMsg->Close() ) { - if ( !m_notifMsg->Close() ) - wxLogStatus("Failed to hide manual notification message"); + wxLogStatus("Failed to hide manual notification message"); } } diff --git a/src/common/file.cpp b/src/common/file.cpp index 58e36f2218..d4514c5693 100644 --- a/src/common/file.cpp +++ b/src/common/file.cpp @@ -560,7 +560,9 @@ void wxTempFile::Discard() { m_file.Close(); if ( wxRemove(m_strTemp) != 0 ) + { wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str()); + } } #endif // wxUSE_FILE diff --git a/src/common/hyperlnkcmn.cpp b/src/common/hyperlnkcmn.cpp index 582147736d..7765e21d8b 100644 --- a/src/common/hyperlnkcmn.cpp +++ b/src/common/hyperlnkcmn.cpp @@ -77,8 +77,12 @@ void wxHyperlinkCtrlBase::SendEvent() wxString url = GetURL(); wxHyperlinkEvent linkEvent(this, GetId(), url); if (!GetEventHandler()->ProcessEvent(linkEvent)) // was the event skipped ? + { if (!wxLaunchDefaultBrowser(url)) + { wxLogWarning(wxT("Could not launch the default browser with url '%s' !"), url.c_str()); + } + } } #endif // wxUSE_HYPERLINKCTRL diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index 388a0c8224..93288ddab1 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -84,7 +84,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, if ( !image->Ok() ) { if ( verbose ) + { wxLogError(_("BMP: Couldn't save invalid image.")); + } return false; } @@ -118,7 +120,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, ) { if ( verbose ) + { wxLogError(_("BMP: wxImage doesn't have own wxPalette.")); + } return false; } bpp = 8; @@ -222,7 +226,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, ) { if (verbose) + { wxLogError(_("BMP: Couldn't write the file (Bitmap) header.")); + } return false; } } @@ -243,7 +249,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, ) { if (verbose) + { wxLogError(_("BMP: Couldn't write the file (BitmapInfo) header.")); + } return false; } } @@ -317,7 +325,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, if ( !stream.Write(rgbquad, palette_size*4) ) { if (verbose) + { wxLogError(_("BMP: Couldn't write RGB color map.")); + } delete[] rgbquad; #if wxUSE_PALETTE delete palette; @@ -450,7 +460,9 @@ bool wxBMPHandler::SaveDib(wxImage *image, if ( !stream.Write(buffer, row_width) ) { if (verbose) + { wxLogError(_("BMP: Couldn't write data.")); + } delete[] buffer; #if wxUSE_PALETTE delete palette; @@ -498,7 +510,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, if ( !cmap ) { if (verbose) + { wxLogError(_("BMP: Couldn't allocate memory.")); + } return false; } } @@ -518,7 +532,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, if ( !ptr ) { if ( verbose ) + { wxLogError( _("BMP: Couldn't allocate memory.") ); + } return false; } @@ -531,7 +547,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, if ( !alpha ) { if ( verbose ) + { wxLogError(_("BMP: Couldn't allocate memory.")); + } return false; } } @@ -924,13 +942,17 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, if ( width > 32767 ) { if (verbose) + { wxLogError( _("DIB Header: Image width > 32767 pixels for file.") ); + } return false; } if ( height > 32767 ) { if (verbose) + { wxLogError( _("DIB Header: Image height > 32767 pixels for file.") ); + } return false; } @@ -944,7 +966,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, if ( bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32 ) { if (verbose) + { wxLogError( _("DIB Header: Unknown bitdepth in file.") ); + } return false; } @@ -954,7 +978,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, comp != BI_BITFIELDS ) { if (verbose) + { wxLogError( _("DIB Header: Unknown encoding in file.") ); + } return false; } @@ -969,7 +995,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32))) { if (verbose) + { wxLogError( _("DIB Header: Encoding doesn't match bitdepth.") ); + } return false; } @@ -978,7 +1006,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, verbose, IsBmp, true) ) { if (verbose) + { wxLogError( _("Error in reading image DIB.") ); + } return false; } @@ -991,7 +1021,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, verbose, IsBmp, false) ) { if (verbose) + { wxLogError( _("ICO: Error in reading mask DIB.") ); + } return false; } image->SetMaskFromImage(mask, 255, 255, 255); @@ -1069,13 +1101,17 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( image->GetHeight () > 127 ) { if ( verbose ) + { wxLogError(_("ICO: Image too tall for an icon.")); + } return false; } if ( image->GetWidth () > 255 ) { if ( verbose ) + { wxLogError(_("ICO: Image too wide for an icon.")); + } return false; } @@ -1101,7 +1137,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !stream.IsOk() ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } @@ -1160,7 +1198,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !bResult ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } IsMask = true; @@ -1169,7 +1209,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !bResult ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } wxUint32 Size = cStream.GetSize(); @@ -1224,7 +1266,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !stream.IsOk() ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } @@ -1234,7 +1278,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !bResult ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } IsMask = true; @@ -1243,7 +1289,9 @@ bool wxICOHandler::SaveFile(wxImage *image, if ( !bResult ) { if ( verbose ) + { wxLogError(_("ICO: Error writing the image file!")); + } return false; } diff --git a/src/common/imaggif.cpp b/src/common/imaggif.cpp index cd81463b49..7c7ef7c8e3 100644 --- a/src/common/imaggif.cpp +++ b/src/common/imaggif.cpp @@ -89,7 +89,9 @@ bool wxGIFHandler::SaveFile( wxImage * WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool verbose ) { if (verbose) + { wxLogDebug(wxT("GIF: the handler is read-only!!")); + } return false; } diff --git a/src/common/imagiff.cpp b/src/common/imagiff.cpp index 2ea52b1403..2c7dd95454 100644 --- a/src/common/imagiff.cpp +++ b/src/common/imagiff.cpp @@ -777,7 +777,9 @@ bool wxIFFHandler::SaveFile(wxImage * WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool verbose) { if (verbose) + { wxLogDebug(wxT("IFF: the handler is read-only!!")); + } return false; } diff --git a/src/common/imagjpeg.cpp b/src/common/imagjpeg.cpp index a06f0dd8f2..3dbadbe1cf 100644 --- a/src/common/imagjpeg.cpp +++ b/src/common/imagjpeg.cpp @@ -251,7 +251,9 @@ bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos * We need to clean up the JPEG object, close the input file, and return. */ if (verbose) + { wxLogError(_("JPEG: Couldn't load - file is probably corrupted.")); + } (cinfo.src->term_source)(&cinfo); jpeg_destroy_decompress(&cinfo); if (image->Ok()) image->Destroy(); @@ -421,7 +423,9 @@ bool wxJPEGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo * We need to clean up the JPEG object, close the input file, and return. */ if (verbose) + { wxLogError(_("JPEG: Couldn't save image.")); + } jpeg_destroy_compress(&cinfo); return false; } diff --git a/src/common/imagpcx.cpp b/src/common/imagpcx.cpp index 71f3b1e7a5..09a4612cbf 100644 --- a/src/common/imagpcx.cpp +++ b/src/common/imagpcx.cpp @@ -439,7 +439,9 @@ bool wxPCXHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose if (!CanRead(stream)) { if (verbose) + { wxLogError(_("PCX: this is not a PCX file.")); + } return false; } diff --git a/src/common/imagpng.cpp b/src/common/imagpng.cpp index 83446867ad..abe155c880 100644 --- a/src/common/imagpng.cpp +++ b/src/common/imagpng.cpp @@ -165,7 +165,9 @@ PNGLINKAGEMODE wx_png_warning(png_structp png_ptr, png_const_charp message) { wxPNGInfoStruct *info = png_ptr ? WX_PNG_INFO(png_ptr) : NULL; if ( !info || info->verbose ) + { wxLogWarning( wxString::FromAscii(message) ); + } } // from pngerror.c @@ -608,7 +610,9 @@ wxPNGHandler::LoadFile(wxImage *image, error: if (verbose) + { wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory.")); + } if ( image->Ok() ) { @@ -657,7 +661,9 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbos if (!png_ptr) { if (verbose) + { wxLogError(_("Couldn't save PNG image.")); + } return false; } @@ -666,7 +672,9 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbos { png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); if (verbose) + { wxLogError(_("Couldn't save PNG image.")); + } return false; } @@ -674,7 +682,9 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbos { png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); if (verbose) + { wxLogError(_("Couldn't save PNG image.")); + } return false; } diff --git a/src/common/imagpnm.cpp b/src/common/imagpnm.cpp index 2b3e75f979..731220450b 100644 --- a/src/common/imagpnm.cpp +++ b/src/common/imagpnm.cpp @@ -69,7 +69,10 @@ bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose case wxT('5'): // RAW Grey case wxT('6'): break; default: - if (verbose) wxLogError(_("PNM: File format is not recognized.")); + if (verbose) + { + wxLogError(_("PNM: File format is not recognized.")); + } return false; } @@ -85,7 +88,9 @@ bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose if (!ptr) { if (verbose) + { wxLogError( _("PNM: Couldn't allocate memory.") ); + } return false; } @@ -103,7 +108,10 @@ bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose *ptr++=(unsigned char)value; // B if ( !buf_stream ) { - if (verbose) wxLogError(_("PNM: File seems truncated.")); + if (verbose) + { + wxLogError(_("PNM: File seems truncated.")); + } return false; } } @@ -122,7 +130,10 @@ bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose if ( !buf_stream ) { - if (verbose) wxLogError(_("PNM: File seems truncated.")); + if (verbose) + { + wxLogError(_("PNM: File seems truncated.")); + } return false; } } @@ -141,7 +152,10 @@ bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose *ptr++=value; // B if ( !buf_stream ) { - if (verbose) wxLogError(_("PNM: File seems truncated.")); + if (verbose) + { + wxLogError(_("PNM: File seems truncated.")); + } return false; } } diff --git a/src/common/imagtga.cpp b/src/common/imagtga.cpp index d98ff01800..62080d22c1 100644 --- a/src/common/imagtga.cpp +++ b/src/common/imagtga.cpp @@ -669,7 +669,9 @@ bool wxTGAHandler::LoadFile(wxImage* image, if ( !CanRead(stream) ) { if ( verbose ) + { wxLogError(wxT("TGA: this is not a TGA file.")); + } return false; } diff --git a/src/common/imagtiff.cpp b/src/common/imagtiff.cpp index 506000e034..13606aeffe 100644 --- a/src/common/imagtiff.cpp +++ b/src/common/imagtiff.cpp @@ -270,7 +270,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if (!tif) { if (verbose) + { wxLogError( _("TIFF: Error loading image.") ); + } return false; } @@ -278,7 +280,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if (!TIFFSetDirectory( tif, (tdir_t)index )) { if (verbose) + { wxLogError( _("Invalid TIFF image index.") ); + } TIFFClose( tif ); @@ -305,7 +309,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if ( bytesNeeded >= wxUINT32_MAX ) { if ( verbose ) + { wxLogError( _("TIFF: Image size is abnormally big.") ); + } TIFFClose(tif); @@ -317,7 +323,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if (!raster) { if (verbose) + { wxLogError( _("TIFF: Couldn't allocate memory.") ); + } TIFFClose( tif ); @@ -328,7 +336,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if (!image->Ok()) { if (verbose) + { wxLogError( _("TIFF: Couldn't allocate memory.") ); + } _TIFFfree( raster ); TIFFClose( tif ); @@ -342,7 +352,9 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos if (!TIFFReadRGBAImage( tif, w, h, raster, 0 )) { if (verbose) + { wxLogError( _("TIFF: Error reading image.") ); + } _TIFFfree( raster ); image->Destroy(); @@ -450,7 +462,9 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo if (!tif) { if (verbose) + { wxLogError( _("TIFF: Error saving image.") ); + } return false; } @@ -530,7 +544,9 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo if (!buf) { if (verbose) + { wxLogError( _("TIFF: Couldn't allocate memory.") ); + } TIFFClose( tif ); @@ -576,7 +592,9 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo if ( TIFFWriteScanline(tif, buf ? buf : ptr, (uint32)row, 0) < 0 ) { if (verbose) + { wxLogError( _("TIFF: Error writing image.") ); + } TIFFClose( tif ); if (buf) diff --git a/src/common/intl.cpp b/src/common/intl.cpp index 978b4b41e5..f5fe1b49cd 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -1635,7 +1635,9 @@ bool wxLocale::Init(const wxString& name, m_pszOldLocale = NULL; if ( m_pszOldLocale == NULL ) + { wxLogError(_("locale '%s' can not be set."), szLocale); + } // the short name will be used to look for catalog files as well, // so we need something here diff --git a/src/common/log.cpp b/src/common/log.cpp index eea84cbf12..0afb906f28 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -137,82 +137,9 @@ PreviousLogInfo gs_prevLog; // ============================================================================ // ---------------------------------------------------------------------------- -// implementation of Log functions -// -// NB: unfortunately we need all these distinct functions, we can't make them -// macros and not all compilers inline vararg functions. +// helper global functions // ---------------------------------------------------------------------------- -// generic log function -void wxVLogGeneric(wxLogLevel level, const wxString& format, va_list argptr) -{ - if ( wxLog::IsEnabled() ) - { - wxLog::OnLog(level, wxString::FormatV(format, argptr)); - } -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void wxDoLogGenericWchar(wxLogLevel level, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogGeneric(level, format, argptr); - va_end(argptr); -} -#endif // wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void wxDoLogGenericUtf8(wxLogLevel level, const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogGeneric(level, format, argptr); - va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - -#if !wxUSE_UTF8_LOCALE_ONLY - #define IMPLEMENT_LOG_FUNCTION_WCHAR(level) \ - void wxDoLog##level##Wchar(const wxChar *format, ...) \ - { \ - va_list argptr; \ - va_start(argptr, format); \ - wxVLog##level(format, argptr); \ - va_end(argptr); \ - } -#else - #define IMPLEMENT_LOG_FUNCTION_WCHAR(level) -#endif - -#if wxUSE_UNICODE_UTF8 - #define IMPLEMENT_LOG_FUNCTION_UTF8(level) \ - void wxDoLog##level##Utf8(const char *format, ...) \ - { \ - va_list argptr; \ - va_start(argptr, format); \ - wxVLog##level(format, argptr); \ - va_end(argptr); \ - } -#else - #define IMPLEMENT_LOG_FUNCTION_UTF8(level) -#endif - -#define IMPLEMENT_LOG_FUNCTION(level) \ - void wxVLog##level(const wxString& format, va_list argptr) \ - { \ - if ( wxLog::IsEnabled() ) \ - wxLog::OnLog(wxLOG_##level, wxString::FormatV(format, argptr)); \ - } \ - IMPLEMENT_LOG_FUNCTION_WCHAR(level) \ - IMPLEMENT_LOG_FUNCTION_UTF8(level) - -IMPLEMENT_LOG_FUNCTION(Error) -IMPLEMENT_LOG_FUNCTION(Warning) -IMPLEMENT_LOG_FUNCTION(Message) -IMPLEMENT_LOG_FUNCTION(Info) -IMPLEMENT_LOG_FUNCTION(Status) - void wxSafeShowMessage(const wxString& title, const wxString& text) { #ifdef __WINDOWS__ @@ -223,291 +150,6 @@ void wxSafeShowMessage(const wxString& title, const wxString& text) #endif } -// fatal errors can't be suppressed nor handled by the custom log target and -// always terminate the program -void wxVLogFatalError(const wxString& format, va_list argptr) -{ - wxSafeShowMessage(wxS("Fatal Error"), wxString::FormatV(format, argptr)); - -#ifdef __WXWINCE__ - ExitThread(3); -#else - abort(); -#endif -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void wxDoLogFatalErrorWchar(const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogFatalError(format, argptr); - - // some compilers warn about unreachable code and it shouldn't matter - // for the others anyhow... - //va_end(argptr); -} -#endif // wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void wxDoLogFatalErrorUtf8(const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogFatalError(format, argptr); - - // some compilers warn about unreachable code and it shouldn't matter - // for the others anyhow... - //va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - -// same as info, but only if 'verbose' mode is on -void wxVLogVerbose(const wxString& format, va_list argptr) -{ - if ( wxLog::IsEnabled() ) { - if ( wxLog::GetActiveTarget() != NULL && wxLog::GetVerbose() ) - wxLog::OnLog(wxLOG_Info, wxString::FormatV(format, argptr)); - } -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void wxDoLogVerboseWchar(const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogVerbose(format, argptr); - va_end(argptr); -} -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void wxDoLogVerboseUtf8(const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogVerbose(format, argptr); - va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - -// ---------------------------------------------------------------------------- -// debug and trace functions -// ---------------------------------------------------------------------------- - -#if wxUSE_LOG_DEBUG - void wxVLogDebug(const wxString& format, va_list argptr) - { - if ( wxLog::IsEnabled() ) - { - wxLog::OnLog(wxLOG_Debug, wxString::FormatV(format, argptr)); - } - } - -#if !wxUSE_UTF8_LOCALE_ONLY - void wxDoLogDebugWchar(const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogDebug(format, argptr); - va_end(argptr); - } -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 - void wxDoLogDebugUtf8(const char *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogDebug(format, argptr); - va_end(argptr); - } -#endif // wxUSE_UNICODE_UTF8 -#endif // wxUSE_LOG_DEBUG - -#if wxUSE_LOG_TRACE - void wxVLogTrace(const wxString& mask, const wxString& format, va_list argptr) - { - if ( wxLog::IsEnabled() && wxLog::IsAllowedTraceMask(mask) ) { - wxString msg; - msg << wxS("(") << mask << wxS(") ") << wxString::FormatV(format, argptr); - - wxLog::OnLog(wxLOG_Trace, msg); - } - } - -#if !wxUSE_UTF8_LOCALE_ONLY - void wxDoLogTraceWchar(const wxString& mask, const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 - void wxDoLogTraceUtf8(const wxString& mask, const char *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } -#endif // wxUSE_UNICODE_UTF8 - -// deprecated (but not declared as such because we don't want to complicate -// DECLARE_LOG_FUNCTION macros even more) overloads for wxTraceMask -#if WXWIN_COMPATIBILITY_2_8 - void wxVLogTrace(wxTraceMask mask, const wxString& format, va_list argptr) - { - // we check that all of mask bits are set in the current mask, so - // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something - // if both bits are set. - if ( wxLog::IsEnabled() && ((wxLog::GetTraceMask() & mask) == mask) ) { - wxLog::OnLog(wxLOG_Trace, wxString::FormatV(format, argptr)); - } - } - -#if !wxUSE_UTF8_LOCALE_ONLY - void wxDoLogTraceWchar(wxTraceMask mask, const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 - void wxDoLogTraceUtf8(wxTraceMask mask, const char *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } -#endif // wxUSE_UNICODE_UTF8 - -#endif // WXWIN_COMPATIBILITY_2_8 - -#ifdef __WATCOMC__ -#if WXWIN_COMPATIBILITY_2_8 - // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 - void wxDoLogTraceWchar(int mask, const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } -#endif // WXWIN_COMPATIBILITY_2_8 - - void wxDoLogTraceWchar(const char *mask, const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } - - void wxDoLogTraceWchar(const wchar_t *mask, const wxChar *format, ...) - { - va_list argptr; - va_start(argptr, format); - wxVLogTrace(mask, format, argptr); - va_end(argptr); - } - -#if WXWIN_COMPATIBILITY_2_8 - void wxVLogTrace(int mask, const wxString& format, va_list argptr) - { wxVLogTrace((wxTraceMask)mask, format, argptr); } -#endif // WXWIN_COMPATIBILITY_2_8 - void wxVLogTrace(const char *mask, const wxString& format, va_list argptr) - { wxVLogTrace(wxString(mask), format, argptr); } - void wxVLogTrace(const wchar_t *mask, const wxString& format, va_list argptr) - { wxVLogTrace(wxString(mask), format, argptr); } -#endif // __WATCOMC__ -#endif // wxUSE_LOG_TRACE - - -// wxLogSysError: one uses the last error code, for other you must give it -// explicitly - -// return the system error message description -static inline wxString wxLogSysErrorHelper(long err) -{ - return wxString::Format(_(" (error %ld: %s)"), err, wxSysErrorMsg(err)); -} - -void WXDLLIMPEXP_BASE wxVLogSysError(const wxString& format, va_list argptr) -{ - wxVLogSysError(wxSysErrorCode(), format, argptr); -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void WXDLLIMPEXP_BASE wxDoLogSysErrorWchar(const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogSysError(format, argptr); - va_end(argptr); -} -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void WXDLLIMPEXP_BASE wxDoLogSysErrorUtf8(const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogSysError(format, argptr); - va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - -void WXDLLIMPEXP_BASE wxVLogSysError(long err, const wxString& format, va_list argptr) -{ - if ( wxLog::IsEnabled() ) - { - wxLog::OnLog(wxLOG_Error, - wxString::FormatV(format, argptr) + wxLogSysErrorHelper(err)); - } -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void WXDLLIMPEXP_BASE wxDoLogSysErrorWchar(long lErrCode, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogSysError(lErrCode, format, argptr); - va_end(argptr); -} -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void WXDLLIMPEXP_BASE wxDoLogSysErrorUtf8(long lErrCode, const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogSysError(lErrCode, format, argptr); - va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - -#ifdef __WATCOMC__ -// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 -void WXDLLIMPEXP_BASE wxDoLogSysErrorWchar(unsigned long lErrCode, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogSysError(lErrCode, format, argptr); - va_end(argptr); -} - -void WXDLLIMPEXP_BASE wxVLogSysError(unsigned long err, const wxString& format, va_list argptr) - { wxVLogSysError((long)err, format, argptr); } -#endif // __WATCOMC__ - // ---------------------------------------------------------------------------- // wxLog class implementation // ---------------------------------------------------------------------------- @@ -581,35 +223,65 @@ wxLog::OnLog(wxLogLevel level, const wxString& msg, const wxLogRecordInfo& info) { - if ( IsEnabled() && ms_logLevel >= level ) + // fatal errors can't be suppressed nor handled by the custom log target + // and always terminate the program + if ( level == wxLOG_FatalError ) { - wxLog *pLogger = GetActiveTarget(); - if ( pLogger ) - { - if ( GetRepetitionCounting() ) - { - wxCRIT_SECT_LOCKER(lock, GetPreviousLogCS()); + wxSafeShowMessage(wxS("Fatal Error"), msg); - if ( msg == gs_prevLog.msg ) - { - gs_prevLog.numRepeated++; - - // nothing else to do, in particular, don't log the - // repeated message - return; - } - - pLogger->LogLastRepeatIfNeededUnlocked(); - - // reset repetition counter for a new message - gs_prevLog.msg = msg; - gs_prevLog.level = level; - gs_prevLog.info = info; - } - - pLogger->DoLogRecord(level, msg, info); - } +#ifdef __WXWINCE__ + ExitThread(3); +#else + abort(); +#endif } + + wxLog *pLogger = GetActiveTarget(); + if ( !pLogger ) + return; + + if ( GetRepetitionCounting() ) + { + wxCRIT_SECT_LOCKER(lock, GetPreviousLogCS()); + + if ( msg == gs_prevLog.msg ) + { + gs_prevLog.numRepeated++; + + // nothing else to do, in particular, don't log the + // repeated message + return; + } + + pLogger->LogLastRepeatIfNeededUnlocked(); + + // reset repetition counter for a new message + gs_prevLog.msg = msg; + gs_prevLog.level = level; + gs_prevLog.info = info; + } + + // handle extra data which may be passed to us by wxLogXXX() + wxString prefix, suffix; + wxUIntPtr num; + if ( info.GetNumValue(wxLOG_KEY_SYS_ERROR_CODE, &num) ) + { + long err = static_cast(num); + if ( !err ) + err = wxSysErrorCode(); + + suffix.Printf(_(" (error %ld: %s)"), err, wxSysErrorMsg(err)); + } + +#if wxUSE_LOG_TRACE + wxString str; + if ( level == wxLOG_Trace && info.GetStrValue(wxLOG_KEY_TRACE_MASK, &str) ) + { + prefix = "(" + str + ") "; + } +#endif // wxUSE_LOG_TRACE + + pLogger->DoLogRecord(level, prefix + msg + suffix, info); } void wxLog::DoLogRecord(wxLogLevel level, diff --git a/src/common/msgout.cpp b/src/common/msgout.cpp index 6e9c57a558..0e663c40fc 100644 --- a/src/common/msgout.cpp +++ b/src/common/msgout.cpp @@ -176,7 +176,7 @@ void wxMessageOutputLog::Output(const wxString& str) out.Replace(wxT("\t"), wxT(" ")); - ::wxLogMessage(wxT("%s"), out.c_str()); + wxLogMessage(wxT("%s"), out.c_str()); } #endif // wxUSE_BASE diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 032b8f094e..000d89b464 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -819,7 +819,9 @@ void wxSocketBase::Init() // this Initialize() will be undone by wxSocketModule::OnExit(), all // the other calls to it should be matched by a call to Shutdown() if (!Initialize()) + { wxLogError("Cannot initialize wxSocketBase"); + } } } diff --git a/src/common/tarstrm.cpp b/src/common/tarstrm.cpp index 033c34cf09..0942b65236 100644 --- a/src/common/tarstrm.cpp +++ b/src/common/tarstrm.cpp @@ -793,7 +793,9 @@ wxStreamError wxTarInputStream::ReadHeaders() while (!done) { m_hdr->Read(*m_parent_i_stream); if (m_parent_i_stream->Eof()) + { wxLogError(_("incomplete header block in tar")); + } if (!*m_parent_i_stream) return wxSTREAM_READ_ERROR; m_offset += TAR_BLOCKSIZE; @@ -1040,7 +1042,9 @@ size_t wxTarInputStream::OnSysRead(void *buffer, size_t size) } else if (!m_parent_i_stream->IsOk()) { // any other error will have been reported by the underlying stream if (m_parent_i_stream->Eof()) + { wxLogError(_("unexpected end of file")); + } m_lasterror = wxSTREAM_READ_ERROR; } diff --git a/src/common/zipstrm.cpp b/src/common/zipstrm.cpp index e353d41986..17f698fb60 100644 --- a/src/common/zipstrm.cpp +++ b/src/common/zipstrm.cpp @@ -1269,7 +1269,9 @@ bool wxZipEndRec::Read(wxInputStream& stream, wxMBConv& conv) if (m_DiskNumber != 0 || m_StartDisk != 0 || m_EntriesHere != m_TotalEntries) + { wxLogWarning(_("assuming this is a multi-part zip concatenated")); + } return true; } diff --git a/src/common/zstream.cpp b/src/common/zstream.cpp index 57bed6a6a3..13b29c1782 100644 --- a/src/common/zstream.cpp +++ b/src/common/zstream.cpp @@ -224,7 +224,9 @@ size_t wxZlibInputStream::OnSysRead(void *buffer, size_t size) // by the parent strean, m_lasterror = wxSTREAM_READ_ERROR; if (m_parent_i_stream->Eof()) + { wxLogError(_("Can't read inflate stream: unexpected EOF in underlying stream.")); + } break; default: diff --git a/src/generic/logg.cpp b/src/generic/logg.cpp index 08f2808d7b..b4fe435373 100644 --- a/src/generic/logg.cpp +++ b/src/generic/logg.cpp @@ -201,60 +201,10 @@ static int OpenLogFile(wxFile& file, wxString *filename = NULL, wxWindow *parent #endif // CAN_SAVE_FILES -// ---------------------------------------------------------------------------- -// global variables -// ---------------------------------------------------------------------------- - -// we use a global variable to store the frame pointer for wxLogStatus - bad, -// but it's the easiest way -static wxFrame *gs_pFrame = NULL; // FIXME MT-unsafe - // ============================================================================ // implementation // ============================================================================ -// ---------------------------------------------------------------------------- -// global functions -// ---------------------------------------------------------------------------- - -// accepts an additional argument which tells to which frame the output should -// be directed -void wxVLogStatus(wxFrame *pFrame, const wxString& format, va_list argptr) -{ - wxString msg; - - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL ) - { - msg.PrintfV(format, argptr); - - wxASSERT( gs_pFrame == NULL ); // should be reset! - gs_pFrame = pFrame; - wxLog::OnLog(wxLOG_Status, msg); - gs_pFrame = NULL; - } -} - -#if !wxUSE_UTF8_LOCALE_ONLY -void wxDoLogStatusWchar(wxFrame *pFrame, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogStatus(pFrame, format, argptr); - va_end(argptr); -} -#endif // !wxUSE_UTF8_LOCALE_ONLY - -#if wxUSE_UNICODE_UTF8 -void wxDoLogStatusUtf8(wxFrame *pFrame, const char *format, ...) -{ - va_list argptr; - va_start(argptr, format); - wxVLogStatus(pFrame, format, argptr); - va_end(argptr); -} -#endif // wxUSE_UNICODE_UTF8 - // ---------------------------------------------------------------------------- // wxLogGui implementation (FIXME MT-unsafe) // ---------------------------------------------------------------------------- @@ -420,8 +370,16 @@ void wxLogGui::DoLogRecord(wxLogLevel level, case wxLOG_Status: #if wxUSE_STATUSBAR { + wxFrame *pFrame = NULL; + + // check if the frame was passed to us explicitly + wxUIntPtr ptr; + if ( info.GetNumValue(wxLOG_KEY_FRAME, &ptr) ) + { + pFrame = static_cast(wxUIntToPtr(ptr)); + } + // find the top window and set it's status text if it has any - wxFrame *pFrame = gs_pFrame; if ( pFrame == NULL ) { wxWindow *pWin = wxTheApp->GetTopWindow(); if ( pWin != NULL && pWin->IsKindOf(CLASSINFO(wxFrame)) ) { @@ -1080,7 +1038,9 @@ void wxLogDialog::OnSave(wxCommandEvent& WXUNUSED(event)) } if ( !rc || !file.Write(GetLogMessages()) || !file.Close() ) + { wxLogError(_("Can't save log contents to file.")); + } } #endif // CAN_SAVE_FILES diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 14b2bea6b7..60974b785a 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -2572,9 +2572,11 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column), wx_model->GetValue( value, item, cell->GetOwner()->GetModelColumn() ); if (value.GetType() != cell->GetVariantType()) + { wxLogError( wxT("Wrong type, required: %s but: %s"), value.GetType().c_str(), cell->GetVariantType().c_str() ); + } cell->SetValue( value ); diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 53853c6ef9..782856d81d 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -4671,7 +4671,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int s1 = selectionRange.GetStart()-1; int fragmentLen = s1 - r1 + 1; if (fragmentLen < 0) + { wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen); + } wxString stringFragment = str.Mid(r1 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); @@ -4702,7 +4704,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int fragmentLen = s2 - s1 + 1; if (fragmentLen < 0) + { wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen); + } wxString stringFragment = str.Mid(s1 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true); @@ -4733,7 +4737,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int fragmentLen = r2 - s2 + 1; if (fragmentLen < 0) + { wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen); + } wxString stringFragment = str.Mid(s2 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);