]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/strvararg.h
no changes, just remove #if'd out code
[wxWidgets.git] / include / wx / strvararg.h
index ee87423fa786344bf36ff4867bb4db7d76f78087..29b4ae041bfa3b037ee2e5a99d308fb5715780f1 100644 (file)
@@ -22,8 +22,8 @@
 #include "wx/buffer.h"
 #include "wx/unichar.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
 
 // ----------------------------------------------------------------------------
 // WX_DEFINE_VARARG_FUNC* macros
@@ -47,6 +47,11 @@ class WXDLLIMPEXP_BASE wxString;
 //   * wchar_t* if wxUSE_UNICODE_WCHAR or if wxUSE_UNICODE_UTF8 and the current
 //     locale is not UTF-8
 //
 //   * 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. Furthermore,
+// it must be passed by value, not reference, because it's modified by the
+// vararg templates internally.
+//
 // Parameters:
 // [ there are examples in square brackets showing values of the parameters
 //   for the wxFprintf() wrapper for fprintf() function with the following
 // Parameters:
 // [ there are examples in square brackets showing values of the parameters
 //   for the wxFprintf() wrapper for fprintf() function with the following
@@ -111,55 +116,74 @@ class WXDLLIMPEXP_BASE wxString;
 // wxFormatString
 // ----------------------------------------------------------------------------
 
 // wxFormatString
 // ----------------------------------------------------------------------------
 
-// This class should be used for format string argument of the functions
+// 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,
 // 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())
+// 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)
 //
 // 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) {}
+        : m_char(wxScopedCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
     wxFormatString(const wchar_t *str)
     wxFormatString(const wchar_t *str)
-        : m_wchar(wxWCharBuffer::CreateNonOwned(str)), m_str(NULL), m_cstr(NULL) {}
+        : m_wchar(wxScopedWCharBuffer::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 wxString& str)
         : m_str(&str), m_cstr(NULL) {}
     wxFormatString(const wxCStrData& str)
         : m_str(NULL), m_cstr(&str) {}
-    wxFormatString(const wxCharBuffer& str)
+    wxFormatString(const wxScopedCharBuffer& str)
         : m_char(str), m_str(NULL), m_cstr(NULL)  {}
         : m_char(str), m_str(NULL), m_cstr(NULL)  {}
-    wxFormatString(const wxWCharBuffer& str)
+    wxFormatString(const wxScopedWCharBuffer& str)
         : m_wchar(str), m_str(NULL), m_cstr(NULL) {}
 
         : m_wchar(str), m_str(NULL), m_cstr(NULL) {}
 
+
+    enum ArgumentType
+    {
+        Arg_Char,    // character as char
+
+        Arg_Other    // something else, for example int for %d
+    };
+
+    // returns the type of format specifier for n-th variadic argument (this is
+    // not necessarily n-th format specifier if positional specifiers are used);
+    // called by wxArgNormalizer<> specializations to get information about
+    // n-th variadic argument desired representation
+    ArgumentType GetArgumentType(unsigned n) const;
+
+    // returns the value passed to ctor, only converted to wxString, similarly
+    // to other InputAsXXX() methods
+    wxString InputAsString() const;
+
 #if !wxUSE_UNICODE_WCHAR
     operator const char*() const
 #if !wxUSE_UNICODE_WCHAR
     operator const char*() const
-        { return wx_const_cast(wxFormatString*, this)->AsChar(); }
+        { return const_cast<wxFormatString*>(this)->AsChar(); }
 private:
 private:
+    // InputAsChar() returns the value 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();
     const char* AsChar();
+    wxScopedCharBuffer m_convertedChar;
 #endif // !wxUSE_UNICODE_WCHAR
 
 #if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
 public:
     operator const wchar_t*() const
 #endif // !wxUSE_UNICODE_WCHAR
 
 #if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
 public:
     operator const wchar_t*() const
-        { return wx_const_cast(wxFormatString*, this)->AsWChar(); }
+        { return const_cast<wxFormatString*>(this)->AsWChar(); }
 private:
 private:
+    const wchar_t* InputAsWChar();
     const wchar_t* AsWChar();
     const wchar_t* AsWChar();
+    wxScopedWCharBuffer m_convertedWChar;
 #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
 
 private:
 #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
+    wxScopedCharBuffer  m_char;
+    wxScopedWCharBuffer m_wchar;
 
     // NB: we can use a pointer here, because wxFormatString is only used
     //     as function argument, so it has shorter life than the string
 
     // NB: we can use a pointer here, because wxFormatString is only used
     //     as function argument, so it has shorter life than the string
@@ -167,9 +191,71 @@ private:
     const wxString * const m_str;
     const wxCStrData * const m_cstr;
 
     const wxString * const m_str;
     const wxCStrData * const m_cstr;
 
-    DECLARE_NO_COPY_CLASS(wxFormatString)
+    wxDECLARE_NO_ASSIGN_CLASS(wxFormatString);
+};
+
+// these two helper classes are used to find wxFormatString argument among fixed
+// arguments passed to a vararg template
+struct wxFormatStringArgument
+{
+    wxFormatStringArgument(const wxFormatString *s = NULL) : m_str(s) {}
+    const wxFormatString *m_str;
+
+    // overriding this operator allows us to reuse _WX_VARARG_JOIN macro
+    wxFormatStringArgument operator,(const wxFormatStringArgument& a) const
+    {
+        wxASSERT_MSG( m_str == NULL || a.m_str == NULL,
+                      "can't have two format strings in vararg function" );
+        return wxFormatStringArgument(m_str ? m_str : a.m_str);
+    }
+
+    operator const wxFormatString*() const { return m_str; }
 };
 
 };
 
