From 2523e9b70044baa92a1c63ffdfe179c28ad53536 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Thu, 26 Apr 2007 11:40:04 +0000 Subject: [PATCH] use UTF8-encoded char* strings in UTF8 build instead of wchar_t* if the current locale uses UTF8; fall back to widechar CRT functions in the locale is not UTF8 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45663 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/dcpsg.h | 10 +- include/wx/log.h | 146 ++++++--- include/wx/mimetype.h | 42 ++- include/wx/msgout.h | 14 +- include/wx/string.h | 260 +++++++++++----- include/wx/stringimpl.h | 5 +- include/wx/stringops.h | 2 + include/wx/strvararg.h | 590 ++++++++++++++++++++++++++++--------- include/wx/wx.h | 1 + include/wx/wxcrtvararg.h | 241 ++++++++++----- src/common/filesys.cpp | 10 +- src/common/fmapbase.cpp | 1 + src/common/ftp.cpp | 1 + src/common/http.cpp | 2 +- src/common/log.cpp | 106 +++++-- src/common/mimecmn.cpp | 23 +- src/common/msgout.cpp | 2 +- src/common/string.cpp | 60 +++- src/common/stringimpl.cpp | 2 - src/common/strvararg.cpp | 111 ++----- src/common/wxcrt.cpp | 258 ++++++++++++---- src/common/wxprintf.cpp | 71 ++--- src/generic/logg.cpp | 12 +- 23 files changed, 1341 insertions(+), 629 deletions(-) diff --git a/include/wx/generic/dcpsg.h b/include/wx/generic/dcpsg.h index 1958c18278..f1932134d8 100644 --- a/include/wx/generic/dcpsg.h +++ b/include/wx/generic/dcpsg.h @@ -86,12 +86,18 @@ public: static void SetResolution(int ppi); static int GetResolution(); - WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, DoPsPrintfFormat) + WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, 1, (const wxString&), DoPsPrintfFormat) +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, 1, (const char*), DoPsPrintfFormat) + WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, 1, (const wchar_t*), DoPsPrintfFormat) +#endif + void PsPrint( const wxString& psdata ); void PsPrint( int ch ); private: - void DoPsPrintfFormat(const wxChar *fmt, ... ); + void DoPsPrintfFormat(const wxString& fmt, ... ); static float ms_PSScaleFactor; diff --git a/include/wx/log.h b/include/wx/log.h index b280d7d309..0ed1ddbc62 100644 --- a/include/wx/log.h +++ b/include/wx/log.h @@ -471,39 +471,93 @@ WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); // define wxLog // ---------------------------------------------------------------------------- -#define DECLARE_LOG_FUNCTION_PUBLIC(level) \ - /* void wxLog##level(const wxChar *szFormat, ...); */ \ - WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, wxDoLog##level) +#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 -#define DECLARE_LOG_FUNCTION_IMPL(level) \ - extern void WXDLLIMPEXP_BASE wxVLog##level(const wxString& format, \ - va_list argptr); \ +#define DECLARE_LOG_FUNCTION(level) \ extern void WXDLLIMPEXP_BASE \ - wxDoLog##level(const wxChar *szFormat, ...) ATTRIBUTE_PRINTF_1 + wxDoLog##level(const wxString& format, ...); \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 1, (const wxString&), wxDoLog##level) \ + DECLARE_LOG_FUNCTION_WATCOM(level) \ + extern void WXDLLIMPEXP_BASE wxVLog##level(const wxString& format, \ + va_list 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_FUNCTION_WATCOM(level) \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 1, (const char*), wxDoLog##level) \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 1, (const wchar_t*), wxDoLog##level) \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 1, (const wxCStrData&), wxDoLog##level) +#else + #define DECLARE_LOG_FUNCTION_WATCOM(level) +#endif + -#define DECLARE_LOG_FUNCTION2_EXP_IMPL(level, argclass, arg, expdecl) \ +#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \ + extern void expdecl wxDoLog##level(argclass arg, \ + const wxString& format, ...); \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 2, (argclass, const wxString&), \ + wxDoLog##level) \ + DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl) \ extern void expdecl wxVLog##level(argclass arg, \ const wxString& format, \ - va_list argptr); \ - extern void expdecl wxDoLog##level(argclass arg, \ - const wxChar *szFormat, \ - ...) ATTRIBUTE_PRINTF_2 + va_list 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_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 2, (argclass, const char*), \ + wxDoLog##level) \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 2, (argclass, const wchar_t*), \ + wxDoLog##level) \ + WX_DEFINE_VARARG_FUNC_VOID(wxLog##level, \ + 2, (argclass, const wxCStrData&), \ + wxDoLog##level) +#else + #define DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl) +#endif + #else // !wxUSE_LOG // log functions do nothing at all -#define DECLARE_LOG_FUNCTION_PUBLIC(level) \ - /* void wxLog##level(const wxChar *szFormat, ...) {} */ \ - WX_DEFINE_VARARG_FUNC_NOP(wxLog##level) - -#define DECLARE_LOG_FUNCTION_IMPL(level) \ +#define DECLARE_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*)) \ + 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 wxString& WXUNUSED(format), \ - va_list WXUNUSED(argptr)) { } \ + va_list WXUNUSED(argptr)) { } \ -#define DECLARE_LOG_FUNCTION2_EXP_IMPL(level, argclass, arg, expdecl) \ +#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_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 wxString& WXUNUSED(format), \ - va_list WXUNUSED(argptr)) {} + const wxString& WXUNUSED(format), \ + va_list WXUNUSED(argptr)) {} + +#undef WX_WATCOM_ONLY_CODE // Empty Class to fake wxLogNull class WXDLLIMPEXP_BASE wxLogNull @@ -521,28 +575,13 @@ public: #endif // wxUSE_LOG/!wxUSE_LOG -#define DECLARE_LOG_FUNCTION(level) \ - DECLARE_LOG_FUNCTION_PUBLIC(level) \ - DECLARE_LOG_FUNCTION_IMPL(level) - -#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \ - DECLARE_LOG_FUNCTION_PUBLIC(level) \ - DECLARE_LOG_FUNCTION2_EXP_IMPL(level, argclass, arg, expdecl) - -#define DECLARE_LOG_FUNCTION2_EXP(level, argclass, arg, expdecl) \ - DECLARE_LOG_FUNCTION_PUBLIC(level) \ - DECLARE_LOG_FUNCTION2_EXP_IMPL(level, argclass, arg, expdecl) - -#define DECLARE_LOG_FUNCTION2_IMPL(level, argclass, arg) \ - DECLARE_LOG_FUNCTION2_EXP_IMPL(level, argclass, arg, WXDLLIMPEXP_BASE) - #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_IMPL: +// DECLARE_LOG_FUNCTION2: #if defined(__VISUALC__) && __VISUALC__ < 1300 - // "not enough actual parameters for macro 'DECLARE_LOG_FUNCTION2_EXP_IMPL'" + // "not enough actual parameters for macro 'DECLARE_LOG_FUNCTION2_EXP'" #pragma warning(disable:4003) #endif @@ -559,26 +598,26 @@ 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_IMPL(Status); +DECLARE_LOG_FUNCTION(Status); #if wxUSE_GUI // this one is the same as previous except that it allows to explicitly class WXDLLEXPORT wxFrame; // specify the frame to which the output should go - DECLARE_LOG_FUNCTION2_EXP_IMPL(Status, wxFrame *, pFrame, WXDLLIMPEXP_CORE); + DECLARE_LOG_FUNCTION2_EXP(Status, wxFrame *, pFrame, WXDLLIMPEXP_CORE); #endif // wxUSE_GUI -DECLARE_LOG_FUNCTION_PUBLIC(Status) - // additional one: as wxLogError, but also logs last system call error code // and the corresponding error message if available -DECLARE_LOG_FUNCTION_IMPL(SysError); +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_IMPL(SysError, long, lErrCode); - -DECLARE_LOG_FUNCTION_PUBLIC(SysError) +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 do nothing in release mode #if wxUSE_LOG && wxUSE_LOG_DEBUG @@ -590,12 +629,21 @@ DECLARE_LOG_FUNCTION_PUBLIC(SysError) // this version only logs the message if the mask had been added to the // list of masks with AddTraceMask() - DECLARE_LOG_FUNCTION2_IMPL(Trace, const wxString&, mask); + 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 - DECLARE_LOG_FUNCTION2_IMPL(Trace, wxTraceMask, mask); - DECLARE_LOG_FUNCTION_PUBLIC(Trace) + 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 diff --git a/include/wx/mimetype.h b/include/wx/mimetype.h index 3c99c2c621..2a38d413ca 100644 --- a/include/wx/mimetype.h +++ b/include/wx/mimetype.h @@ -116,16 +116,44 @@ private: class WXDLLIMPEXP_BASE wxFileTypeInfo { +private: + void VarArgInit(const wxString& mimeType, + const wxString& openCmd, + const wxString& printCmd, + const wxString& desc, + // the other parameters form a NULL terminated list of + // extensions + ...); public: // ctors // a normal item - wxFileTypeInfo(const wxChar *mimeType, - const wxChar *openCmd, - const wxChar *printCmd, - const wxChar *desc, - // the other parameters form a NULL terminated list of - // extensions - ...); + + // wxFileTypeInfo(const wxString& mimeType, + // const wxString& openCmd, + // const wxString& printCmd, + // const wxString& desc, + // // the other parameters form a NULL terminated list of + // // extensions + // ...); + WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo, + 4, (const wxString&, const wxString&, + const wxString&, const wxString&), + VarArgInit) +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo, + 4, (const char*, const char*, + const char*, const char*), + VarArgInit) + WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo, + 4, (const wchar_t*, const wchar_t*, + const wchar_t*, const wchar_t*), + VarArgInit) + WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo, + 4, (const wxCStrData&, const wxCStrData&, + const wxCStrData&, const wxCStrData&), + VarArgInit) +#endif // the array elements correspond to the parameters of the ctor above in // the same order diff --git a/include/wx/msgout.h b/include/wx/msgout.h index ba377c079c..f48232752a 100755 --- a/include/wx/msgout.h +++ b/include/wx/msgout.h @@ -36,13 +36,19 @@ public: virtual ~wxMessageOutputBase() { } // show a message to the user - // void Printf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2 = 0; - WX_DEFINE_VARARG_FUNC_VOID(Printf, DoPrintf) + // void Printf(const wxString& format, ...) = 0; + WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxString&), DoPrintf) +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const char*), DoPrintf) + WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wchar_t*), DoPrintf) + WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxCStrData&), DoPrintf) +#endif protected: // NB: this is pure virtual so that it can be implemented in dllexported // wxMessagOutput class - virtual void DoPrintf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2 = 0; + virtual void DoPrintf(const wxString& format, ...) = 0; // called by DoPrintf() to output formatted string virtual void Output(const wxString& str) = 0; @@ -67,7 +73,7 @@ public: static wxMessageOutput* Set(wxMessageOutput* msgout); protected: - virtual void DoPrintf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2; + virtual void DoPrintf(const wxString& format, ...); virtual void Output(const wxString& str) = 0; private: diff --git a/include/wx/string.h b/include/wx/string.h index 83ca3c62ee..476af64419 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -51,7 +51,7 @@ #include #endif -#include "wx/wxchar.h" // for wxChar, wxStrlen() etc. +#include "wx/wxcrt.h" // for wxChar, wxStrlen() etc. #include "wx/strvararg.h" #include "wx/buffer.h" // for wxCharBuffer #include "wx/strconv.h" // for wxConvertXXX() macros and wxMBConv classes @@ -216,6 +216,10 @@ public: inline wxString AsString() const; + // returns the value as C string in internal representation (equivalent + // to AsString().wx_str(), but more efficient) + const wxStringCharType *AsInternal() const; + // allow expressions like "c_str()[0]": inline wxUniChar operator[](size_t n) const; wxUniChar operator[](int n) const { return operator[](size_t(n)); } @@ -292,8 +296,8 @@ class WXDLLIMPEXP_BASE wxStringPrintfMixinBase protected: wxStringPrintfMixinBase() {} - int DoPrintf(const wxChar *format, ...) ATTRIBUTE_PRINTF_2; - static wxString DoFormat(const wxChar *format, ...) ATTRIBUTE_PRINTF_1; + int DoPrintf(const wxString& format, ...); + static wxString DoFormat(const wxString& format, ...); }; // this class contains template wrappers for wxString's vararg methods, it's @@ -316,13 +320,27 @@ public: // these are duplicated wxString methods, they're also declared below // if !wxNEEDS_WXSTRING_PRINTF_MIXIN: - // int Printf(const wxChar *pszFormat, ...); - WX_DEFINE_VARARG_FUNC(int, Printf, DoPrintf) - // static wxString Format(const wxChar *pszFormat, ...) ATTRIBUTE_PRINTF_1; - WX_DEFINE_VARARG_FUNC(static typename StringReturnType::type, - Format, DoFormat) - // int sprintf(const wxChar *pszFormat, ...) ATTRIBUTE_PRINTF_2; - WX_DEFINE_VARARG_FUNC(int, sprintf, DoPrintf) + // static wxString Format(const wString& format, ...) ATTRIBUTE_PRINTF_1; + WX_DEFINE_VARARG_FUNC2_SANS_N0(static typename StringReturnType::type, + Format, 1, (const wxString&), + DoFormat, DoFormat) + // We have to implement the version without template arguments manually + // because of the StringReturnType<> hack, although WX_DEFINE_VARARG_FUNC + // normally does it itself. It has to be a template so that we can use + // the hack, even though there's no real template parameter: + struct FormatDummyArg {} ; + + template + inline static typename StringReturnType::type + Format(const wxString& fmt, FormatDummyArg dummy = FormatDummyArg()) + { + return DoFormat(fmt); + } + + // int Printf(const wxString& format, ...); + WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxString&), DoPrintf) + // int sprintf(const wxString& format, ...) ATTRIBUTE_PRINTF_2; + WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxString&), DoPrintf) protected: wxStringPrintfMixin() : wxStringPrintfMixinBase() {} @@ -879,7 +897,6 @@ public: // libstdc++ on some Linux versions which is bad, so instead we ask the // client code to define this wxUSE_STD_STRING symbol if they need it #if wxUSE_STD_STRING - #if wxUSE_UNICODE_WCHAR wxString(const wxStdWideString& str) : m_impl(str) {} #else // UTF-8 or ANSI @@ -1484,16 +1501,27 @@ public: // formatted input/output // as sprintf(), returns the number of characters written or < 0 on error // (take 'this' into account in attribute parameter count) - // int Printf(const wxChar *pszFormat, ...); - WX_DEFINE_VARARG_FUNC(int, Printf, DoPrintf) + // int Printf(const wxString& format, ...); + WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxString&), DoPrintf) +#ifdef __WATCOMC__ + WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const char*), DoPrintf) + WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wchar_t*), DoPrintf) + WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxCStrData&), DoPrintf) +#endif #endif // !wxNEEDS_WXSTRING_PRINTF_MIXIN // as vprintf(), returns the number of characters written or < 0 on error int PrintfV(const wxString& format, va_list argptr); #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN // returns the string containing the result of Printf() to it - // static wxString Format(const wxChar *pszFormat, ...) ATTRIBUTE_PRINTF_1; - WX_DEFINE_VARARG_FUNC(static wxString, Format, DoFormat) + // static wxString Format(const wxString& format, ...) ATTRIBUTE_PRINTF_1; + WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxString&), DoFormat) +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const char*), DoFormat) + WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wchar_t*), DoFormat) + WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxCStrData&), DoFormat) +#endif #endif // the same as above, but takes a va_list static wxString FormatV(const wxString& format, va_list argptr); @@ -1529,8 +1557,14 @@ public: #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN // use Printf() // (take 'this' into account in attribute parameter count) - // int sprintf(const wxChar *pszFormat, ...) ATTRIBUTE_PRINTF_2; - WX_DEFINE_VARARG_FUNC(int, sprintf, DoPrintf) + // int sprintf(const wxString& format, ...) ATTRIBUTE_PRINTF_2; + WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxString&), DoPrintf) +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const char*), DoPrintf) + WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wchar_t*), DoPrintf) + WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxCStrData&), DoPrintf) +#endif #endif // wxNEEDS_WXSTRING_PRINTF_MIXIN // use Cmp() @@ -2200,7 +2234,7 @@ public: wxString& operator+=(wchar_t ch) { return *this += wxUniChar(ch); } private: -#if !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 +#if !wxUSE_STL_BASED_WXSTRING // helpers for wxStringBuffer and wxStringBufferLength wxStringCharType *DoGetWriteBuf(size_t nLen) { return m_impl.DoGetWriteBuf(nLen); } @@ -2208,14 +2242,11 @@ private: { m_impl.DoUngetWriteBuf(); } void DoUngetWriteBuf(size_t nLen) { m_impl.DoUngetWriteBuf(nLen); } - - friend class WXDLLIMPEXP_BASE wxStringBuffer; - friend class WXDLLIMPEXP_BASE wxStringBufferLength; -#endif // !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 +#endif // !wxUSE_STL_BASED_WXSTRING #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN - int DoPrintf(const wxChar *format, ...) ATTRIBUTE_PRINTF_2; - static wxString DoFormat(const wxChar *format, ...) ATTRIBUTE_PRINTF_1; + int DoPrintf(const wxString& format, ...); + static wxString DoFormat(const wxString& format, ...); #endif #if !wxUSE_STL_BASED_WXSTRING @@ -2253,7 +2284,10 @@ private: #if !wxUSE_UNICODE_WCHAR ConvertedBuffer m_convertedToWChar; #endif + friend class WXDLLIMPEXP_BASE wxCStrData; + friend class wxImplStringBuffer; + friend class wxImplStringBufferLength; }; #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN @@ -2321,107 +2355,170 @@ inline wxString operator+(wchar_t ch, const wxString& string) // wxStringBuffer: a tiny class allowing to get a writable pointer into string // ---------------------------------------------------------------------------- -#if wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8 +#if !wxUSE_STL_BASED_WXSTRING +// string buffer for direct access to string data in their native +// representation: +class wxImplStringBuffer +{ +public: + typedef wxStringCharType CharType; + + wxImplStringBuffer(wxString& str, size_t lenWanted = 1024) + : m_str(str), m_buf(NULL) + { m_buf = m_str.DoGetWriteBuf(lenWanted); } + + ~wxImplStringBuffer() { m_str.DoUngetWriteBuf(); } + + operator wxStringCharType*() const { return m_buf; } -class WXDLLIMPEXP_BASE wxStringBuffer +private: + wxString& m_str; + wxStringCharType *m_buf; + + DECLARE_NO_COPY_CLASS(wxImplStringBuffer) +}; + +class wxImplStringBufferLength { public: - wxStringBuffer(wxString& str, size_t lenWanted = 1024) + typedef wxStringCharType CharType; + + wxImplStringBufferLength(wxString& str, size_t lenWanted = 1024) + : m_str(str), m_buf(NULL), m_len(0), m_lenSet(false) + { + m_buf = m_str.DoGetWriteBuf(lenWanted); + wxASSERT(m_buf != NULL); + } + + ~wxImplStringBufferLength() + { + wxASSERT(m_lenSet); + m_str.DoUngetWriteBuf(m_len); + } + + operator wxStringCharType*() const { return m_buf; } + void SetLength(size_t length) { m_len = length; m_lenSet = true; } + +private: + wxString& m_str; + wxStringCharType *m_buf; + size_t m_len; + bool m_lenSet; + + DECLARE_NO_COPY_CLASS(wxImplStringBufferLength) +}; + +#endif // !wxUSE_STL_BASED_WXSTRING + +template +class wxStringTypeBufferBase +{ +public: + typedef T CharType; + + wxStringTypeBufferBase(wxString& str, size_t lenWanted = 1024) : m_str(str), m_buf(lenWanted) { } - ~wxStringBuffer() { m_str.assign(m_buf.data(), wxStrlen(m_buf.data())); } - operator wxChar*() { return m_buf.data(); } + operator CharType*() { return m_buf.data(); } -private: +protected: wxString& m_str; -#if wxUSE_UNICODE - wxWCharBuffer m_buf; -#else - wxCharBuffer m_buf; -#endif - - DECLARE_NO_COPY_CLASS(wxStringBuffer) + wxCharTypeBuffer m_buf; }; -class WXDLLIMPEXP_BASE wxStringBufferLength +template +class wxStringTypeBufferLengthBase { public: - wxStringBufferLength(wxString& str, size_t lenWanted = 1024) + typedef T CharType; + + wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024) : m_str(str), m_buf(lenWanted), m_len(0), m_lenSet(false) { } - ~wxStringBufferLength() + ~wxStringTypeBufferLengthBase() { wxASSERT(m_lenSet); m_str.assign(m_buf.data(), m_len); } - operator wxChar*() { return m_buf.data(); } + operator CharType*() { return m_buf.data(); } void SetLength(size_t length) { m_len = length; m_lenSet = true; } -private: +protected: wxString& m_str; -#if wxUSE_UNICODE - wxWCharBuffer m_buf; -#else - wxCharBuffer m_buf; -#endif + wxCharTypeBuffer m_buf; size_t m_len; bool m_lenSet; - - DECLARE_NO_COPY_CLASS(wxStringBufferLength) }; -#else // if !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 +template +class wxStringTypeBuffer : public wxStringTypeBufferBase +{ +public: + wxStringTypeBuffer(wxString& str, size_t lenWanted = 1024) + : wxStringTypeBufferBase(str, lenWanted) {} + ~wxStringTypeBuffer() + { + this->m_str.assign(this->m_buf.data()); + } -class WXDLLIMPEXP_BASE wxStringBuffer + DECLARE_NO_COPY_CLASS(wxStringTypeBuffer) +}; + +template +class wxStringTypeBufferLength : public wxStringTypeBufferLengthBase { public: - wxStringBuffer(wxString& str, size_t lenWanted = 1024) - : m_str(str), m_buf(NULL) - { m_buf = m_str.DoGetWriteBuf(lenWanted); } + wxStringTypeBufferLength(wxString& str, size_t lenWanted = 1024) + : wxStringTypeBufferLengthBase(str, lenWanted) {} - ~wxStringBuffer() { m_str.DoUngetWriteBuf(); } + ~wxStringTypeBufferLength() + { + wxASSERT(this->m_lenSet); + this->m_str.assign(this->m_buf.data(), this->m_len); + } - operator wxChar*() const { return m_buf; } + DECLARE_NO_COPY_CLASS(wxStringTypeBufferLength) +}; -private: - wxString& m_str; - wxChar *m_buf; +#if wxUSE_STL_BASED_WXSTRING +class wxImplStringBuffer : public wxStringTypeBufferBase +{ +public: + wxImplStringBuffer(wxString& str, size_t lenWanted = 1024) + : wxStringTypeBufferBase(str, lenWanted) {} + ~wxImplStringBuffer() + { m_str.m_impl.assign(m_buf.data()); } - DECLARE_NO_COPY_CLASS(wxStringBuffer) + DECLARE_NO_COPY_CLASS(wxImplStringBuffer) }; -class WXDLLIMPEXP_BASE wxStringBufferLength +class wxImplStringBufferLength : public wxStringTypeBufferLengthBase { public: - wxStringBufferLength(wxString& str, size_t lenWanted = 1024) - : m_str(str), m_buf(NULL), m_len(0), m_lenSet(false) - { - m_buf = m_str.DoGetWriteBuf(lenWanted); - wxASSERT(m_buf != NULL); - } + wxImplStringBufferLength(wxString& str, size_t lenWanted = 1024) + : wxStringTypeBufferLengthBase(str, lenWanted) {} - ~wxStringBufferLength() + ~wxImplStringBufferLength() { wxASSERT(m_lenSet); - m_str.DoUngetWriteBuf(m_len); + m_str.m_impl.assign(m_buf.data(), m_len); } - operator wxChar*() const { return m_buf; } - void SetLength(size_t length) { m_len = length; m_lenSet = true; } - -private: - wxString& m_str; - wxChar *m_buf; - size_t m_len; - bool m_lenSet; - - DECLARE_NO_COPY_CLASS(wxStringBufferLength) + DECLARE_NO_COPY_CLASS(wxImplStringBufferLength) }; +#endif // wxUSE_STL_BASED_WXSTRING + +#if wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8 +typedef wxStringTypeBuffer wxStringBuffer; +typedef wxStringTypeBufferLength wxStringBufferLength; +#else // if !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 +typedef wxImplStringBuffer wxStringBuffer; +typedef wxImplStringBufferLength wxStringBufferLength; #endif // !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 // --------------------------------------------------------------------------- @@ -2600,6 +2697,11 @@ inline wxString wxCStrData::AsString() const return m_str->Mid(m_offset); } +inline const wxStringCharType *wxCStrData::AsInternal() const +{ + return wxStringOperations::AddToIter(m_str->wx_str(), m_offset); +} + inline wxUniChar wxCStrData::operator*() const { if ( m_str->empty() ) diff --git a/include/wx/stringimpl.h b/include/wx/stringimpl.h index 1b3f172c94..a3f82ca74f 100644 --- a/include/wx/stringimpl.h +++ b/include/wx/stringimpl.h @@ -23,7 +23,8 @@ // ---------------------------------------------------------------------------- #include "wx/defs.h" // everybody should include this -#include "wx/wxchar.h" // for wxChar, wxStrlen() etc. +#include "wx/chartype.h" // for wxChar +#include "wx/wxcrt.h" // for wxStrlen() etc. #include @@ -540,12 +541,10 @@ public: // string += char wxStringImpl& operator+=(wxStringCharType ch) { return append(1, ch); } -#if !wxUSE_UNICODE_UTF8 // helpers for wxStringBuffer and wxStringBufferLength wxStringCharType *DoGetWriteBuf(size_t nLen); void DoUngetWriteBuf(); void DoUngetWriteBuf(size_t nLen); -#endif private: #if wxUSE_UNICODE_UTF8 diff --git a/include/wx/stringops.h b/include/wx/stringops.h index 6451275bb1..972b832717 100644 --- a/include/wx/stringops.h +++ b/include/wx/stringops.h @@ -39,6 +39,8 @@ struct WXDLLIMPEXP_BASE wxStringOperationsWchar { return i + n; } static wxStringImpl::const_iterator AddToIter(const wxStringImpl::const_iterator& i, int n) { return i + n; } + static const wxChar* AddToIter(const wxChar *i, int n) + { return i + n; } // returns distance of the two iterators in Unicode characters static int DiffIters(const wxStringImpl::iterator& i1, diff --git a/include/wx/strvararg.h b/include/wx/strvararg.h index 55eb9c01f2..459c0ffeec 100644 --- a/include/wx/strvararg.h +++ b/include/wx/strvararg.h @@ -16,13 +16,14 @@ #error "OpenWatcom version >= 1.4 is required to compile this code" #endif +#include "wx/cpp.h" #include "wx/chartype.h" +#include "wx/wxcrt.h" +#include "wx/strconv.h" +#include "wx/buffer.h" class WXDLLIMPEXP_BASE wxCStrData; class WXDLLIMPEXP_BASE wxString; -class WXDLLIMPEXP_BASE wxCharBuffer; -class WXDLLIMPEXP_BASE wxWCharBuffer; - // ---------------------------------------------------------------------------- // WX_DEFINE_VARARG_FUNC* macros @@ -35,40 +36,86 @@ class WXDLLIMPEXP_BASE wxWCharBuffer; // // This is done by defining a set of N template function taking 1..N arguments // (currently, N is set to 30 in this header). These functions are just thin -// wrappers around another variadic function (@a impl) and the only thing -// the wrapper does is that it normalizes the arguments passed in so that -// they are of the type expected by variadic functions taking string -// arguments, i.e., char* or wchar_t*, depending on the build: +// wrappers around another variadic function ('impl' or 'implUtf8' arguments, +// see below) and the only thing the wrapper does is that it normalizes the +// arguments passed in so that they are of the type expected by variadic +// functions taking string arguments, i.e., char* or wchar_t*, depending on the +// build: // * char* in the current locale's charset in ANSI build -// * whchar_t* in the Unicode build +// * char* with UTF-8 encoding if wxUSE_UNICODE_UTF8 and the app is running +// under an UTF-8 locale +// * wchar_t* if wxUSE_UNICODE_WCHAR or if wxUSE_UNICODE_UTF8 and the current +// locale is not UTF-8 // // Parameters: -// rettype Functions' return type. -// name Name of the function. -// impl Name of the variadic function that implements 'name'. -#define WX_DEFINE_VARARG_FUNC(rettype, name, impl) \ - _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ - _WX_VARARG_DEFINE_FUNC, \ - rettype, name, impl) - -// Like WX_DEFINE_VARARG_FUNC, but for variadic functions that don't return +// [ there are examples in square brackets showing values of the parameters +// for the wxFprintf() wrapper for fprintf() function with the following +// prototype: +// int wxFprintf(FILE *stream, const wxString& format, ...); ] +// +// rettype Functions' return type [int] +// name Name of the function [fprintf] +// numfixed The number of leading "fixed" (i.e., not variadic) +// arguments of the function (e.g. "stream" and "format" +// arguments of fprintf()); their type is _not_ converted +// using wxArgNormalizer, unlike the rest of +// the function's arguments [2] +// fixed List of types of the leading "fixed" arguments, in +// parenthesis [(FILE*,const wxString&)] +// impl Name of the variadic function that implements 'name' for +// the native strings representation (wchar_t* if +// wxUSE_UNICODE_WCHAR or wxUSE_UNICODE_UTF8 when running under +// non-UTF8 locale, char* in ANSI build) [wxCrt_Fprintf] +// implUtf8 Like 'impl', but for the UTF-8 char* version to be used +// if wxUSE_UNICODE_UTF8 and running under UTF-8 locale +// (ignored otherwise) [fprintf] +// +#define WX_DEFINE_VARARG_FUNC2(rettype, name, numfixed, fixed, impl, implUtf8)\ + _WX_VARARG_DEFINE_FUNC_N0(rettype, name, impl, implUtf8, numfixed, fixed) \ + WX_DEFINE_VARARG_FUNC2_SANS_N0(rettype, name, numfixed, fixed, impl, implUtf8) + +// ditto, but without the version with 0 template/vararg arguments +#define WX_DEFINE_VARARG_FUNC2_SANS_N0(rettype, name, \ + numfixed, fixed, impl, implUtf8) \ + _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ + _WX_VARARG_DEFINE_FUNC, \ + rettype, name, impl, implUtf8, numfixed, fixed) + +// like WX_DEFINE_VARARG_FUNC2, but for impl=implUtf8: +#define WX_DEFINE_VARARG_FUNC(rettype, name, numfixed, fixed, impl) \ + WX_DEFINE_VARARG_FUNC2(rettype, name, numfixed, fixed, impl, impl) + +// Like WX_DEFINE_VARARG_FUNC2, but for variadic functions that don't return // a value. -#define WX_DEFINE_VARARG_FUNC_VOID(name, impl) \ - _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ - _WX_VARARG_DEFINE_FUNC_VOID, \ - void, name, impl) +#define WX_DEFINE_VARARG_FUNC_VOID2(name, numfixed, fixed, impl, implUtf8) \ + _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ + _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ + _WX_VARARG_DEFINE_FUNC_VOID, \ + void, name, impl, implUtf8, numfixed, fixed) + +// like WX_DEFINE_VARARG_FUNC_VOID2, but for impl=implUtf8: +#define WX_DEFINE_VARARG_FUNC_VOID(name, numfixed, fixed, impl) \ + WX_DEFINE_VARARG_FUNC_VOID2(name, numfixed, fixed, impl, impl) // Like WX_DEFINE_VARARG_FUNC_VOID, but instead of wrapping an implementation // function, does nothing in defined functions' bodies. // // Used to implement wxLogXXX functions if wxUSE_LOG=0. -#define WX_DEFINE_VARARG_FUNC_NOP(name) \ - _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ - _WX_VARARG_DEFINE_FUNC_NOP, \ - void, name, dummy) +#define WX_DEFINE_VARARG_FUNC_NOP(name, numfixed, fixed) \ + _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ + _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ + _WX_VARARG_DEFINE_FUNC_NOP, \ + void, name, dummy, numfixed, fixed) + +// Like WX_DEFINE_VARARG_FUNC_CTOR, but for defining template constructors +#define WX_DEFINE_VARARG_FUNC_CTOR(name, numfixed, fixed, impl) \ + _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, impl, numfixed, fixed) \ + _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \ + _WX_VARARG_DEFINE_FUNC_CTOR, \ + void, name, impl, impl, numfixed, fixed) // ---------------------------------------------------------------------------- -// implementation +// wxArgNormalizer* converters // ---------------------------------------------------------------------------- // Converts an argument passed to wxPrint etc. into standard form expected, @@ -87,122 +134,236 @@ struct wxArgNormalizer const T& m_value; }; +// normalizer for passing arguments to functions working with wchar_t* (and +// until ANSI build is removed, char* in ANSI build as well - FIXME-UTF8) +// string representation +#if !wxUSE_UTF8_LOCALE_ONLY +template +struct wxArgNormalizerWchar : public wxArgNormalizer +{ + wxArgNormalizerWchar(const T& value) : wxArgNormalizer(value) {} +}; +#endif // !wxUSE_UTF8_LOCALE_ONLY + +// normalizer for passing arguments to functions working with UTF-8 encoded +// char* strings +#if wxUSE_UNICODE_UTF8 + template + struct wxArgNormalizerUtf8 : public wxArgNormalizer + { + wxArgNormalizerUtf8(const T& value) : wxArgNormalizer(value) {} + }; + + #define wxArgNormalizerNative wxArgNormalizerUtf8 +#else // wxUSE_UNICODE_WCHAR + #define wxArgNormalizerNative wxArgNormalizerWchar +#endif // wxUSE_UNICODE_UTF8 // wxUSE_UNICODE_UTF8 + + + // special cases for converting strings: -template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer + +// base class for wxArgNormalizer specializations that need to do conversion; +// CharType is either wxStringCharType or wchar_t in UTF-8 build when wrapping +// widechar CRT function +template +struct wxArgNormalizerWithBuffer { - wxArgNormalizer(const wxCStrData& value) : m_value(value) {} - const wxChar *get() const; // FIXME-UTF8: should be wxStringCharType + typedef wxCharTypeBuffer CharBuffer; - const wxCStrData& m_value; -}; + wxArgNormalizerWithBuffer() {} + wxArgNormalizerWithBuffer(const CharBuffer& buf) : m_value(buf) {} -template<> -struct wxArgNormalizer : public wxArgNormalizer -{ - wxArgNormalizer(const wxCStrData& value) - : wxArgNormalizer(value) {} + const CharType *get() const { return m_value; } + + CharBuffer m_value; }; +// string objects: template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer +struct WXDLLIMPEXP_BASE wxArgNormalizerNative { - wxArgNormalizer(const wxString& value) : m_value(value) {} - const wxChar *get() const; // FIXME-UTF8: should be wxStringCharType + wxArgNormalizerNative(const wxString& s) : m_value(s) {} + const wxStringCharType *get() const; const wxString& m_value; }; +// c_str() values: template<> -struct wxArgNormalizer : public wxArgNormalizer +struct WXDLLIMPEXP_BASE wxArgNormalizerNative { - wxArgNormalizer(const wxString& value) - : wxArgNormalizer(value) {} + wxArgNormalizerNative(const wxCStrData& value) : m_value(value) {} + const wxStringCharType *get() const; + + const wxCStrData& m_value; }; -#if wxUSE_UNICODE // FIXME-UTF8: should be wxUSE_UNICODE_WCHAR +// wxString/wxCStrData conversion to wchar_t* value +#if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer +struct WXDLLIMPEXP_BASE wxArgNormalizerWchar + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(const char *value); - ~wxArgNormalizer(); - const wchar_t *get() const; - - wxWCharBuffer *m_value; + wxArgNormalizerWchar(const wxString& s); }; template<> -struct wxArgNormalizer : public wxArgNormalizer +struct WXDLLIMPEXP_BASE wxArgNormalizerWchar + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(char *value) - : wxArgNormalizer(value) {} + wxArgNormalizerWchar(const wxCStrData& s); }; -#endif // wxUSE_UNICODE_WCHAR +#endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY + + +// C string pointers of the wrong type (wchar_t* for ANSI or UTF8 build, +// char* for wchar_t Unicode build or UTF8): +#if wxUSE_UNICODE_WCHAR -// FIXME-UTF8 -#if 0 // wxUSE_UNICODE_UTF8 -// for conversion from local charset to UTF-8 template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer +struct wxArgNormalizerWchar + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(const char *value); - ~wxArgNormalizer(); - const char *get() const; - - wxCharBuffer *m_value; + wxArgNormalizerWchar(const char* s) + : wxArgNormalizerWithBuffer(wxConvLibc.cMB2WC(s)) {} }; +#elif wxUSE_UNICODE_UTF8 + template<> -struct wxArgNormalizer : public wxArgNormalizer +struct wxArgNormalizerUtf8 + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(char *value) - : wxArgNormalizer(value) {} + wxArgNormalizerUtf8(const wchar_t* s) + : wxArgNormalizerWithBuffer(wxConvUTF8.cWC2MB(s)) {} }; -#endif // wxUSE_UNICODE_UTF8 -#if /*wxUSE_UNICODE_UTF8 || */ !wxUSE_UNICODE // FIXME-UTF8 template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer +struct wxArgNormalizerUtf8 + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(const wchar_t *value); - ~wxArgNormalizer(); - const char *get() const; + wxArgNormalizerUtf8(const char* s) + { + // FIXME-UTF8: optimize this if current locale is UTF-8 one + + // convert to widechar string first: + wxWCharBuffer buf(wxConvLibc.cMB2WC(s)); - wxCharBuffer *m_value; + // then to UTF-8: + if ( buf ) + m_value = wxConvUTF8.cWC2MB(buf); + } }; +// UTF-8 build needs conversion to wchar_t* too: +#if !wxUSE_UTF8_LOCALE_ONLY template<> -struct wxArgNormalizer : public wxArgNormalizer +struct wxArgNormalizerWchar + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(wchar_t *value) - : wxArgNormalizer(value) {} + wxArgNormalizerWchar(const char* s) + : wxArgNormalizerWithBuffer(wxConvLibc.cMB2WC(s)) {} }; -#endif // wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE +#endif // !wxUSE_UTF8_LOCALE_ONLY + +#else // ANSI - FIXME-UTF8 -// versions for passing wx[W]CharBuffer: template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer - : public wxArgNormalizer +struct wxArgNormalizerWchar + : public wxArgNormalizerWithBuffer { - wxArgNormalizer(const wxCharBuffer& buf); + wxArgNormalizerWchar(const wchar_t* s) + : wxArgNormalizerWithBuffer(wxConvLibc.cWC2MB(s)) {} }; -template<> -struct WXDLLIMPEXP_BASE wxArgNormalizer - : public wxArgNormalizer +#endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8/ANSI + + +// this macro is used to implement specialization that are exactly same as +// some other specialization, i.e. to "forward" the implementation (e.g. for +// T=wxString and T=const wxString&). Note that the ctor takes BaseT argument, +// not T! +#if wxUSE_UNICODE_UTF8 + #if wxUSE_UTF8_LOCALE_ONLY + #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ + _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) + #else // possibly non-UTF8 locales + #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ + _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT); \ + _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerUtf8, T, BaseT) + #endif +#else // wxUSE_UNICODE_WCHAR + #define WX_ARG_NORMALIZER_FORWARD(T, BaseT) \ + _WX_ARG_NORMALIZER_FORWARD_IMPL(wxArgNormalizerWchar, T, BaseT) +#endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR + +#define _WX_ARG_NORMALIZER_FORWARD_IMPL(Normalizer, T, BaseT) \ + template<> \ + struct Normalizer : public Normalizer \ + { \ + Normalizer(BaseT value) : Normalizer(value) {} \ + } + +// non-reference versions of specializations for string objects +WX_ARG_NORMALIZER_FORWARD(wxString, const wxString&); +WX_ARG_NORMALIZER_FORWARD(wxCStrData, const wxCStrData&); + +// versions for passing non-const pointers: +WX_ARG_NORMALIZER_FORWARD(char*, const char*); +WX_ARG_NORMALIZER_FORWARD(wchar_t*, const wchar_t*); + +// versions for passing wx[W]CharBuffer: +WX_ARG_NORMALIZER_FORWARD(wxCharBuffer, const char*); +WX_ARG_NORMALIZER_FORWARD(const wxCharBuffer&, const char*); +WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*); +WX_ARG_NORMALIZER_FORWARD(const wxWCharBuffer&, const wchar_t*); + +#undef WX_ARG_NORMALIZER_FORWARD +#undef _WX_ARG_NORMALIZER_FORWARD_IMPL + +// ---------------------------------------------------------------------------- +// WX_VA_ARG_STRING +// ---------------------------------------------------------------------------- + +// Replacement for va_arg() for use with strings in functions that accept +// strings normalized by wxArgNormalizer: + +struct WXDLLIMPEXP_BASE wxArgNormalizedString { - wxArgNormalizer(const wxWCharBuffer& buf); + wxArgNormalizedString(const void* ptr) : m_ptr(ptr) {} + + // returns true if non-NULL string was passed in + bool IsValid() const { return m_ptr != NULL; } + operator bool() const { return IsValid(); } + + // extracts the string, returns empty string if NULL was passed in + wxString GetString() const; + operator wxString() const; + +private: + const void *m_ptr; }; +#define WX_VA_ARG_STRING(ap) wxArgNormalizedString(va_arg(ap, const void*)) +// ---------------------------------------------------------------------------- +// implementation of the WX_DEFINE_VARARG_* macros +// ---------------------------------------------------------------------------- -// NB: The vararg emulation code is limited to 30 arguments at the moment. -// If you need more, you need to +// NB: The vararg emulation code is limited to 30 variadic and 4 fixed +// arguments at the moment. +// If you need more variadic arguments, you need to // 1) increase the value of _WX_VARARG_MAX_ARGS // 2) add _WX_VARARG_JOIN_* and _WX_VARARG_ITER_* up to the new // _WX_VARARG_MAX_ARGS value to the lists below +// If you need more fixed arguments, you need to +// 1) increase the value of _WX_VARARG_MAX_FIXED_ARGS +// 2) add _WX_VARARG_FIXED_EXPAND_* and _WX_VARARG_FIXED_UNUSED_EXPAND_* +// macros below #define _WX_VARARG_MAX_ARGS 30 +#define _WX_VARARG_MAX_FIXED_ARGS 4 #define _WX_VARARG_JOIN_1(m) m(1) #define _WX_VARARG_JOIN_2(m) _WX_VARARG_JOIN_1(m), m(2) @@ -235,36 +396,72 @@ struct WXDLLIMPEXP_BASE wxArgNormalizer #define _WX_VARARG_JOIN_29(m) _WX_VARARG_JOIN_28(m), m(29) #define _WX_VARARG_JOIN_30(m) _WX_VARARG_JOIN_29(m), m(30) -#define _WX_VARARG_ITER_1(m,a,b,c) m(1,a,b,c) -#define _WX_VARARG_ITER_2(m,a,b,c) _WX_VARARG_ITER_1(m,a,b,c) m(2,a,b,c) -#define _WX_VARARG_ITER_3(m,a,b,c) _WX_VARARG_ITER_2(m,a,b,c) m(3,a,b,c) -#define _WX_VARARG_ITER_4(m,a,b,c) _WX_VARARG_ITER_3(m,a,b,c) m(4,a,b,c) -#define _WX_VARARG_ITER_5(m,a,b,c) _WX_VARARG_ITER_4(m,a,b,c) m(5,a,b,c) -#define _WX_VARARG_ITER_6(m,a,b,c) _WX_VARARG_ITER_5(m,a,b,c) m(6,a,b,c) -#define _WX_VARARG_ITER_7(m,a,b,c) _WX_VARARG_ITER_6(m,a,b,c) m(7,a,b,c) -#define _WX_VARARG_ITER_8(m,a,b,c) _WX_VARARG_ITER_7(m,a,b,c) m(8,a,b,c) -#define _WX_VARARG_ITER_9(m,a,b,c) _WX_VARARG_ITER_8(m,a,b,c) m(9,a,b,c) -#define _WX_VARARG_ITER_10(m,a,b,c) _WX_VARARG_ITER_9(m,a,b,c) m(10,a,b,c) -#define _WX_VARARG_ITER_11(m,a,b,c) _WX_VARARG_ITER_10(m,a,b,c) m(11,a,b,c) -#define _WX_VARARG_ITER_12(m,a,b,c) _WX_VARARG_ITER_11(m,a,b,c) m(12,a,b,c) -#define _WX_VARARG_ITER_13(m,a,b,c) _WX_VARARG_ITER_12(m,a,b,c) m(13,a,b,c) -#define _WX_VARARG_ITER_14(m,a,b,c) _WX_VARARG_ITER_13(m,a,b,c) m(14,a,b,c) -#define _WX_VARARG_ITER_15(m,a,b,c) _WX_VARARG_ITER_14(m,a,b,c) m(15,a,b,c) -#define _WX_VARARG_ITER_16(m,a,b,c) _WX_VARARG_ITER_15(m,a,b,c) m(16,a,b,c) -#define _WX_VARARG_ITER_17(m,a,b,c) _WX_VARARG_ITER_16(m,a,b,c) m(17,a,b,c) -#define _WX_VARARG_ITER_18(m,a,b,c) _WX_VARARG_ITER_17(m,a,b,c) m(18,a,b,c) -#define _WX_VARARG_ITER_19(m,a,b,c) _WX_VARARG_ITER_18(m,a,b,c) m(19,a,b,c) -#define _WX_VARARG_ITER_20(m,a,b,c) _WX_VARARG_ITER_19(m,a,b,c) m(20,a,b,c) -#define _WX_VARARG_ITER_21(m,a,b,c) _WX_VARARG_ITER_20(m,a,b,c) m(21,a,b,c) -#define _WX_VARARG_ITER_22(m,a,b,c) _WX_VARARG_ITER_21(m,a,b,c) m(22,a,b,c) -#define _WX_VARARG_ITER_23(m,a,b,c) _WX_VARARG_ITER_22(m,a,b,c) m(23,a,b,c) -#define _WX_VARARG_ITER_24(m,a,b,c) _WX_VARARG_ITER_23(m,a,b,c) m(24,a,b,c) -#define _WX_VARARG_ITER_25(m,a,b,c) _WX_VARARG_ITER_24(m,a,b,c) m(25,a,b,c) -#define _WX_VARARG_ITER_26(m,a,b,c) _WX_VARARG_ITER_25(m,a,b,c) m(26,a,b,c) -#define _WX_VARARG_ITER_27(m,a,b,c) _WX_VARARG_ITER_26(m,a,b,c) m(27,a,b,c) -#define _WX_VARARG_ITER_28(m,a,b,c) _WX_VARARG_ITER_27(m,a,b,c) m(28,a,b,c) -#define _WX_VARARG_ITER_29(m,a,b,c) _WX_VARARG_ITER_28(m,a,b,c) m(29,a,b,c) -#define _WX_VARARG_ITER_30(m,a,b,c) _WX_VARARG_ITER_29(m,a,b,c) m(30,a,b,c) +#define _WX_VARARG_ITER_1(m,a,b,c,d,e,f) m(1,a,b,c,d,e,f) +#define _WX_VARARG_ITER_2(m,a,b,c,d,e,f) _WX_VARARG_ITER_1(m,a,b,c,d,e,f) m(2,a,b,c,d,e,f) +#define _WX_VARARG_ITER_3(m,a,b,c,d,e,f) _WX_VARARG_ITER_2(m,a,b,c,d,e,f) m(3,a,b,c,d,e,f) +#define _WX_VARARG_ITER_4(m,a,b,c,d,e,f) _WX_VARARG_ITER_3(m,a,b,c,d,e,f) m(4,a,b,c,d,e,f) +#define _WX_VARARG_ITER_5(m,a,b,c,d,e,f) _WX_VARARG_ITER_4(m,a,b,c,d,e,f) m(5,a,b,c,d,e,f) +#define _WX_VARARG_ITER_6(m,a,b,c,d,e,f) _WX_VARARG_ITER_5(m,a,b,c,d,e,f) m(6,a,b,c,d,e,f) +#define _WX_VARARG_ITER_7(m,a,b,c,d,e,f) _WX_VARARG_ITER_6(m,a,b,c,d,e,f) m(7,a,b,c,d,e,f) +#define _WX_VARARG_ITER_8(m,a,b,c,d,e,f) _WX_VARARG_ITER_7(m,a,b,c,d,e,f) m(8,a,b,c,d,e,f) +#define _WX_VARARG_ITER_9(m,a,b,c,d,e,f) _WX_VARARG_ITER_8(m,a,b,c,d,e,f) m(9,a,b,c,d,e,f) +#define _WX_VARARG_ITER_10(m,a,b,c,d,e,f) _WX_VARARG_ITER_9(m,a,b,c,d,e,f) m(10,a,b,c,d,e,f) +#define _WX_VARARG_ITER_11(m,a,b,c,d,e,f) _WX_VARARG_ITER_10(m,a,b,c,d,e,f) m(11,a,b,c,d,e,f) +#define _WX_VARARG_ITER_12(m,a,b,c,d,e,f) _WX_VARARG_ITER_11(m,a,b,c,d,e,f) m(12,a,b,c,d,e,f) +#define _WX_VARARG_ITER_13(m,a,b,c,d,e,f) _WX_VARARG_ITER_12(m,a,b,c,d,e,f) m(13,a,b,c,d,e,f) +#define _WX_VARARG_ITER_14(m,a,b,c,d,e,f) _WX_VARARG_ITER_13(m,a,b,c,d,e,f) m(14,a,b,c,d,e,f) +#define _WX_VARARG_ITER_15(m,a,b,c,d,e,f) _WX_VARARG_ITER_14(m,a,b,c,d,e,f) m(15,a,b,c,d,e,f) +#define _WX_VARARG_ITER_16(m,a,b,c,d,e,f) _WX_VARARG_ITER_15(m,a,b,c,d,e,f) m(16,a,b,c,d,e,f) +#define _WX_VARARG_ITER_17(m,a,b,c,d,e,f) _WX_VARARG_ITER_16(m,a,b,c,d,e,f) m(17,a,b,c,d,e,f) +#define _WX_VARARG_ITER_18(m,a,b,c,d,e,f) _WX_VARARG_ITER_17(m,a,b,c,d,e,f) m(18,a,b,c,d,e,f) +#define _WX_VARARG_ITER_19(m,a,b,c,d,e,f) _WX_VARARG_ITER_18(m,a,b,c,d,e,f) m(19,a,b,c,d,e,f) +#define _WX_VARARG_ITER_20(m,a,b,c,d,e,f) _WX_VARARG_ITER_19(m,a,b,c,d,e,f) m(20,a,b,c,d,e,f) +#define _WX_VARARG_ITER_21(m,a,b,c,d,e,f) _WX_VARARG_ITER_20(m,a,b,c,d,e,f) m(21,a,b,c,d,e,f) +#define _WX_VARARG_ITER_22(m,a,b,c,d,e,f) _WX_VARARG_ITER_21(m,a,b,c,d,e,f) m(22,a,b,c,d,e,f) +#define _WX_VARARG_ITER_23(m,a,b,c,d,e,f) _WX_VARARG_ITER_22(m,a,b,c,d,e,f) m(23,a,b,c,d,e,f) +#define _WX_VARARG_ITER_24(m,a,b,c,d,e,f) _WX_VARARG_ITER_23(m,a,b,c,d,e,f) m(24,a,b,c,d,e,f) +#define _WX_VARARG_ITER_25(m,a,b,c,d,e,f) _WX_VARARG_ITER_24(m,a,b,c,d,e,f) m(25,a,b,c,d,e,f) +#define _WX_VARARG_ITER_26(m,a,b,c,d,e,f) _WX_VARARG_ITER_25(m,a,b,c,d,e,f) m(26,a,b,c,d,e,f) +#define _WX_VARARG_ITER_27(m,a,b,c,d,e,f) _WX_VARARG_ITER_26(m,a,b,c,d,e,f) m(27,a,b,c,d,e,f) +#define _WX_VARARG_ITER_28(m,a,b,c,d,e,f) _WX_VARARG_ITER_27(m,a,b,c,d,e,f) m(28,a,b,c,d,e,f) +#define _WX_VARARG_ITER_29(m,a,b,c,d,e,f) _WX_VARARG_ITER_28(m,a,b,c,d,e,f) m(29,a,b,c,d,e,f) +#define _WX_VARARG_ITER_30(m,a,b,c,d,e,f) _WX_VARARG_ITER_29(m,a,b,c,d,e,f) m(30,a,b,c,d,e,f) + + +#define _WX_VARARG_FIXED_EXPAND_1(t1) \ + t1 f1 +#define _WX_VARARG_FIXED_EXPAND_2(t1,t2) \ + t1 f1, t2 f2 +#define _WX_VARARG_FIXED_EXPAND_3(t1,t2,t3) \ + t1 f1, t2 f2, t3 f3 +#define _WX_VARARG_FIXED_EXPAND_4(t1,t2,t3,t4) \ + t1 f1, t2 f2, t3 f3, t4 f4 + +#define _WX_VARARG_FIXED_UNUSED_EXPAND_1(t1) \ + t1 WXUNUSED(f1) +#define _WX_VARARG_FIXED_UNUSED_EXPAND_2(t1,t2) \ + t1 WXUNUSED(f1), t2 WXUNUSED(f2) +#define _WX_VARARG_FIXED_UNUSED_EXPAND_3(t1,t2,t3) \ + t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3) +#define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \ + t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4) + + +// This macro expands N-items tuple of fixed arguments types into part of +// function's declaration. For example, +// "_WX_VARARG_FIXED_EXPAND(3, (int, char*, int))" expands into +// "int f1, char* f2, int f3". +#define _WX_VARARG_FIXED_EXPAND(N, args) \ + _WX_VARARG_FIXED_EXPAND_IMPL(N, args) +#define _WX_VARARG_FIXED_EXPAND_IMPL(N, args) \ + _WX_VARARG_FIXED_EXPAND_##N args + +// Ditto for unused arguments +#define _WX_VARARG_FIXED_UNUSED_EXPAND(N, args) \ + _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) +#define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \ + _WX_VARARG_FIXED_UNUSED_EXPAND_##N args + // This macro calls another macro 'm' passed as second argument 'N' times, // with its only argument set to 1..N, and concatenates the results using @@ -280,61 +477,160 @@ struct WXDLLIMPEXP_BASE wxArgNormalizer #define _WX_VARARG_JOIN(N, m) _WX_VARARG_JOIN_IMPL(N, m) #define _WX_VARARG_JOIN_IMPL(N, m) _WX_VARARG_JOIN_##N(m) + // This macro calls another macro 'm' passed as second argument 'N' times, with -// its first argument set to 1..N and the remaining arguments set to 'a', 'b' -// and 'c'. The results are separated with whitespace in the expansion. +// its first argument set to 1..N and the remaining arguments set to 'a', 'b', +// 'c', 'd', 'e' and 'f'. The results are separated with whitespace in the +// expansion. // // An example: // // this macro expands to: -// // foo(1,a,b,c) -// // foo(2,a,b,c) -// // foo(3,a,b,c) -// _WX_VARARG_ITER(3, foo, a, b, c) +// // foo(1,a,b,c,d,e,f) +// // foo(2,a,b,c,d,e,f) +// // foo(3,a,b,c,d,e,f) +// _WX_VARARG_ITER(3, foo, a, b, c, d, e, f) // // N must not be greater than _WX_VARARG_MAX_ARGS (=30). -#define _WX_VARARG_ITER(N, m,a,b,c) _WX_VARARG_ITER_IMPL(N, m, a, b, c) -#define _WX_VARARG_ITER_IMPL(N, m,a,b,c) _WX_VARARG_ITER_##N(m, a, b, c) +#define _WX_VARARG_ITER(N,m,a,b,c,d,e,f) \ + _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) +#define _WX_VARARG_ITER_IMPL(N,m,a,b,c,d,e,f) \ + _WX_VARARG_ITER_##N(m,a,b,c,d,e,f) -// Generates code snippet for i-th argument in vararg function's prototype. -#define _WX_VARARG_ARG(i) T##i a##i +// Generates code snippet for i-th "variadic" argument in vararg function's +// prototype: +#define _WX_VARARG_ARG(i) T##i a##i -// Like _WX_VARARG_ARG_UNUSED, but outputs argument's type with WXUNUSED. -#define _WX_VARARG_ARG_UNUSED(i) T##i WXUNUSED(a##i) +// Like _WX_VARARG_ARG_UNUSED, but outputs argument's type with WXUNUSED: +#define _WX_VARARG_ARG_UNUSED(i) T##i WXUNUSED(a##i) -// Generates code snippet for i-th type in vararg function's template<...>. -#define _WX_VARARG_TEMPL(i) typename T##i +// Generates code snippet for i-th type in vararg function's template<...>: +#define _WX_VARARG_TEMPL(i) typename T##i // Generates code snippet for passing i-th argument of vararg function -// wrapper to its implementation, normalizing it in the process -#define _WX_VARARG_PASS(i) wxArgNormalizer(a##i).get() +// wrapper to its implementation, normalizing it in the process: +#define _WX_VARARG_PASS_WCHAR(i) wxArgNormalizerWchar(a##i).get() +#define _WX_VARARG_PASS_UTF8(i) wxArgNormalizerUtf8(a##i).get() + + +// And the same for fixed arguments, _not_ normalizing it: +// FIXME-UTF8: this works, but uses wxString's implicit conversion to wxChar* +// for the 'format' argument (which is const wxString&) _if_ the +// implementation function has C sting argument; we need to +// have wxFixedArgNormalizer here that will pass everything +// as-is except for wxString (for which wx_str() would be used), +// but OTOH, we don't want to do that if the implementation takes +// wxString argument +#define _WX_VARARG_PASS_FIXED(i) f##i + +#if wxUSE_UNICODE_UTF8 + #define _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed) \ + return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ + _WX_VARARG_JOIN(N, _WX_VARARG_PASS_UTF8)) + #define _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed) \ + return_kw implUtf8(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) +#endif // wxUSE_UNICODE_UTF8 + +#define _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) \ + return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED), \ + _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR)) +#define _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) \ + return_kw impl(_WX_VARARG_JOIN(numfixed, _WX_VARARG_PASS_FIXED)) + +#if wxUSE_UNICODE_UTF8 + #if wxUSE_UTF8_LOCALE_ONLY + #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_UTF8 + #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_UTF8 + #else // possibly non-UTF8 locales + #define _WX_VARARG_DO_CALL(return_kw, impl, implUtf8, N, numfixed) \ + if ( wxLocaleIsUtf8 ) \ + _WX_VARARG_DO_CALL_UTF8(return_kw, impl, implUtf8, N, numfixed);\ + else \ + _WX_VARARG_DO_CALL_WCHAR(return_kw, impl, implUtf8, N, numfixed) + + #define _WX_VARARG_DO_CALL0(return_kw, impl, implUtf8, numfixed) \ + if ( wxLocaleIsUtf8 ) \ + _WX_VARARG_DO_CALL0_UTF8(return_kw, impl, implUtf8, numfixed); \ + else \ + _WX_VARARG_DO_CALL0_WCHAR(return_kw, impl, implUtf8, numfixed) + #endif // wxUSE_UTF8_LOCALE_ONLY or not +#else // wxUSE_UNICODE_WCHAR or ANSI + #define _WX_VARARG_DO_CALL _WX_VARARG_DO_CALL_WCHAR + #define _WX_VARARG_DO_CALL0 _WX_VARARG_DO_CALL0_WCHAR +#endif // wxUSE_UNICODE_UTF8 / wxUSE_UNICODE_WCHAR // Macro to be used with _WX_VARARG_ITER in the implementation of // WX_DEFINE_VARARG_FUNC (see its documentation for the meaning of arguments) -#define _WX_VARARG_DEFINE_FUNC(N, rettype, name, impl) \ - template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ - rettype name(_WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ - { \ - return impl(_WX_VARARG_JOIN(N, _WX_VARARG_PASS)); \ +#define _WX_VARARG_DEFINE_FUNC(N, rettype, name, \ + impl, implUtf8, numfixed, fixed) \ + template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ + rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ + _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ + { \ + _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed); \ + } + +#define _WX_VARARG_DEFINE_FUNC_N0(rettype, name, \ + impl, implUtf8, numfixed, fixed) \ + inline rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ + { \ + _WX_VARARG_DO_CALL0(return, impl, implUtf8, numfixed); \ } // Macro to be used with _WX_VARARG_ITER in the implementation of // WX_DEFINE_VARARG_FUNC_VOID (see its documentation for the meaning of // arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's // requirements). -#define _WX_VARARG_DEFINE_FUNC_VOID(N, rettype, name, impl) \ - template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ - void name(_WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ - { \ - impl(_WX_VARARG_JOIN(N, _WX_VARARG_PASS)); \ +#define _WX_VARARG_DEFINE_FUNC_VOID(N, rettype, name, \ + impl, implUtf8, numfixed, fixed) \ + template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ + void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ + _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ + { \ + _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ + impl, implUtf8, N, numfixed); \ + } + +#define _WX_VARARG_DEFINE_FUNC_VOID_N0(name, impl, implUtf8, numfixed, fixed) \ + inline void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ + { \ + _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ + impl, implUtf8, numfixed); \ + } + +// Macro to be used with _WX_VARARG_ITER in the implementation of +// WX_DEFINE_VARARG_FUNC_CTOR (see its documentation for the meaning of +// arguments; rettype is ignored and is used only to satisfy _WX_VARARG_ITER's +// requirements). +#define _WX_VARARG_DEFINE_FUNC_CTOR(N, rettype, name, \ + impl, implUtf8, numfixed, fixed) \ + template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ + name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \ + _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \ + { \ + _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE, \ + impl, implUtf8, N, numfixed); \ + } + +#define _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \ + inline name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed)) \ + { \ + _WX_VARARG_DO_CALL0(wxEMPTY_PARAMETER_VALUE, \ + impl, implUtf8, numfixed); \ } // Macro to be used with _WX_VARARG_ITER in the implementation of // WX_DEFINE_VARARG_FUNC_NOP, i.e. empty stub for a disabled vararg function. // The rettype and impl arguments are ignored. -#define _WX_VARARG_DEFINE_FUNC_NOP(N, rettype, name, impl) \ - template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ - void name(_WX_VARARG_JOIN(N, _WX_VARARG_ARG_UNUSED)) {} - +#define _WX_VARARG_DEFINE_FUNC_NOP(N, rettype, name, \ + impl, implUtf8, numfixed, fixed) \ + template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \ + void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed), \ + _WX_VARARG_JOIN(N, _WX_VARARG_ARG_UNUSED)) \ + {} + +#define _WX_VARARG_DEFINE_FUNC_NOP_N0(name, numfixed, fixed) \ + inline void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed)) \ + {} #endif // _WX_STRVARARG_H_ diff --git a/include/wx/wx.h b/include/wx/wx.h index df72b056b2..62ba23fa15 100644 --- a/include/wx/wx.h +++ b/include/wx/wx.h @@ -31,6 +31,7 @@ #include "wx/stopwatch.h" #include "wx/module.h" #include "wx/wxcrt.h" +#include "wx/wxcrtvararg.h" #if wxUSE_GUI diff --git a/include/wx/wxcrtvararg.h b/include/wx/wxcrtvararg.h index c036b33ecf..6ddb99ff1c 100644 --- a/include/wx/wxcrtvararg.h +++ b/include/wx/wxcrtvararg.h @@ -16,51 +16,38 @@ #include "wx/wxcrt.h" #include "wx/strvararg.h" +#include "wx/string.h" + +// ---------------------------------------------------------------------------- +// CRT functions aliases +// ---------------------------------------------------------------------------- /* Required for wxPrintf() etc */ #include #ifdef wxHAVE_TCHAR_SUPPORT - WX_DEFINE_VARARG_FUNC(int, wxFprintf, _ftprintf) - WX_DEFINE_VARARG_FUNC(int, wxPrintf, _tprintf) - #define wxPutc(c,f) _puttc(WXWCHAR_T_CAST(c),f) - #define wxPutchar _puttchar - #define wxPuts _putts - #define wxScanf _tscanf /* FIXME-UTF8: not wrapped */ - #if defined(__DMC__) - #if wxUSE_UNICODE - /* Digital Mars adds count to _stprintf (C99) so prototype conversion see wxchar.cpp */ - int wxDoSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... ) ; - WX_DEFINE_VARARG_FUNC(int, wxSprintf, wxDoSprintf) - #else - /* and there is a bug in D Mars tchar.h prior to 8.39.4n, so define - as sprintf */ - WX_DEFINE_VARARG_FUNC(int, wxSprintf, sprintf) - #endif - #else - WX_DEFINE_VARARG_FUNC(int, wxSprintf, _stprintf) - #endif + #define wxCRT_Fprintf _ftprintf + #define wxCRT_Printf _tprintf + #define wxCRT_Scanf _tscanf - /* FIXME-UTF8: not wrapped */ - #define wxSscanf _stscanf - #define wxVfprintf _vftprintf - #define wxVprintf _vtprintf - #define wxVsscanf _vstscanf - #define wxVsprintf _vstprintf + #define wxCRT_Sscanf _stscanf + #define wxCRT_Vfprintf _vftprintf + #define wxCRT_Vprintf _vtprintf + #define wxCRT_Vsscanf _vstscanf + #define wxCRT_Vsprintf _vstprintf #else /* !TCHAR-aware compilers */ #if !wxUSE_UNICODE /* ASCII */ - WX_DEFINE_VARARG_FUNC(int, wxFprintf, fprintf) - #define wxFscanf fscanf - WX_DEFINE_VARARG_FUNC(int, wxPrintf, printf) - #define wxScanf scanf - WX_DEFINE_VARARG_FUNC(int, wxSprintf, sprintf) - #define wxSscanf sscanf - #define wxVfprintf vfprintf - #define wxVprintf vprintf - #define wxVsscanf vsscanf - #define wxVsprintf vsprintf + #define wxCRT_Fprintf fprintf + #define wxCRT_Fscanf fscanf + #define wxCRT_Printf printf + #define wxCRT_Scanf scanf + #define wxCRT_Sscanf sscanf + #define wxCRT_Vfprintf vfprintf + #define wxCRT_Vprintf vprintf + #define wxCRT_Vsscanf vsscanf + #define wxCRT_Vsprintf vsprintf #endif /* ASCII */ #endif /* TCHAR-aware compilers/the others */ @@ -156,9 +143,7 @@ #ifndef wxVsnprintf_ #if defined(__VISUALC__) || \ (defined(__BORLANDC__) && __BORLANDC__ >= 0x540) - #define wxSnprintf_ _sntprintf #define wxVsnprintf_ _vsntprintf - WX_DEFINE_VARARG_FUNC(int, wxSnprintf_, _sntprintf) #endif #endif @@ -171,19 +156,12 @@ #define wxVsnprintf_ vswprintf #elif defined(__WATCOMC__) #define wxVsnprintf_ _vsnwprintf - WX_DEFINE_VARARG_FUNC(int, wxSnprintf_, _snwprintf) #endif #else /* ASCII */ /* All versions of CodeWarrior supported by wxWidgets apparently have both snprintf() and vsnprintf() */ - #if defined(HAVE_SNPRINTF) \ - || defined(__MWERKS__) || defined(__WATCOMC__) - #ifndef HAVE_BROKEN_SNPRINTF_DECL - WX_DEFINE_VARARG_FUNC(int, wxSnprintf_, snprintf) - #endif - #endif #if defined(HAVE_VSNPRINTF) \ || defined(__MWERKS__) || defined(__WATCOMC__) #ifdef HAVE_BROKEN_VSNPRINTF_DECL @@ -196,18 +174,10 @@ #endif /* wxVsnprintf_ */ #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */ -#ifndef wxSnprintf_ - /* no snprintf(), cook our own */ - WXDLLIMPEXP_BASE int - wxDoSnprintf_(wxChar *buf, size_t len, - const wxChar *format, ...) ATTRIBUTE_PRINTF_3; - WX_DEFINE_VARARG_FUNC(int, wxSnprintf_, wxDoSnprintf_) -#endif #ifndef wxVsnprintf_ /* no (suitable) vsnprintf(), cook our own */ WXDLLIMPEXP_BASE int - wxVsnprintf_(wxChar *buf, size_t len, - const wxChar *format, va_list argptr); + wxVsnprintf_(wxChar *buf, size_t len, const wxChar *format, va_list argptr); #define wxUSE_WXVSNPRINTF 1 #else @@ -242,28 +212,15 @@ either because we don't have them at all or because they don't have the semantics we need */ - WX_DEFINE_VARARG_FUNC(int, wxScanf, wxDoScanf) - int wxDoScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_1; - - WX_DEFINE_VARARG_FUNC(int, wxSscanf, wxDoSscanf) - int wxDoSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; - - WX_DEFINE_VARARG_FUNC(int, wxFscanf, wxDoFscanf) - int wxDoFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; - - WX_DEFINE_VARARG_FUNC(int, wxPrintf, wxDoPrintf) - int wxDoPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_1; - - WX_DEFINE_VARARG_FUNC(int, wxSprintf, wxDoSprintf) - int wxDoSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; - - WX_DEFINE_VARARG_FUNC(int, wxFprintf, wxDoFprintf) - int wxDoFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; - - int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap ); - int wxVfprintf( FILE *stream, const wxChar *format, va_list ap ); - int wxVprintf( const wxChar *format, va_list ap ); - int wxVsprintf( wxChar *str, const wxChar *format, va_list ap ); + int wxCRT_Scanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_1; + int wxCRT_Sscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; + int wxCRT_Fscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; + int wxCRT_Vsscanf( const wxChar *str, const wxChar *format, va_list ap ); + int wxCRT_Printf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_1; + int wxCRT_Fprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_2; + int wxCRT_Vfprintf( FILE *stream, const wxChar *format, va_list ap ); + int wxCRT_Vprintf( const wxChar *format, va_list ap ); + int wxCRT_Vsprintf( wxChar *str, const wxChar *format, va_list ap ); #endif /* wxNEED_PRINTF_CONVERSION */ /* these 2 can be simply mapped to the versions with underscore at the end */ @@ -273,12 +230,136 @@ anything as our own wxVsnprintf_() already behaves as needed. */ #if defined(wxNEED_PRINTF_CONVERSION) && defined(wxVsnprintf_) - WX_DEFINE_VARARG_FUNC(int, wxSnprintf, wxDoSnprintf) - int wxDoSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3; - int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap ); + int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap ); #else - #define wxSnprintf wxSnprintf_ - #define wxVsnprintf wxVsnprintf_ + #define wxCRT_Vsnprintf wxVsnprintf_ +#endif + + +// ---------------------------------------------------------------------------- +// user-friendly wrappers to CRT functions +// ---------------------------------------------------------------------------- + +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + #define wxPrintf wxPrintf_Impl + #define wxFprintf wxFprintf_Impl + #define wxSprintf wxSprintf_Impl + #define wxSnprintf wxSnprintf_Impl +#endif + +// FIXME-UTF8: explicit wide-string and short-string format specifiers +// (%hs, %ls and variants) are currently broken, only %s works +// as expected (regardless of the build) + +// FIXME-UTF8: %c (and %hc, %lc) don't work as expected either: in UTF-8 build, +// we should replace them with %s (as some Unicode chars may be +// encoded with >1 bytes) and in all builds, we should use wchar_t +// for all characters and convert char to it; +// we'll also need wxArgNormalizer specializations for char, +// wchar_t, wxUniChar and wxUniCharRef to handle this correctly + +WX_DEFINE_VARARG_FUNC2(int, wxPrintf, 1, (const wxString&), + wxCRT_Printf, printf) +WX_DEFINE_VARARG_FUNC2(int, wxFprintf, 2, (FILE*, const wxString&), + wxCRT_Fprintf, fprintf) + +// va_list versions of printf functions simply forward to the respective +// CRT function; note that they assume that va_list was created using +// wxArgNormalizer! +#if wxUSE_UNICODE_UTF8 + #if wxUSE_UTF8_LOCALE_ONLY + #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \ + return implUtf8 args + #else + #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \ + if ( wxLocaleIsUtf8 ) return implUtf8 args; \ + else return implWchar args + #endif +#else // wxUSE_UNICODE_WCHAR / ANSI + #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8) \ + return implWchar args #endif +inline int +wxVprintf(const wxString& format, va_list ap) +{ + WX_VARARG_VFOO_IMPL((format, ap), wxCRT_Vprintf, vprintf); +} + +inline int +wxVfprintf(FILE *f, const wxString& format, va_list ap) +{ + WX_VARARG_VFOO_IMPL((f, format, ap), wxCRT_Vfprintf, vfprintf); +} + +#undef WX_VARARG_VFOO_IMPL + + +// wxSprintf() and friends have to be implemented in two forms, one for +// writing to char* buffer and one for writing to wchar_t*: + +int WXDLLIMPEXP_BASE wxDoSprintf(char *str, const wxString& format, ...); +WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (char*, const wxString&), + wxDoSprintf) + +int WXDLLIMPEXP_BASE +wxVsprintf(char *str, const wxString& format, va_list argptr); + +int WXDLLIMPEXP_BASE wxDoSnprintf(char *str, size_t size, const wxString& format, ...); +WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (char*, size_t, const wxString&), + wxDoSnprintf) + +int WXDLLIMPEXP_BASE +wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr); + +#if wxUSE_UNICODE +int WXDLLIMPEXP_BASE wxDoSprintf(wchar_t *str, const wxString& format, ...); +WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (wchar_t*, const wxString&), + wxDoSprintf) + +int WXDLLIMPEXP_BASE +wxVsprintf(wchar_t *str, const wxString& format, va_list argptr); + +int WXDLLIMPEXP_BASE wxDoSnprintf(wchar_t *str, size_t size, const wxString& format, ...); +WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (wchar_t*, size_t, const wxString&), + wxDoSnprintf) + +int WXDLLIMPEXP_BASE +wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr); +#endif // wxUSE_UNICODE + +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + // + // fortunately, OpenWatcom implements __VA_ARGS__, so we can provide macros + // that cast the format argument to wxString: + #undef wxPrintf + #undef wxFprintf + #undef wxSprintf + #undef wxSnprintf + + #define wxPrintf(fmt, ...) \ + wxPrintf_Impl(wxString(fmt), __VA_ARGS__) + #define wxFprintf(f, fmt, ...) \ + wxFprintf_Impl(f, wxString(fmt), __VA_ARGS__) + #define wxSprintf(s, fmt, ...) \ + wxSprintf_Impl(s, wxString(fmt), __VA_ARGS__) + #define wxSnprintf(s, n, fmt, ...) \ + wxSnprintf_Impl(s, n, wxString(fmt), __VA_ARGS__) +#endif // __WATCOMC__ + + +// We can't use wxArgNormalizer for variadic arguments to wxScanf() etc. +// because they are writable, so instead of providing friendly template +// vararg-like functions, we just provide both char* and wchar_t* variants +// of these functions. The type of output variadic arguments for %s must match +// the type of 'str' and 'format' arguments. + +// FIXME-UTF8: actually do it, for now we only have wxChar* variants: +#define wxScanf wxCRT_Scanf +#define wxFscanf wxCRT_Fscanf +#define wxSscanf wxCRT_Sscanf +#define wxVsscanf wxCRT_Vsscanf + #endif /* _WX_WXCRTVARARG_H_ */ diff --git a/src/common/filesys.cpp b/src/common/filesys.cpp index 19675f7996..94a229f49c 100644 --- a/src/common/filesys.cpp +++ b/src/common/filesys.cpp @@ -69,27 +69,27 @@ wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location) wxEmptyString, wxEmptyString, _T("JPEG image (from fallback)"), - _T("jpg"), _T("jpeg"), _T("JPG"), _T("JPEG"), NULL), + _T("jpg"), _T("jpeg"), _T("JPG"), _T("JPEG"), 0), wxFileTypeInfo(_T("image/gif"), wxEmptyString, wxEmptyString, _T("GIF image (from fallback)"), - _T("gif"), _T("GIF"), NULL), + _T("gif"), _T("GIF"), 0), wxFileTypeInfo(_T("image/png"), wxEmptyString, wxEmptyString, _T("PNG image (from fallback)"), - _T("png"), _T("PNG"), NULL), + _T("png"), _T("PNG"), 0), wxFileTypeInfo(_T("image/bmp"), wxEmptyString, wxEmptyString, _T("windows bitmap image (from fallback)"), - _T("bmp"), _T("BMP"), NULL), + _T("bmp"), _T("BMP"), 0), wxFileTypeInfo(_T("text/html"), wxEmptyString, wxEmptyString, _T("HTML document (from fallback)"), - _T("htm"), _T("html"), _T("HTM"), _T("HTML"), NULL), + _T("htm"), _T("html"), _T("HTM"), _T("HTML"), 0), // must terminate the table with this! wxFileTypeInfo() }; diff --git a/src/common/fmapbase.cpp b/src/common/fmapbase.cpp index 48e1b2e148..e989e839f8 100644 --- a/src/common/fmapbase.cpp +++ b/src/common/fmapbase.cpp @@ -31,6 +31,7 @@ #include "wx/log.h" #include "wx/intl.h" #include "wx/module.h" + #include "wx/wxcrtvararg.h" #endif //WX_PRECOMP #if defined(__WXMSW__) diff --git a/src/common/ftp.cpp b/src/common/ftp.cpp index 3672b76b4b..da7c72171e 100644 --- a/src/common/ftp.cpp +++ b/src/common/ftp.cpp @@ -38,6 +38,7 @@ #include "wx/utils.h" #include "wx/log.h" #include "wx/intl.h" + #include "wx/wxcrtvararg.h" #endif // WX_PRECOMP #include "wx/sckaddr.h" diff --git a/src/common/http.cpp b/src/common/http.cpp index f190f800e4..f8977ecedf 100644 --- a/src/common/http.cpp +++ b/src/common/http.cpp @@ -141,7 +141,7 @@ wxString wxHTTP::GenerateAuthString(const wxString& user, const wxString& pass) } else { buf << wxString::Format(wxT("%c%c"), base64[((from[0] << 4) & 0x30) | ((from[1] >> 4) & 0xf)], base64[(from[1] << 2) & 0x3c]); } - buf << wxString::Format(wxT("=")); + buf << wxT("="); } return buf; diff --git a/src/common/log.cpp b/src/common/log.cpp index e6690b652a..1e03c06a06 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -91,11 +91,11 @@ void wxVLogGeneric(wxLogLevel level, const wxString& format, va_list argptr) } } -void wxDoLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) +void wxDoLogGeneric(wxLogLevel level, const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogGeneric(level, szFormat, argptr); + va_start(argptr, format); + wxVLogGeneric(level, format, argptr); va_end(argptr); } @@ -108,11 +108,11 @@ void wxDoLogGeneric(wxLogLevel level, const wxChar *szFormat, ...) } \ } \ \ - void wxDoLog##level(const wxChar *szFormat, ...) \ + void wxDoLog##level(const wxString& format, ...) \ { \ va_list argptr; \ - va_start(argptr, szFormat); \ - wxVLog##level(szFormat, argptr); \ + va_start(argptr, format); \ + wxVLog##level(format, argptr); \ va_end(argptr); \ } @@ -145,11 +145,11 @@ void wxVLogFatalError(const wxString& format, va_list argptr) #endif } -void wxDoLogFatalError(const wxChar *szFormat, ...) +void wxDoLogFatalError(const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogFatalError(szFormat, argptr); + va_start(argptr, format); + wxVLogFatalError(format, argptr); // some compilers warn about unreachable code and it shouldn't matter // for the others anyhow... @@ -167,30 +167,30 @@ void wxVLogVerbose(const wxString& format, va_list argptr) } } -void wxDoLogVerbose(const wxChar *szFormat, ...) +void wxDoLogVerbose(const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogVerbose(szFormat, argptr); + va_start(argptr, format); + wxVLogVerbose(format, argptr); va_end(argptr); } // debug functions #ifdef __WXDEBUG__ #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) \ - void wxVLog##level(const wxChar *szFormat, va_list argptr) \ + void wxVLog##level(const wxString& format, va_list argptr) \ { \ if ( wxLog::IsEnabled() ) { \ wxLog::OnLog(wxLOG_##level, \ - wxString::FormatV(szFormat, argptr), time(NULL));\ + wxString::FormatV(format, argptr), time(NULL)); \ } \ } \ \ - void wxDoLog##level(const wxChar *szFormat, ...) \ + void wxDoLog##level(const wxString& format, ...) \ { \ va_list argptr; \ - va_start(argptr, szFormat); \ - wxVLog##level(szFormat, argptr); \ + va_start(argptr, format); \ + wxVLog##level(format, argptr); \ va_end(argptr); \ } @@ -204,11 +204,11 @@ void wxDoLogVerbose(const wxChar *szFormat, ...) } } - void wxDoLogTrace(const wxString& mask, const wxChar *szFormat, ...) + void wxDoLogTrace(const wxString& mask, const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogTrace(mask, szFormat, argptr); + va_start(argptr, format); + wxVLogTrace(mask, format, argptr); va_end(argptr); } @@ -222,14 +222,48 @@ void wxDoLogVerbose(const wxChar *szFormat, ...) } } - void wxDoLogTrace(wxTraceMask mask, const wxChar *szFormat, ...) + void wxDoLogTrace(wxTraceMask mask, const wxString& format, ...) + { + va_list argptr; + va_start(argptr, format); + wxVLogTrace(mask, format, argptr); + va_end(argptr); + } + +#ifdef __WATCOMC__ + // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 + void wxDoLogTrace(int mask, const wxString& format, ...) + { + va_list argptr; + va_start(argptr, format); + wxVLogTrace(mask, format, argptr); + va_end(argptr); + } + + void wxDoLogTrace(const char *mask, const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogTrace(mask, szFormat, argptr); + va_start(argptr, format); + wxVLogTrace(mask, format, argptr); va_end(argptr); } + void wxDoLogTrace(const wchar_t *mask, const wxString& format, ...) + { + va_list argptr; + va_start(argptr, format); + wxVLogTrace(mask, format, argptr); + va_end(argptr); + } + + void wxVLogTrace(int mask, const wxString& format, va_list argptr) + { wxVLogTrace((wxTraceMask)mask, format, argptr); } + 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__ + #else // release #define IMPLEMENT_LOG_DEBUG_FUNCTION(level) #endif @@ -251,11 +285,11 @@ void WXDLLEXPORT wxVLogSysError(const wxString& format, va_list argptr) wxVLogSysError(wxSysErrorCode(), format, argptr); } -void WXDLLEXPORT wxDoLogSysError(const wxChar *szFormat, ...) +void WXDLLEXPORT wxDoLogSysError(const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogSysError(szFormat, argptr); + va_start(argptr, format); + wxVLogSysError(format, argptr); va_end(argptr); } @@ -268,14 +302,28 @@ void WXDLLEXPORT wxVLogSysError(long err, const wxString& format, va_list argptr } } -void WXDLLEXPORT wxDoLogSysError(long lErrCode, const wxChar *szFormat, ...) +void WXDLLEXPORT wxDoLogSysError(long lErrCode, const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogSysError(lErrCode, szFormat, argptr); + va_start(argptr, format); + wxVLogSysError(lErrCode, format, argptr); va_end(argptr); } +#ifdef __WATCOMC__ +// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351 +void WXDLLEXPORT wxDoLogSysError(unsigned long lErrCode, const wxString& format, ...) +{ + va_list argptr; + va_start(argptr, format); + wxVLogSysError(lErrCode, format, argptr); + va_end(argptr); +} + +void WXDLLEXPORT wxVLogSysError(unsigned long err, const wxString& format, va_list argptr) + { wxVLogSysError((long)err, format, argptr); } +#endif // __WATCOMC__ + // ---------------------------------------------------------------------------- // wxLog class implementation // ---------------------------------------------------------------------------- diff --git a/src/common/mimecmn.cpp b/src/common/mimecmn.cpp index 9325fb81c3..1db9b7176c 100644 --- a/src/common/mimecmn.cpp +++ b/src/common/mimecmn.cpp @@ -111,19 +111,20 @@ wxString wxMimeTypeCommands::GetVerbCmd(size_t n) const // wxFileTypeInfo // ---------------------------------------------------------------------------- -wxFileTypeInfo::wxFileTypeInfo(const wxChar *mimeType, - const wxChar *openCmd, - const wxChar *printCmd, - const wxChar *desc, - ...) - : m_mimeType(mimeType), - m_openCmd(openCmd), - m_printCmd(printCmd), - m_desc(desc) +void wxFileTypeInfo::VarArgInit(const wxString& mimeType, + const wxString& openCmd, + const wxString& printCmd, + const wxString& desc, + ...) { va_list argptr; va_start(argptr, desc); + m_mimeType = mimeType; + m_openCmd = openCmd; + m_printCmd = printCmd; + m_desc = desc; + for ( ;; ) { // icc gives this warning in its own va_arg() macro, argh @@ -132,7 +133,7 @@ wxFileTypeInfo::wxFileTypeInfo(const wxChar *mimeType, #pragma warning(disable: 1684) #endif - const wxChar *ext = va_arg(argptr, const wxChar *); + wxArgNormalizedString ext(WX_VA_ARG_STRING(argptr)); #ifdef __INTELC__ #pragma warning(pop) @@ -143,7 +144,7 @@ wxFileTypeInfo::wxFileTypeInfo(const wxChar *mimeType, break; } - m_exts.Add(ext); + m_exts.Add(ext.GetString()); } va_end(argptr); diff --git a/src/common/msgout.cpp b/src/common/msgout.cpp index 44ec5e1597..ca7f4e1c70 100755 --- a/src/common/msgout.cpp +++ b/src/common/msgout.cpp @@ -76,7 +76,7 @@ wxMessageOutput* wxMessageOutput::Set(wxMessageOutput* msgout) return old; } -void wxMessageOutput::DoPrintf(const wxChar* format, ...) +void wxMessageOutput::DoPrintf(const wxString& format, ...) { va_list args; va_start(args, format); diff --git a/src/common/string.cpp b/src/common/string.cpp index 25f604519c..b2969ff04f 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -23,6 +23,7 @@ #ifndef WX_PRECOMP #include "wx/string.h" + #include "wx/wxcrtvararg.h" #endif #include @@ -1442,9 +1443,9 @@ bool wxString::ToDouble(double *val) const /* static */ #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN -wxString wxStringPrintfMixinBase::DoFormat(const wxChar *format, ...) +wxString wxStringPrintfMixinBase::DoFormat(const wxString& format, ...) #else -wxString wxString::DoFormat(const wxChar *format, ...) +wxString wxString::DoFormat(const wxString& format, ...) #endif { va_list argptr; @@ -1467,9 +1468,9 @@ wxString wxString::FormatV(const wxString& format, va_list argptr) } #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN -int wxStringPrintfMixinBase::DoPrintf(const wxChar *format, ...) +int wxStringPrintfMixinBase::DoPrintf(const wxString& format, ...) #else -int wxString::DoPrintf(const wxChar *format, ...) +int wxString::DoPrintf(const wxString& format, ...) #endif { va_list argptr; @@ -1491,14 +1492,27 @@ int wxString::DoPrintf(const wxChar *format, ...) return iLen; } -int wxString::PrintfV(const wxString& format, va_list argptr) +#if wxUSE_UNICODE_UTF8 +template +#else +// we only need one version in non-UTF8 builds and at least two Windows +// compilers have problems with this function template, so use just one +// normal function here +#endif +static int DoStringPrintfV(wxString& str, + const wxString& format, va_list argptr) { int size = 1024; for ( ;; ) { - wxStringBuffer tmp(*this, size + 1); +#if wxUSE_UNICODE_UTF8 + BufferType tmp(str, size + 1); + typename BufferType::CharType *buf = tmp; +#else + wxStringBuffer tmp(str, size + 1); wxChar *buf = tmp; +#endif if ( !buf ) { @@ -1510,7 +1524,7 @@ int wxString::PrintfV(const wxString& format, va_list argptr) // only a copy va_list argptrcopy; wxVaCopy(argptrcopy, argptr); - int len = wxVsnprintf(buf, size, (const wxChar*)/*FIXME-UTF8*/format, argptrcopy); + int len = wxVsnprintf(buf, size, format, argptrcopy); va_end(argptrcopy); // some implementations of vsnprintf() don't NUL terminate @@ -1554,9 +1568,37 @@ int wxString::PrintfV(const wxString& format, va_list argptr) } // we could have overshot - Shrink(); + str.Shrink(); + + return str.length(); +} - return length(); +int wxString::PrintfV(const wxString& format, va_list argptr) +{ + va_list argcopy; + wxVaCopy(argcopy, argptr); + +#if wxUSE_UNICODE_UTF8 + #if wxUSE_STL_BASED_WXSTRING + typedef wxStringTypeBuffer Utf8Buffer; + #else + typedef wxImplStringBuffer Utf8Buffer; + #endif +#endif + +#if wxUSE_UTF8_LOCALE_ONLY + return DoStringPrintfV(*this, format, argcopy); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + return DoStringPrintfV(*this, format, argcopy); + else + // wxChar* version + return DoStringPrintfV(*this, format, argcopy); + #else + return DoStringPrintfV(*this, format, argcopy); + #endif // UTF8/WCHAR +#endif } // ---------------------------------------------------------------------------- diff --git a/src/common/stringimpl.cpp b/src/common/stringimpl.cpp index ecf9ea5b1b..3cafa8bf80 100644 --- a/src/common/stringimpl.cpp +++ b/src/common/stringimpl.cpp @@ -752,7 +752,6 @@ bool wxStringImpl::ConcatSelf(size_t nSrcLen, return true; } -#if !wxUSE_UNICODE_UTF8 // get the pointer to writable buffer of (at least) nLen bytes wxStringCharType *wxStringImpl::DoGetWriteBuf(size_t nLen) { @@ -784,6 +783,5 @@ void wxStringImpl::DoUngetWriteBuf(size_t nLen) pData->nDataLength = nLen; pData->Validate(true); } -#endif // !wxUSE_UNICODE_UTF8 #endif // !wxUSE_STL_BASED_WXSTRING diff --git a/src/common/strvararg.cpp b/src/common/strvararg.cpp index 81288c6f89..f18e2f0bc1 100644 --- a/src/common/strvararg.cpp +++ b/src/common/strvararg.cpp @@ -24,116 +24,53 @@ #endif #include "wx/strvararg.h" -#include "wx/buffer.h" -#include "wx/strconv.h" #include "wx/string.h" // ============================================================================ // implementation // ============================================================================ -const wxChar *wxArgNormalizer::get() const -{ - // FIXME-UTF8: use some way that doesn't involve implicit conversion, - // so that we deallocate any converted buffer immediately; - // can't use AsString() because it returns wxString and not - // const wxString&, unfortunately; use As[W]CharBuf() when - // available. - return m_value; -} -const wxChar *wxArgNormalizer::get() const +const wxStringCharType *wxArgNormalizerNative::get() const { -#if wxUSE_UNICODE_UTF8 // FIXME-UTF8 - return (const wxChar*)m_value; -#else return m_value.wx_str(); -#endif -} - -#if wxUSE_UNICODE // FIXME-UTF8: should be wxUSE_UNICODE_WCHAR -wxArgNormalizer::wxArgNormalizer(const char *value) -{ - // FIXME-UTF8: move this to the header so that m_value doesn't have - // to be dynamically allocated - m_value = new wxWCharBuffer(wxConvLibc.cMB2WC(value)); -} - -wxArgNormalizer::~wxArgNormalizer() -{ - delete m_value; -} - -const wchar_t *wxArgNormalizer::get() const -{ - return m_value->data(); } -#endif // wxUSE_UNICODE_WCHAR - -#if /*wxUSE_UNICODE_UTF8 ||*/ !wxUSE_UNICODE // FIXME-UTF8 -wxArgNormalizer::wxArgNormalizer(const wchar_t *value) +const wxStringCharType *wxArgNormalizerNative::get() const { -#if wxUSE_UNICODE_UTF8 // FIXME-UTF8: this will be the only case - m_value = new wxCharBuffer(wxConvUTF8.cWC2MB(value)); -#else - m_value = new wxCharBuffer(wxConvLibc.cWC2MB(value)); -#endif + return m_value.AsInternal(); } -wxArgNormalizer::~wxArgNormalizer() +#if wxUSE_UNICODE_UTF8 +wxArgNormalizerWchar::wxArgNormalizerWchar(const wxString& s) + : wxArgNormalizerWithBuffer(s.wc_str()) { - delete m_value; } -const char *wxArgNormalizer::get() const +wxArgNormalizerWchar::wxArgNormalizerWchar(const wxCStrData& s) + : wxArgNormalizerWithBuffer(s.AsWCharBuf()) { - return m_value->data(); -} -#endif // wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE - -#if 0 // wxUSE_UNICODE_UTF8 - FIXME-UTF8 -wxArgNormalizer::wxArgNormalizer(const char *value) -{ - // FIXME-UTF8: move this to the header so that m_value doesn't have - // to be dynamically allocated - // FIXME-UTF8: optimize this if current locale is UTF-8 one - - // convert to widechar string first: - wxWCharBuffer buf(wxConvLibc.cMB2WC(value)); - - if ( buf ) - { - // then to UTF-8: - m_value = new wxCharBuffer(wxConvUTF8.cWC2MB(value)); - } - else - { - m_value = new wxCharBuffer(); - } -} - -wxArgNormalizer::~wxArgNormalizer() -{ - delete m_value; -} - -const char *wxArgNormalizer::get() const -{ - return m_value->data(); } #endif // wxUSE_UNICODE_UTF8 - - -// FIXME-UTF8: move this to the header once it's possible to include buffer.h -// without including wxcrt.h -wxArgNormalizer::wxArgNormalizer(const wxCharBuffer& buf) - : wxArgNormalizer(buf.data()) +wxString wxArgNormalizedString::GetString() const { + if ( !IsValid() ) + return wxEmptyString; + +#if wxUSE_UTF8_LOCALE_ONLY + return wxString(wx_reinterpret_cast(const char*, m_ptr)); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + return wxString(wx_reinterpret_cast(const char*, m_ptr)); + else + #endif + return wxString(wx_reinterpret_cast(const wchar_t*, m_ptr)); +#endif // !wxUSE_UTF8_LOCALE_ONLY } -wxArgNormalizer::wxArgNormalizer(const wxWCharBuffer& buf) - : wxArgNormalizer(buf.data()) +wxArgNormalizedString::operator wxString() const { + return GetString(); } diff --git a/src/common/wxcrt.cpp b/src/common/wxcrt.cpp index 15bc111642..7a1c9363bb 100644 --- a/src/common/wxcrt.cpp +++ b/src/common/wxcrt.cpp @@ -163,31 +163,16 @@ bool WXDLLEXPORT wxOKlibc() #undef wxVsprintf #undef wxVprintf #undef wxVsnprintf_ - #undef wxSnprintf_ #define wxNEED_WPRINTF int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr ); #endif -#if !defined(wxSnprintf_) -int WXDLLEXPORT wxDoSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - - int iLen = wxVsnprintf_(buf, len, format, argptr); - - va_end(argptr); - - return iLen; -} -#endif // wxSnprintf_ - #if defined(__DMC__) /* Digital Mars adds count to _stprintf (C99) so convert */ #if wxUSE_UNICODE - int wxDoSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... ) + int wxSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... ) { va_list arglist; @@ -527,7 +512,7 @@ wxString wxConvertFormat(const wxChar *format) #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF) -int wxDoScanf( const wxChar *format, ... ) +int wxCRT_Scanf( const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -539,7 +524,7 @@ int wxDoScanf( const wxChar *format, ... ) return ret; } -int wxDoSscanf( const wxChar *str, const wxChar *format, ... ) +int wxCRT_Sscanf( const wxChar *str, const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -551,7 +536,7 @@ int wxDoSscanf( const wxChar *str, const wxChar *format, ... ) return ret; } -int wxDoFscanf( FILE *stream, const wxChar *format, ... ) +int wxCRT_Fscanf( FILE *stream, const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -562,7 +547,7 @@ int wxDoFscanf( FILE *stream, const wxChar *format, ... ) return ret; } -int wxDoPrintf( const wxChar *format, ... ) +int wxCRT_Printf( const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -574,80 +559,247 @@ int wxDoPrintf( const wxChar *format, ... ) return ret; } -#ifndef wxSnprintf -int wxDoSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) +int wxCRT_Fprintf( FILE *stream, const wxChar *format, ... ) { va_list argptr; - va_start(argptr, format); - - int ret = vswprintf( str, size, wxFormatConverter(format), argptr ); + va_start( argptr, format ); - // VsnprintfTestCase reveals that glibc's implementation of vswprintf - // doesn't nul terminate on truncation. - str[size - 1] = 0; + int ret = vfwprintf( stream, wxFormatConverter(format), argptr ); va_end(argptr); return ret; } -#endif // wxSnprintf -int wxDoSprintf( wxChar *str, const wxChar *format, ... ) +int wxCRT_Vsscanf( const wxChar *str, const wxChar *format, va_list argptr ) +{ + return vswscanf( str, wxFormatConverter(format), argptr ); +} + +int wxCRT_Vfprintf( FILE *stream, const wxChar *format, va_list argptr ) +{ + return vfwprintf( stream, wxFormatConverter(format), argptr ); +} + +int wxCRT_Vprintf( const wxChar *format, va_list argptr ) +{ + return vwprintf( wxFormatConverter(format), argptr ); +} + +#ifndef wxCRT_Vsnprintf +int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr ) +{ + return vswprintf( str, size, wxFormatConverter(format), argptr ); +} +#endif // wxCRT_Vsnprintf + +int wxCRT_Vsprintf( wxChar *str, const wxChar *format, va_list argptr ) +{ + // same as for wxSprintf() + return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr); +} + +#endif // wxNEED_PRINTF_CONVERSION + + +// ---------------------------------------------------------------------------- +// wrappers to printf and scanf function families +// ---------------------------------------------------------------------------- + +int wxDoSprintf(char *str, const wxString& format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsprintf(str, format, argptr); + + va_end(argptr); + return rv; +} + +#if wxUSE_UNICODE +int wxDoSprintf(wchar_t *str, const wxString& format, ...) { va_list argptr; va_start(argptr, format); - // note that wxString::FormatV() uses wxVsnprintf(), not wxSprintf(), so - // it's safe to implement this one in terms of it - wxString s(wxString::FormatV(format, argptr)); - wxStrcpy(str, s); + int rv = wxVsprintf(str, format, argptr); va_end(argptr); + return rv; +} +#endif - return s.length(); +int wxDoSnprintf(char *str, size_t size, const wxString& format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsnprintf(str, size, format, argptr); + + va_end(argptr); + return rv; } -int wxDoFprintf( FILE *stream, const wxChar *format, ... ) +#if wxUSE_UNICODE +int wxDoSnprintf(wchar_t *str, size_t size, const wxString& format, ...) { va_list argptr; - va_start( argptr, format ); + va_start(argptr, format); - int ret = vfwprintf( stream, wxFormatConverter(format), argptr ); + int rv = wxVsnprintf(str, size, format, argptr); va_end(argptr); + return rv; +} +#endif - return ret; + +#ifdef HAVE_BROKEN_VSNPRINTF_DECL + #define vsnprintf wx_fixed_vsnprintf +#endif + +#if wxUSE_UNICODE +static int ConvertStringToBuf(const wxString& s, char *out, size_t outsize) +{ + const wxWX2WCbuf buf = s.wc_str(); + + size_t len = wxConvLibc.FromWChar(out, outsize, buf); + if ( len != wxCONV_FAILED ) + return len-1; + else + return wxConvLibc.FromWChar(NULL, 0, buf); } -int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr ) +#if wxUSE_UNICODE_UTF8 +static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize) { - return vswscanf( str, wxFormatConverter(format), argptr ); + const wxWX2WCbuf buf(s.wc_str()); + size_t len = wxWcslen(buf); + if ( outsize > len ) + memcpy(out, buf, (len+1) * sizeof(wchar_t)); + // else: not enough space + return len; } +#endif -int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr ) +template +static size_t PrintfViaString(T *out, size_t outsize, + const wxString& format, va_list argptr) { - return vfwprintf( stream, wxFormatConverter(format), argptr ); + va_list argcopy; + wxVaCopy(argcopy, argptr); + + wxString s; + s.PrintfV(format, argcopy); + + return ConvertStringToBuf(s, out, outsize); } +#endif // wxUSE_UNICODE -int wxVprintf( const wxChar *format, va_list argptr ) +int wxVsprintf(char *str, const wxString& format, va_list argptr) { - return vwprintf( wxFormatConverter(format), argptr ); + va_list argcopy; + wxVaCopy(argcopy, argptr); + +#if wxUSE_UTF8_LOCALE_ONLY + return vsprintf(str, format.wx_str(), argcopy); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + return vsprintf(str, format.wx_str(), argcopy); + else + #endif + #if wxUSE_UNICODE + return PrintfViaString(str, wxNO_LEN, format, argcopy); + #else + return wxCRT_Vsprintf(str, format, argcopy); + #endif +#endif } -#ifndef wxVsnprintf -int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr ) +#if wxUSE_UNICODE +int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr) { - return vswprintf( str, size, wxFormatConverter(format), argptr ); + va_list argcopy; + wxVaCopy(argcopy, argptr); + +#if wxUSE_UNICODE_WCHAR + return wxCRT_Vsprintf(str, format, argcopy); +#else // wxUSE_UNICODE_UTF8 + #if !wxUSE_UTF8_LOCALE_ONLY + if ( !wxLocaleIsUtf8 ) + return wxCRT_Vsprintf(str, format, argcopy); + else + #endif + return PrintfViaString(str, wxNO_LEN, format, argcopy); +#endif // wxUSE_UNICODE_UTF8 } -#endif // wxVsnprintf +#endif // wxUSE_UNICODE -int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr ) +int wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr) { - // same as for wxSprintf() - return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr); + int rv; + va_list argcopy; + wxVaCopy(argcopy, argptr); + +#if wxUSE_UTF8_LOCALE_ONLY + rv = vsnprintf(str, size, format.wx_str(), argcopy); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + rv = vsnprintf(str, size, format.wx_str(), argcopy); + else + #endif + #if wxUSE_UNICODE + { + // NB: if this code is called, then wxString::PrintV() would use the + // wchar_t* version of wxVsnprintf(), so it's safe to use PrintV() + // from here + rv = PrintfViaString(str, size, format, argcopy); + } + #else + rv = wxCRT_Vsnprintf(str, size, format, argcopy); + #endif +#endif + + // VsnprintfTestCase reveals that glibc's implementation of vswprintf + // doesn't nul terminate on truncation. + str[size - 1] = 0; + + return rv; } -#endif // wxNEED_PRINTF_CONVERSION +#if wxUSE_UNICODE +int wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr) +{ + int rv; + va_list argcopy; + wxVaCopy(argcopy, argptr); + +#if wxUSE_UNICODE_WCHAR + rv = wxCRT_Vsnprintf(str, size, format, argcopy); +#else // wxUSE_UNICODE_UTF8 + #if !wxUSE_UTF8_LOCALE_ONLY + if ( !wxLocaleIsUtf8 ) + rv = wxCRT_Vsnprintf(str, size, format, argcopy); + else + #endif + { + // NB: if this code is called, then wxString::PrintV() would use the + // char* version of wxVsnprintf(), so it's safe to use PrintV() + // from here + rv = PrintfViaString(str, size, format, argcopy); + } +#endif // wxUSE_UNICODE_UTF8 + + // VsnprintfTestCase reveals that glibc's implementation of vswprintf + // doesn't nul terminate on truncation. + str[size - 1] = 0; + + return rv; +} +#endif // wxUSE_UNICODE #if wxUSE_WCHAR_T diff --git a/src/common/wxprintf.cpp b/src/common/wxprintf.cpp index 5f8cef2b8c..4aed1cad1f 100644 --- a/src/common/wxprintf.cpp +++ b/src/common/wxprintf.cpp @@ -143,8 +143,7 @@ typedef union { char pad_char; // %hc (in ANSI mode: %c, too) wchar_t pad_wchar; // %lc (in Unicode mode: %c, too) - char *pad_pchar; // %s (related to a char *) - wchar_t *pad_pwchar; // %s (related to a wchar_t *) + void *pad_str; // %s int *pad_nint; // %n short int *pad_nshortint; // %hn @@ -616,10 +615,8 @@ bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr) break; case wxPAT_PCHAR: - p->pad_pchar = va_arg(argptr, char *); - break; case wxPAT_PWCHAR: - p->pad_pwchar = va_arg(argptr, wchar_t *); + p->pad_str = va_arg(argptr, void *); break; case wxPAT_NINT: @@ -735,54 +732,15 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p, size_t case wxPAT_PCHAR: case wxPAT_PWCHAR: { - wxString s; - const wxChar *val = -#if wxUSE_UNICODE - p->pad_pwchar; - - if (m_type == wxPAT_PCHAR) - { - // user passed a string explicitely indicated as ANSI... - val = s = wxString(p->pad_pchar, wxConvLibc); + wxArgNormalizedString arg(p->pad_str); + wxString s = arg; - //wprintf(L"converting ANSI=>Unicode"); // for debug - } -#else - p->pad_pchar; + if ( !arg.IsValid() && m_nMaxWidth >= 6 ) + s = wxT("(null)"); -#if wxUSE_WCHAR_T - if (m_type == wxPAT_PWCHAR) - { - // user passed a string explicitely indicated as Unicode... - val = s = wxString(p->pad_pwchar, wxConvLibc); - - //printf("converting Unicode=>ANSI"); // for debug - } -#endif -#endif - int len; - - if (val) - { -#if wxUSE_STRUTILS - // at this point we are sure that m_nMaxWidth is positive or null - // (see top of wxPrintfConvSpec::LoadArg) - len = wxMin((unsigned int)m_nMaxWidth, wxStrlen(val)); -#else - for ( len = 0; val[len] && (len < m_nMaxWidth); len++ ) - ; -#endif - } - else if (m_nMaxWidth >= 6) - { - val = wxT("(null)"); - len = 6; - } - else - { - val = wxEmptyString; - len = 0; - } + // at this point we are sure that m_nMaxWidth is positive or + // null (see top of wxPrintfConvSpec::LoadArg) + int len = wxMin((unsigned int)m_nMaxWidth, s.length()); int i; @@ -794,11 +752,16 @@ int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p, size_t #if wxUSE_STRUTILS len = wxMin((unsigned int)len, lenMax-lenCur); - wxStrncpy(buf+lenCur, val, len); + #if wxUSE_UNICODE // FIXME-UTF8 + wxStrncpy(buf+lenCur, s.wc_str(), len); + #else + wxStrncpy(buf+lenCur, s.mb_str(), len); + #endif lenCur += len; #else - for (i = 0; i < len; i++) - APPEND_CH(val[i]); + wxString::const_iterator end = s.begin() + len; + for (wxString::const_iterator j = s.begin(); j != end; ++j) + APPEND_CH(*j); #endif if (m_bAlignLeft) diff --git a/src/generic/logg.cpp b/src/generic/logg.cpp index 8547e03461..dc74164100 100644 --- a/src/generic/logg.cpp +++ b/src/generic/logg.cpp @@ -205,13 +205,13 @@ static wxFrame *gs_pFrame = NULL; // FIXME MT-unsafe // accepts an additional argument which tells to which frame the output should // be directed -void wxVLogStatus(wxFrame *pFrame, const wxChar *szFormat, va_list argptr) +void wxVLogStatus(wxFrame *pFrame, const wxString& format, va_list argptr) { wxString msg; wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL ) { - msg.PrintfV(szFormat, argptr); + msg.PrintfV(format, argptr); wxASSERT( gs_pFrame == NULL ); // should be reset! gs_pFrame = pFrame; @@ -224,11 +224,11 @@ void wxVLogStatus(wxFrame *pFrame, const wxChar *szFormat, va_list argptr) } } -void wxDoLogStatus(wxFrame *pFrame, const wxChar *szFormat, ...) +void wxDoLogStatus(wxFrame *pFrame, const wxString& format, ...) { va_list argptr; - va_start(argptr, szFormat); - wxVLogStatus(pFrame, szFormat, argptr); + va_start(argptr, format); + wxVLogStatus(pFrame, format, argptr); va_end(argptr); } @@ -588,7 +588,7 @@ void wxLogFrame::OnSave(wxCommandEvent& WXUNUSED(event)) wxLogError(_("Can't save log contents to file.")); } else { - wxLogStatus(this, _("Log saved to the file '%s'."), filename.c_str()); + wxLogStatus((wxFrame*)this, _("Log saved to the file '%s'."), filename.c_str()); } #endif } -- 2.45.2