#include "wx/cpp.h"
#include "wx/chartype.h"
-#include "wx/wxcrt.h"
#include "wx/strconv.h"
#include "wx/buffer.h"
+#include "wx/unichar.h"
-class WXDLLIMPEXP_BASE wxCStrData;
-class WXDLLIMPEXP_BASE wxString;
+class WXDLLIMPEXP_FWD_BASE wxCStrData;
+class WXDLLIMPEXP_FWD_BASE wxString;
// ----------------------------------------------------------------------------
// WX_DEFINE_VARARG_FUNC* macros
// * wchar_t* if wxUSE_UNICODE_WCHAR or if wxUSE_UNICODE_UTF8 and the current
// locale is not UTF-8
//
+// Note that wxFormatString *must* be used for the format parameter of these
+// functions, otherwise the implementation won't work correctly.
+//
// Parameters:
// [ there are examples in square brackets showing values of the parameters
// for the wxFprintf() wrapper for fprintf() function with the following
// if wxUSE_UNICODE_UTF8 and running under UTF-8 locale
// (ignored otherwise) [fprintf]
//
-#define WX_DEFINE_VARARG_FUNC2(rettype, name, numfixed, fixed, impl, implUtf8)\
+#define WX_DEFINE_VARARG_FUNC(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)
+ WX_DEFINE_VARARG_FUNC_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, \
+#define WX_DEFINE_VARARG_FUNC_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
+// Like WX_DEFINE_VARARG_FUNC, but for variadic functions that don't return
// a value.
-#define WX_DEFINE_VARARG_FUNC_VOID2(name, numfixed, fixed, impl, implUtf8) \
+#define WX_DEFINE_VARARG_FUNC_VOID(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.
//
_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)
+ void, name, dummy, 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) \
+#define WX_DEFINE_VARARG_FUNC_CTOR(name, numfixed, fixed, impl, implUtf8) \
+ _WX_VARARG_DEFINE_FUNC_CTOR_N0(name, impl, implUtf8, numfixed, fixed) \
_WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \
_WX_VARARG_DEFINE_FUNC_CTOR, \
- void, name, impl, impl, numfixed, fixed)
+ void, name, impl, implUtf8, numfixed, fixed)
+
+
+// ----------------------------------------------------------------------------
+// wxFormatString
+// ----------------------------------------------------------------------------
+
+// This class must be used for format string argument of the functions
+// defined using WX_DEFINE_VARARG_FUNC_* macros. It converts the string to
+// char* or wchar_t* for passing to implementation function efficiently (i.e.
+// without keeping the converted string in memory for longer than necessary,
+// like c_str()). It also converts format string to the correct form that
+// accounts for string changes done by wxArgNormalizer<>
+//
+// Note that this class can _only_ be used for function arguments!
+class WXDLLIMPEXP_BASE wxFormatString
+{
+public:
+ wxFormatString(const char *str)
+ : m_char(wxCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wchar_t *str)
+ : m_wchar(wxWCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wxString& str)
+ : m_str(&str), m_cstr(NULL) {}
+ wxFormatString(const wxCStrData& str)
+ : m_str(NULL), m_cstr(&str) {}
+ wxFormatString(const wxCharBuffer& str)
+ : m_char(str), m_str(NULL), m_cstr(NULL) {}
+ wxFormatString(const wxWCharBuffer& str)
+ : m_wchar(str), m_str(NULL), m_cstr(NULL) {}
+
+#if !wxUSE_UNICODE_WCHAR
+ operator const char*() const
+ { return wx_const_cast(wxFormatString*, this)->AsChar(); }
+private:
+ // InputAsChar() returns the value converted passed to ctor, only converted
+ // to char, while AsChar() takes the the string returned by InputAsChar()
+ // and does format string conversion on it as well (and similarly for
+ // ..AsWChar() below)
+ const char* InputAsChar();
+ const char* AsChar();
+ wxCharBuffer m_convertedChar;
+#endif // !wxUSE_UNICODE_WCHAR
+
+#if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
+public:
+ operator const wchar_t*() const
+ { return wx_const_cast(wxFormatString*, this)->AsWChar(); }
+private:
+ const wchar_t* InputAsWChar();
+ const wchar_t* AsWChar();
+ wxWCharBuffer m_convertedWChar;
+#endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
+
+private:
+#ifdef __VISUALC__
+ // "struct 'ConvertedBuffer<T>' needs to have dll-interface to be used by
+ // clients of class 'wxString'" - this is private, we don't care
+ #pragma warning (disable:4251)
+#endif
+ wxCharBuffer m_char;
+ wxWCharBuffer m_wchar;
+#ifdef __VISUALC__
+ #pragma warning (default:4251)
+#endif
+
+ // NB: we can use a pointer here, because wxFormatString is only used
+ // as function argument, so it has shorter life than the string
+ // passed to the ctor
+ const wxString * const m_str;
+ const wxCStrData * const m_cstr;
+
+ DECLARE_NO_COPY_CLASS(wxFormatString)
+};
// ----------------------------------------------------------------------------
// wxArgNormalizer*<T> converters
// Returns the value in a form that can be safely passed to real vararg
// functions. In case of strings, this is char* in ANSI build and wchar_t*
// in Unicode build.
- const T& get() const { return m_value; }
+ T get() const { return m_value; }
- const T& m_value;
+ T m_value;
};
// normalizer for passing arguments to functions working with wchar_t* (and
{
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));
-
- // then to UTF-8:
- if ( buf )
- m_value = wxConvUTF8.cWC2MB(buf);
+ if ( wxLocaleIsUtf8 )
+ {
+ m_value = wxCharBuffer::CreateNonOwned(s);
+ }
+ else
+ {
+ // convert to widechar string first:
+ wxWCharBuffer buf(wxConvLibc.cMB2WC(s));
+
+ // then to UTF-8:
+ if ( buf )
+ m_value = wxConvUTF8.cWC2MB(buf);
+ }
}
};
WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*);
WX_ARG_NORMALIZER_FORWARD(const wxWCharBuffer&, const wchar_t*);
+// versions for std::[w]string:
+#if wxUSE_STD_STRING
+
+#include "wx/stringimpl.h"
+
+#if !wxUSE_UTF8_LOCALE_ONLY
+template<>
+struct wxArgNormalizerWchar<const std::string&>
+ : public wxArgNormalizerWchar<const char*>
+{
+ wxArgNormalizerWchar(const std::string& s)
+ : wxArgNormalizerWchar<const char*>(s.c_str()) {}
+};
+
+template<>
+struct wxArgNormalizerWchar<const wxStdWideString&>
+ : public wxArgNormalizerWchar<const wchar_t*>
+{
+ wxArgNormalizerWchar(const wxStdWideString& s)
+ : wxArgNormalizerWchar<const wchar_t*>(s.c_str()) {}
+};
+#endif // !wxUSE_UTF8_LOCALE_ONLY
+
+#if wxUSE_UNICODE_UTF8
+template<>
+struct wxArgNormalizerUtf8<const std::string&>
+ : public wxArgNormalizerUtf8<const char*>
+{
+ wxArgNormalizerUtf8(const std::string& s)
+ : wxArgNormalizerUtf8<const char*>(s.c_str()) {}
+};
+
+template<>
+struct wxArgNormalizerUtf8<const wxStdWideString&>
+ : public wxArgNormalizerUtf8<const wchar_t*>
+{
+ wxArgNormalizerUtf8(const wxStdWideString& s)
+ : wxArgNormalizerUtf8<const wchar_t*>(s.c_str()) {}
+};
+#endif // wxUSE_UNICODE_UTF8
+
+WX_ARG_NORMALIZER_FORWARD(std::string, const std::string&);
+WX_ARG_NORMALIZER_FORWARD(wxStdWideString, const wxStdWideString&);
+
+#endif // wxUSE_STD_STRING
+
+
+// versions for wxUniChar, wxUniCharRef:
+
+#if !wxUSE_UTF8_LOCALE_ONLY
+template<>
+struct wxArgNormalizerWchar<const wxUniChar&>
+{
+ wxArgNormalizerWchar(const wxUniChar& s) : m_value(s) {}
+
+ // FIXME-UTF8: use wchar_t once ANSI build is removed
+ wxChar get() const { return m_value; }
+
+ wxChar m_value;
+};
+#endif // !wxUSE_UTF8_LOCALE_ONLY
+
+#if wxUSE_UNICODE_UTF8
+template<>
+struct wxArgNormalizerUtf8<const wxUniChar&>
+{
+ wxArgNormalizerUtf8(const wxUniChar& s) : m_value(s.AsUTF8()) {}
+
+ const wxStringCharType *get() const { return m_value; }
+
+ wxUniChar::Utf8CharBuffer m_value;
+};
+#endif // wxUSE_UNICODE_UTF8
+
+WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&);
+// convert char/wchar_t to wxUniChar to get output in the right encoding:
+WX_ARG_NORMALIZER_FORWARD(char, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(const char&, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(unsigned char, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(const unsigned char&, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(wchar_t, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(const wchar_t&, const wxUniChar&);
+
+
#undef WX_ARG_NORMALIZER_FORWARD
#undef _WX_ARG_NORMALIZER_FORWARD_IMPL
#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)
+#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
inline void name(_WX_VARARG_FIXED_UNUSED_EXPAND(numfixed, fixed)) \
{}
+
+// ----------------------------------------------------------------------------
+// workaround for OpenWatcom bug #351
+// ----------------------------------------------------------------------------
+
+#ifdef __WATCOMC__
+// workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+
+// This macro can be used to forward a 'vararg' template to another one with
+// different fixed arguments types. Parameters are same as for
+// WX_DEFINE_VARARG_FUNC (rettype=void can be used here), 'convfixed' is how
+// to convert fixed arguments. For example, this is typical code for dealing
+// with different forms of format string:
+//
+// WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxFormatString&),
+// DoPrintfWchar, DoPrintfUtf8)
+// #ifdef __WATCOMC__
+// WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const wxString&),
+// (wxFormatString(f1)))
+// WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const char*),
+// (wxFormatString(f1)))
+// ...
+#define WX_VARARG_WATCOM_WORKAROUND(rettype, name, numfixed, fixed, convfixed)\
+ _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \
+ _WX_VARARG_WATCOM_WORKAROUND, \
+ rettype, name, convfixed, dummy, numfixed, fixed)
+
+#define WX_VARARG_WATCOM_WORKAROUND_CTOR(name, numfixed, fixed, convfixed) \
+ _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \
+ _WX_VARARG_WATCOM_WORKAROUND_CTOR, \
+ dummy, name, convfixed, dummy, numfixed, fixed)
+
+#define _WX_VARARG_WATCOM_UNPACK_1(a1) a1
+#define _WX_VARARG_WATCOM_UNPACK_2(a1, a2) a1, a2
+#define _WX_VARARG_WATCOM_UNPACK_3(a1, a2, a3) a1, a2, a3
+#define _WX_VARARG_WATCOM_UNPACK_4(a1, a2, a3, a4) a1, a2, a3, a4
+#define _WX_VARARG_WATCOM_UNPACK(N, convfixed) \
+ _WX_VARARG_WATCOM_UNPACK_##N convfixed
+
+#define _WX_VARARG_WATCOM_WORKAROUND(N, rettype, name, \
+ convfixed, dummy, 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)) \
+ { \
+ return name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed), \
+ _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR)); \
+ }
+
+#define _WX_VARARG_WATCOM_WORKAROUND_CTOR(N, dummy1, name, \
+ convfixed, dummy2, numfixed, fixed) \
+ template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)> \
+ name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed), \
+ _WX_VARARG_JOIN(N, _WX_VARARG_ARG)) \
+ { \
+ name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed), \
+ _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR)); \
+ }
+
+#endif // __WATCOMC__
+
#endif // _WX_STRVARARG_H_