+template<typename T>
+struct wxFormatStringArgumentFinder
+{
+    static wxFormatStringArgument find(T)
+    {
+        // by default, arguments are not format strings, so return "not found"
+        return wxFormatStringArgument();
+    }
+};
+
+template<>
+struct wxFormatStringArgumentFinder<const wxFormatString&>
+{
+    static wxFormatStringArgument find(const wxFormatString& arg)
+        { return wxFormatStringArgument(&arg); }
+};
+
+template<>
+struct wxFormatStringArgumentFinder<wxFormatString>
+    : public wxFormatStringArgumentFinder<const wxFormatString&> {};
+
+// avoid passing big objects by value to wxFormatStringArgumentFinder::find()
+// (and especially wx[W]CharBuffer with its auto_ptr<> style semantics!):
+template<>
+struct wxFormatStringArgumentFinder<wxString>
+    : public wxFormatStringArgumentFinder<const wxString&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxScopedCharBuffer>
+    : public wxFormatStringArgumentFinder<const wxScopedCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxScopedWCharBuffer>
+    : public wxFormatStringArgumentFinder<const wxScopedWCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxCharBuffer>
+    : public wxFormatStringArgumentFinder<const wxCharBuffer&> {};
+
+template<>
+struct wxFormatStringArgumentFinder<wxWCharBuffer>
+    : public wxFormatStringArgumentFinder<const wxWCharBuffer&> {};
+
+
 // ----------------------------------------------------------------------------
 // wxArgNormalizer*<T> converters
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxArgNormalizer*<T> converters
 // ----------------------------------------------------------------------------
@@ -180,7 +266,13 @@ private:
 template<typename T>
 struct wxArgNormalizer
 {
 template<typename T>
 struct wxArgNormalizer
 {
-    wxArgNormalizer(const T& value) : m_value(value) {}
+    // Ctor. 'value' is the value passed as variadic argument, 'fmt' is pointer
+    // to printf-like format string or NULL if the variadic function doesn't
+    // use format string and 'index' is index of 'value' in variadic arguments
+    // list (starting at 1)
+    wxArgNormalizer(T value,
+                    const wxFormatString *WXUNUSED(fmt), unsigned WXUNUSED(index))
+        : m_value(value) {}
 
     // 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*
 
     // 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*
@@ -197,7 +289,9 @@ struct wxArgNormalizer
 template<typename T>
 struct wxArgNormalizerWchar : public wxArgNormalizer<T>
 {
 template<typename T>
 struct wxArgNormalizerWchar : public wxArgNormalizer<T>
 {
-    wxArgNormalizerWchar(const T& value) : wxArgNormalizer<T>(value) {}
+    wxArgNormalizerWchar(T value,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizer<T>(value, fmt, index) {}
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
@@ -207,7 +301,9 @@ struct wxArgNormalizerWchar : public wxArgNormalizer<T>
     template<typename T>
     struct wxArgNormalizerUtf8 : public wxArgNormalizer<T>
     {
     template<typename T>
     struct wxArgNormalizerUtf8 : public wxArgNormalizer<T>
     {
-        wxArgNormalizerUtf8(const T& value) : wxArgNormalizer<T>(value) {}
+        wxArgNormalizerUtf8(T value,
+                            const wxFormatString *fmt, unsigned index)
+            : wxArgNormalizer<T>(value, fmt, index) {}
     };
 
     #define wxArgNormalizerNative wxArgNormalizerUtf8
     };
 
     #define wxArgNormalizerNative wxArgNormalizerUtf8
@@ -226,10 +322,13 @@ struct wxArgNormalizerWchar : public wxArgNormalizer<T>
 template<typename CharType>
 struct wxArgNormalizerWithBuffer
 {
 template<typename CharType>
 struct wxArgNormalizerWithBuffer
 {
-    typedef wxCharTypeBuffer<CharType> CharBuffer;
+    typedef wxScopedCharTypeBuffer<CharType> CharBuffer;
 
     wxArgNormalizerWithBuffer() {}
 
     wxArgNormalizerWithBuffer() {}
-    wxArgNormalizerWithBuffer(const CharBuffer& buf) : m_value(buf) {}
+    wxArgNormalizerWithBuffer(const CharBuffer& buf,
+                              const wxFormatString *WXUNUSED(fmt),
+                              unsigned WXUNUSED(index))
+        : m_value(buf) {}
 
     const CharType *get() const { return m_value; }
 
 
     const CharType *get() const { return m_value; }
 
@@ -240,7 +339,11 @@ struct wxArgNormalizerWithBuffer
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&>
 {
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&>
 {
-    wxArgNormalizerNative(const wxString& s) : m_value(s) {}
+    wxArgNormalizerNative(const wxString& s,
+                          const wxFormatString *WXUNUSED(fmt),
+                          unsigned WXUNUSED(index))
+        : m_value(s) {}
+
     const wxStringCharType *get() const;
 
     const wxString& m_value;
     const wxStringCharType *get() const;
 
     const wxString& m_value;
@@ -250,7 +353,11 @@ struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&>
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&>
 {
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&>
 {
-    wxArgNormalizerNative(const wxCStrData& value) : m_value(value) {}
+    wxArgNormalizerNative(const wxCStrData& value,
+                          const wxFormatString *WXUNUSED(fmt),
+                          unsigned WXUNUSED(index))
+        : m_value(value) {}
+
     const wxStringCharType *get() const;
 
     const wxCStrData& m_value;
     const wxStringCharType *get() const;
 
     const wxCStrData& m_value;
@@ -262,14 +369,16 @@ template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxString&>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
 struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxString&>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
-    wxArgNormalizerWchar(const wxString& s);
+    wxArgNormalizerWchar(const wxString& s,
+                         const wxFormatString *fmt, unsigned index);
 };
 
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxCStrData&>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
 };
 
 template<>
 struct WXDLLIMPEXP_BASE wxArgNormalizerWchar<const wxCStrData&>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
-    wxArgNormalizerWchar(const wxCStrData& s);
+    wxArgNormalizerWchar(const wxCStrData& s,
+                         const wxFormatString *fmt, unsigned index);
 };
 #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
 
 };
 #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
 
@@ -282,8 +391,9 @@ template<>
 struct wxArgNormalizerWchar<const char*>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
 struct wxArgNormalizerWchar<const char*>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
-    wxArgNormalizerWchar(const char* s)
-        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s)) {}
+    wxArgNormalizerWchar(const char* s,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {}
 };
 
 #elif wxUSE_UNICODE_UTF8
 };
 
 #elif wxUSE_UNICODE_UTF8
@@ -292,24 +402,27 @@ template<>
 struct wxArgNormalizerUtf8<const wchar_t*>
     : public wxArgNormalizerWithBuffer<char>
 {
 struct wxArgNormalizerUtf8<const wchar_t*>
     : public wxArgNormalizerWithBuffer<char>
 {
-    wxArgNormalizerUtf8(const wchar_t* s)
-        : wxArgNormalizerWithBuffer<char>(wxConvUTF8.cWC2MB(s)) {}
+    wxArgNormalizerUtf8(const wchar_t* s,
+                        const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWithBuffer<char>(wxConvUTF8.cWC2MB(s), fmt, index) {}
 };
 
 template<>
 struct wxArgNormalizerUtf8<const char*>
     : public wxArgNormalizerWithBuffer<char>
 {
 };
 
 template<>
 struct wxArgNormalizerUtf8<const char*>
     : public wxArgNormalizerWithBuffer<char>
 {
-    wxArgNormalizerUtf8(const char* s)
+    wxArgNormalizerUtf8(const char* s,
+                        const wxFormatString *WXUNUSED(fmt),
+                        unsigned WXUNUSED(index))
     {
         if ( wxLocaleIsUtf8 )
         {
     {
         if ( wxLocaleIsUtf8 )
         {
-            m_value = wxCharBuffer::CreateNonOwned(s);
+            m_value = wxScopedCharBuffer::CreateNonOwned(s);
         }
         else
         {
             // convert to widechar string first:
         }
         else
         {
             // convert to widechar string first:
-            wxWCharBuffer buf(wxConvLibc.cMB2WC(s));
+            wxScopedWCharBuffer buf(wxConvLibc.cMB2WC(s));
 
             // then to UTF-8:
             if ( buf )
 
             // then to UTF-8:
             if ( buf )
@@ -324,8 +437,9 @@ template<>
 struct wxArgNormalizerWchar<const char*>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
 struct wxArgNormalizerWchar<const char*>
     : public wxArgNormalizerWithBuffer<wchar_t>
 {
-    wxArgNormalizerWchar(const char* s)
-        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s)) {}
+    wxArgNormalizerWchar(const char* s,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWithBuffer<wchar_t>(wxConvLibc.cMB2WC(s), fmt, index) {}
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
@@ -335,8 +449,9 @@ template<>
 struct wxArgNormalizerWchar<const wchar_t*>
     : public wxArgNormalizerWithBuffer<char>
 {
 struct wxArgNormalizerWchar<const wchar_t*>
     : public wxArgNormalizerWithBuffer<char>
 {
-    wxArgNormalizerWchar(const wchar_t* s)
-        : wxArgNormalizerWithBuffer<char>(wxConvLibc.cWC2MB(s)) {}
+    wxArgNormalizerWchar(const wchar_t* s,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWithBuffer<char>(wxConvLibc.cWC2MB(s), fmt, index) {}
 };
 
 #endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8/ANSI
 };
 
 #endif // wxUSE_UNICODE_WCHAR/wxUSE_UNICODE_UTF8/ANSI
@@ -364,7 +479,9 @@ struct wxArgNormalizerWchar<const wchar_t*>
     template<>                                                              \
     struct Normalizer<T> : public Normalizer<BaseT>                         \
     {                                                                       \
     template<>                                                              \
     struct Normalizer<T> : public Normalizer<BaseT>                         \
     {                                                                       \
-        Normalizer(BaseT value) : Normalizer<BaseT>(value) {}               \
+        Normalizer(BaseT value,                                             \
+                   const wxFormatString *fmt, unsigned index)               \
+            : Normalizer<BaseT>(value, fmt, index) {}                       \
     }
 
 // non-reference versions of specializations for string objects
     }
 
 // non-reference versions of specializations for string objects
@@ -376,6 +493,10 @@ 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(wchar_t*, const wchar_t*);
 
 // versions for passing wx[W]CharBuffer:
+WX_ARG_NORMALIZER_FORWARD(wxScopedCharBuffer, const char*);
+WX_ARG_NORMALIZER_FORWARD(const wxScopedCharBuffer&, const char*);
+WX_ARG_NORMALIZER_FORWARD(wxScopedWCharBuffer, const wchar_t*);
+WX_ARG_NORMALIZER_FORWARD(const wxScopedWCharBuffer&, const wchar_t*);
 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(wxCharBuffer, const char*);
 WX_ARG_NORMALIZER_FORWARD(const wxCharBuffer&, const char*);
 WX_ARG_NORMALIZER_FORWARD(wxWCharBuffer, const wchar_t*);
@@ -391,16 +512,18 @@ template<>
 struct wxArgNormalizerWchar<const std::string&>
     : public wxArgNormalizerWchar<const char*>
 {
 struct wxArgNormalizerWchar<const std::string&>
     : public wxArgNormalizerWchar<const char*>
 {
-    wxArgNormalizerWchar(const std::string& s)
-        : wxArgNormalizerWchar<const char*>(s.c_str()) {}
+    wxArgNormalizerWchar(const std::string& s,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWchar<const char*>(s.c_str(), fmt, index) {}
 };
 
 template<>
 struct wxArgNormalizerWchar<const wxStdWideString&>
     : public wxArgNormalizerWchar<const wchar_t*>
 {
 };
 
 template<>
 struct wxArgNormalizerWchar<const wxStdWideString&>
     : public wxArgNormalizerWchar<const wchar_t*>
 {
-    wxArgNormalizerWchar(const wxStdWideString& s)
-        : wxArgNormalizerWchar<const wchar_t*>(s.c_str()) {}
+    wxArgNormalizerWchar(const wxStdWideString& s,
+                         const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerWchar<const wchar_t*>(s.c_str(), fmt, index) {}
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
 };
 #endif // !wxUSE_UTF8_LOCALE_ONLY
 
@@ -409,16 +532,18 @@ template<>
 struct wxArgNormalizerUtf8<const std::string&>
     : public wxArgNormalizerUtf8<const char*>
 {
 struct wxArgNormalizerUtf8<const std::string&>
     : public wxArgNormalizerUtf8<const char*>
 {
-    wxArgNormalizerUtf8(const std::string& s)
-        : wxArgNormalizerUtf8<const char*>(s.c_str()) {}
+    wxArgNormalizerUtf8(const std::string& s,
+                        const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerUtf8<const char*>(s.c_str(), fmt, index) {}
 };
 
 template<>
 struct wxArgNormalizerUtf8<const wxStdWideString&>
     : public wxArgNormalizerUtf8<const wchar_t*>
 {
 };
 
 template<>
 struct wxArgNormalizerUtf8<const wxStdWideString&>
     : public wxArgNormalizerUtf8<const wchar_t*>
 {
-    wxArgNormalizerUtf8(const wxStdWideString& s)
-        : wxArgNormalizerUtf8<const wchar_t*>(s.c_str()) {}
+    wxArgNormalizerUtf8(const wxStdWideString& s,
+                        const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerUtf8<const wchar_t*>(s.c_str(), fmt, index) {}
 };
 #endif // wxUSE_UNICODE_UTF8
 
 };
 #endif // wxUSE_UNICODE_UTF8
 
@@ -429,32 +554,69 @@ WX_ARG_NORMALIZER_FORWARD(wxStdWideString, const wxStdWideString&);
 
 
 // versions for wxUniChar, wxUniCharRef:
 
 
 // versions for wxUniChar, wxUniCharRef:
+// (this is same for UTF-8 and Wchar builds, we just convert to wchar_t)
+template<>
+struct wxArgNormalizer<const wxUniChar&> : public wxArgNormalizer<wchar_t>
+{
+    wxArgNormalizer(const wxUniChar& s,
+                    const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizer<wchar_t>(s.GetValue(), fmt, index) {}
+};
+
+// for wchar_t, default handler does the right thing
+
+// char has to be treated differently in Unicode builds: a char argument may
+// be used either for a character value (which should be converted into
+// wxUniChar) or as an integer value (which should be left as-is). We take
+// advantage of the fact that both char and wchar_t are converted into int
+// in variadic arguments here.
+#if wxUSE_UNICODE
+template<typename T>
+struct wxArgNormalizerNarrowChar
+{
+    wxArgNormalizerNarrowChar(T value,
+                              const wxFormatString *fmt, unsigned index)
+    {
+        // FIXME-UTF8: which one is better default in absence of fmt string
+        //             (i.e. when used like e.g. Foo("foo", "bar", 'c', NULL)?
+        if ( !fmt || fmt->GetArgumentType(index) == wxFormatString::Arg_Char )
+            m_value = wx_truncate_cast(T, wxUniChar(value).GetValue());
+        else
+            m_value = value;
+    }
+
+    int get() const { return m_value; }
+
+    T m_value;
+};
 
 
-#if !wxUSE_UTF8_LOCALE_ONLY
 template<>
 template<>
-struct wxArgNormalizerWchar<const wxUniChar&>
-    : public wxArgNormalizerWchar<wxChar/*FIXME-UTF8: should be wchar_t after ANSI removal*/>
+struct wxArgNormalizer<char> : public wxArgNormalizerNarrowChar<char>
 {
 {
-    wxArgNormalizerWchar(const wxUniChar& s)
-        : wxArgNormalizerWchar<wxChar>((wxChar)s) {}
+    wxArgNormalizer(char value,
+                    const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerNarrowChar<char>(value, fmt, index) {}
 };
 };
-#endif // !wxUSE_UTF8_LOCALE_ONLY
 
 
-#if wxUSE_UNICODE_UTF8
 template<>
 template<>
-struct wxArgNormalizerUtf8<const wxUniChar&>
-    : public wxArgNormalizerUtf8<char>
+struct wxArgNormalizer<unsigned char>
+    : public wxArgNormalizerNarrowChar<unsigned char>
 {
 {
-    wxArgNormalizerUtf8(const wxUniChar& s)
-        // FIXME-UTF8: this is lossy, we need to convert to string, but that
-        // requires format string update
-        : wxArgNormalizerUtf8<char>((const char)s) {}
+    wxArgNormalizer(unsigned char value,
+                    const wxFormatString *fmt, unsigned index)
+        : wxArgNormalizerNarrowChar<unsigned char>(value, fmt, index) {}
 };
 };
-#endif // wxUSE_UNICODE_UTF8
 
 
+#endif // wxUSE_UNICODE
+
+// convert references:
 WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&);
 WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&);
 WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&);
 WX_ARG_NORMALIZER_FORWARD(wxUniChar, const wxUniChar&);
 WX_ARG_NORMALIZER_FORWARD(const wxUniCharRef&, const wxUniChar&);
 WX_ARG_NORMALIZER_FORWARD(wxUniCharRef, const wxUniChar&);
+WX_ARG_NORMALIZER_FORWARD(const wchar_t&, wchar_t);
+
+WX_ARG_NORMALIZER_FORWARD(const char&, char);
+WX_ARG_NORMALIZER_FORWARD(const unsigned char&, unsigned char);
 
 
 #undef WX_ARG_NORMALIZER_FORWARD
 
 
 #undef WX_ARG_NORMALIZER_FORWARD
@@ -583,6 +745,14 @@ private:
 #define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \
          t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4)
 
 #define _WX_VARARG_FIXED_UNUSED_EXPAND_4(t1,t2,t3,t4) \
          t1 WXUNUSED(f1), t2 WXUNUSED(f2), t3 WXUNUSED(f3), t4 WXUNUSED(f4)
 
+#define _WX_VARARG_FIXED_TYPEDEFS_1(t1) \
+             typedef t1 TF1
+#define _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2) \
+             _WX_VARARG_FIXED_TYPEDEFS_1(t1); typedef t2 TF2
+#define _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3) \
+             _WX_VARARG_FIXED_TYPEDEFS_2(t1,t2); typedef t3 TF3
+#define _WX_VARARG_FIXED_TYPEDEFS_4(t1,t2,t3,t4) \
+             _WX_VARARG_FIXED_TYPEDEFS_3(t1,t2,t3); typedef t4 TF4
 
 // This macro expands N-items tuple of fixed arguments types into part of
 // function's declaration. For example,
 
 // This macro expands N-items tuple of fixed arguments types into part of
 // function's declaration. For example,
@@ -599,6 +769,13 @@ private:
 #define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \
                 _WX_VARARG_FIXED_UNUSED_EXPAND_##N args
 
 #define _WX_VARARG_FIXED_UNUSED_EXPAND_IMPL(N, args) \
                 _WX_VARARG_FIXED_UNUSED_EXPAND_##N args
 
+// Declarates typedefs for fixed arguments types; i-th fixed argument types
+// will have TFi typedef.
+#define _WX_VARARG_FIXED_TYPEDEFS(N, args) \
+                _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args)
+#define _WX_VARARG_FIXED_TYPEDEFS_IMPL(N, args) \
+                _WX_VARARG_FIXED_TYPEDEFS_##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
 
 // 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
@@ -645,20 +822,23 @@ private:
 
 // Generates code snippet for passing i-th argument of vararg function
 // wrapper to its implementation, normalizing it in the process:
 
 // Generates code snippet for passing i-th argument of vararg function
 // wrapper to its implementation, normalizing it in the process:
-#define _WX_VARARG_PASS_WCHAR(i)        wxArgNormalizerWchar<T##i>(a##i).get()
-#define _WX_VARARG_PASS_UTF8(i)         wxArgNormalizerUtf8<T##i>(a##i).get()
+#define _WX_VARARG_PASS_WCHAR(i) \
+    wxArgNormalizerWchar<T##i>(a##i, fmt, i).get()
+#define _WX_VARARG_PASS_UTF8(i) \
+    wxArgNormalizerUtf8<T##i>(a##i, fmt, i).get()
 
 
 // And the same for fixed arguments, _not_ normalizing it:
 
 
 // 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<T> 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
 
 #define _WX_VARARG_PASS_FIXED(i)        f##i
 
+#define _WX_VARARG_FIND_FMT(i) \
+            (wxFormatStringArgumentFinder<TF##i>::find(f##i))
+
+#define _WX_VARARG_FORMAT_STRING(numfixed, fixed)                             \
+    _WX_VARARG_FIXED_TYPEDEFS(numfixed, fixed);                               \
+    const wxFormatString *fmt =                                               \
+            (_WX_VARARG_JOIN(numfixed, _WX_VARARG_FIND_FMT))
+
 #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),  \
 #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),  \
@@ -704,6 +884,7 @@ private:
     rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                    \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
     rettype name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                    \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
+        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
         _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed);              \
     }
 
         _WX_VARARG_DO_CALL(return, impl, implUtf8, N, numfixed);              \
     }
 
@@ -724,6 +905,7 @@ private:
     void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                       \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
     void name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                       \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
+        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
         _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
                            impl, implUtf8, N, numfixed);                      \
     }
         _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
                            impl, implUtf8, N, numfixed);                      \
     }
@@ -745,6 +927,7 @@ private:
     name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                            \
                 _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                           \
     {                                                                         \
     name(_WX_VARARG_FIXED_EXPAND(numfixed, fixed),                            \
                 _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                           \
     {                                                                         \
+        _WX_VARARG_FORMAT_STRING(numfixed, fixed);                            \
         _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
                            impl, implUtf8, N, numfixed);                      \
     }
         _WX_VARARG_DO_CALL(wxEMPTY_PARAMETER_VALUE,                           \
                            impl, implUtf8, N, numfixed);                      \
     }
@@ -809,6 +992,8 @@ private:
 #define _WX_VARARG_WATCOM_UNPACK(N, convfixed) \
         _WX_VARARG_WATCOM_UNPACK_##N convfixed
 
 #define _WX_VARARG_WATCOM_UNPACK(N, convfixed) \
         _WX_VARARG_WATCOM_UNPACK_##N convfixed
 
+#define _WX_VARARG_PASS_WATCOM(i) a##i
+
 #define _WX_VARARG_WATCOM_WORKAROUND(N, rettype, name,                        \
                                      convfixed, dummy, numfixed, fixed)       \
     template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
 #define _WX_VARARG_WATCOM_WORKAROUND(N, rettype, name,                        \
                                      convfixed, dummy, numfixed, fixed)       \
     template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
@@ -816,7 +1001,7 @@ private:
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
          return name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed),           \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
          return name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed),           \
-                     _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR));              \
+                     _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WATCOM));             \
     }
 
 #define _WX_VARARG_WATCOM_WORKAROUND_CTOR(N, dummy1, name,                    \
     }
 
 #define _WX_VARARG_WATCOM_WORKAROUND_CTOR(N, dummy1, name,                    \
@@ -826,7 +1011,7 @@ private:
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
          name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed),                  \
                  _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                          \
     {                                                                         \
          name(_WX_VARARG_WATCOM_UNPACK(numfixed, convfixed),                  \
-                     _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WCHAR));              \
+                     _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WATCOM));             \
     }
 
 #endif // __WATCOMC__
     }
 
 #endif // __WATCOMC__