]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/wxcrtvararg.h
support SDK < 10.6, fixes #14902
[wxWidgets.git] / include / wx / wxcrtvararg.h
index c8747eba140888e5f65c6d398c56df6637c8d23f..959f88fcc1e58cb1364905a50d38b0b34f1a955d 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        wx/wxcrtvararg.h
 // Purpose:     Type-safe ANSI and Unicode builds compatible wrappers for
 //              printf(), scanf() and related CRT functions
 // Name:        wx/wxcrtvararg.h
 // Purpose:     Type-safe ANSI and Unicode builds compatible wrappers for
 //              printf(), scanf() and related CRT functions
-// Author:      Joel Farley, Ove Kåven
+// Author:      Joel Farley, Ove Kåven
 // Modified by: Vadim Zeitlin, Robert Roebling, Ron Lee
 // Created:     2007-02-19
 // RCS-ID:      $Id$
 // Modified by: Vadim Zeitlin, Robert Roebling, Ron Lee
 // Created:     2007-02-19
 // RCS-ID:      $Id$
@@ -13,6 +13,9 @@
 #ifndef _WX_WXCRTVARARG_H_
 #define _WX_WXCRTVARARG_H_
 
 #ifndef _WX_WXCRTVARARG_H_
 #define _WX_WXCRTVARARG_H_
 
+// NB: User code should include wx/crt.h instead of including this
+//     header directly.
+
 #include "wx/wxcrt.h"
 #include "wx/strvararg.h"
 
 #include "wx/wxcrt.h"
 #include "wx/strvararg.h"
 
 /* Required for wxPrintf() etc */
 #include <stdarg.h>
 
 /* Required for wxPrintf() etc */
 #include <stdarg.h>
 
-#ifdef wxHAVE_TCHAR_SUPPORT
-    #define  wxCRT_Fprintf   _ftprintf
-    #define  wxCRT_Printf    _tprintf
-    #define  wxCRT_Scanf     _tscanf
-
-    #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 */
-        #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 */
-
 /* printf() family saga */
 
 /*
 /* printf() family saga */
 
 /*
-   For some systems [v]snprintf() exists in the system libraries but not in the
-   headers, so we need to declare it ourselves to be able to use it.
+   For many old Unix systems [v]snprintf()/vsscanf() exists in the system
+   libraries but not in the headers, so we need to declare it ourselves to be
+   able to use it.
  */
  */
+#ifdef __UNIX__
+
 #if defined(HAVE_VSNPRINTF) && !defined(HAVE_VSNPRINTF_DECL)
 #ifdef __cplusplus
     extern "C"
 #if defined(HAVE_VSNPRINTF) && !defined(HAVE_VSNPRINTF_DECL)
 #ifdef __cplusplus
     extern "C"
 #else
     extern
 #endif
 #else
     extern
 #endif
-    WXDLLIMPEXP_BASE int snprintf(char *str, size_t size, const char *format, ...);
+    int snprintf(char *str, size_t size, const char *format, ...);
 #endif /* !HAVE_SNPRINTF_DECL */
 
 #endif /* !HAVE_SNPRINTF_DECL */
 
+#if defined(HAVE_VSSCANF) && !defined(HAVE_VSSCANF_DECL)
+#ifdef __cplusplus
+    extern "C"
+#else
+    extern
+#endif
+    int vsscanf(const char *str, const char *format, va_list ap);
+#endif /* !HAVE_VSSCANF_DECL */
+
 /* Wrapper for vsnprintf if it's 3rd parameter is non-const. Note: the
  * same isn't done for snprintf below, the builtin wxSnprintf_ is used
  * instead since it's already a simple wrapper */
 /* Wrapper for vsnprintf if it's 3rd parameter is non-const. Note: the
  * same isn't done for snprintf below, the builtin wxSnprintf_ is used
  * instead since it's already a simple wrapper */
     }
 #endif
 
     }
 #endif
 
+#endif /* __UNIX__ */
+
 /*
 /*
-   MinGW MSVCRT has non-standard vswprintf() (for MSVC compatibility
-   presumably) and normally _vsnwprintf() is used instead
+   mingw32 normally uses MSVCRT which has non-standard vswprintf() and so
+   normally _vsnwprintf() is used instead, the only exception is when mingw32
+   is used with STLPort which does have a standard vswprintf() starting from
+   version 5.1 which we can use.
  */
  */
-#if defined(HAVE_VSWPRINTF) && defined(__MINGW32__)
-    #undef HAVE_VSWPRINTF
+#ifdef __MINGW32__
+    #if defined(_STLPORT_VERSION) && _STLPORT_VERSION >= 0x510
+        #ifndef HAVE_VSWPRINTF
+            #define HAVE_VSWPRINTF
+        #endif
+    #elif defined(HAVE_VSWPRINTF)
+        /* can't use non-standard vswprintf() */
+        #undef HAVE_VSWPRINTF
+    #endif
+#endif /* __MINGW32__ */
+
+#if defined(__WATCOMC__)
+    #define HAVE_VSWPRINTF 1
 #endif
 
 #if wxUSE_PRINTF_POS_PARAMS
 #endif
 
 #if wxUSE_PRINTF_POS_PARAMS
         our wxVsnprintf() implementation.
     */
     #if defined(HAVE_UNIX98_PRINTF)
         our wxVsnprintf() implementation.
     */
     #if defined(HAVE_UNIX98_PRINTF)
-        #if wxUSE_UNICODE
-            #ifdef HAVE_VSWPRINTF
-                #define wxVsnprintf_        vswprintf
-            #endif
-        #else /* ASCII */
-            #ifdef HAVE_BROKEN_VSNPRINTF_DECL
-                #define wxVsnprintf_    wx_fixed_vsnprintf
-            #else
-                #define wxVsnprintf_    vsnprintf
-            #endif
+        #ifdef HAVE_VSWPRINTF
+            #define wxCRT_VsnprintfW   vswprintf
+        #endif
+        #ifdef HAVE_BROKEN_VSNPRINTF_DECL
+            #define wxCRT_VsnprintfA    wx_fixed_vsnprintf
+        #else
+            #define wxCRT_VsnprintfA    vsnprintf
         #endif
     #else /* !HAVE_UNIX98_PRINTF */
         /*
         #endif
     #else /* !HAVE_UNIX98_PRINTF */
         /*
             main release and does not have the printf_p functions.
          */
         #if defined _MSC_FULL_VER && _MSC_FULL_VER >= 140050727 && !defined __WXWINCE__
             main release and does not have the printf_p functions.
          */
         #if defined _MSC_FULL_VER && _MSC_FULL_VER >= 140050727 && !defined __WXWINCE__
-            #if wxUSE_UNICODE
-                #define wxVsnprintf_    _vswprintf_p
-            #else
-                #define wxVsnprintf_    _vsprintf_p
-            #endif
+            #define wxCRT_VsnprintfA    _vsprintf_p
+            #define wxCRT_VsnprintfW    _vswprintf_p
         #endif
     #endif /* HAVE_UNIX98_PRINTF/!HAVE_UNIX98_PRINTF */
 #else /* !wxUSE_PRINTF_POS_PARAMS */
         #endif
     #endif /* HAVE_UNIX98_PRINTF/!HAVE_UNIX98_PRINTF */
 #else /* !wxUSE_PRINTF_POS_PARAMS */
        is a wrapper around it as explained below
      */
 
        is a wrapper around it as explained below
      */
 
-    /* first deal with TCHAR-aware compilers which have _vsntprintf */
-    #ifndef wxVsnprintf_
-        #if defined(__VISUALC__) || \
-                (defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
-            #define wxVsnprintf_    _vsntprintf
+    #if defined(__VISUALC__) || \
+            (defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
+        #define wxCRT_VsnprintfA    _vsnprintf
+        #define wxCRT_VsnprintfW    _vsnwprintf
+    #else
+        #if defined(HAVE__VSNWPRINTF)
+            #define wxCRT_VsnprintfW    _vsnwprintf
+        #elif defined(HAVE_VSWPRINTF)
+            #define wxCRT_VsnprintfW     vswprintf
+        #elif defined(__WATCOMC__)
+            #define wxCRT_VsnprintfW    _vsnwprintf
         #endif
         #endif
-    #endif
 
 
-    /* if this didn't work, define it separately for Unicode and ANSI builds */
-    #ifndef wxVsnprintf_
-        #if wxUSE_UNICODE
-            #if defined(HAVE__VSNWPRINTF)
-                #define wxVsnprintf_    _vsnwprintf
-            #elif defined(HAVE_VSWPRINTF)
-                #define wxVsnprintf_     vswprintf
-            #elif defined(__WATCOMC__)
-                #define wxVsnprintf_    _vsnwprintf
-            #endif
-        #else /* ASCII */
-            /*
-               All versions of CodeWarrior supported by wxWidgets apparently
-               have both snprintf() and vsnprintf()
-             */
-            #if defined(HAVE_VSNPRINTF) \
-                || defined(__MWERKS__) || defined(__WATCOMC__)
-                #ifdef HAVE_BROKEN_VSNPRINTF_DECL
-                    #define wxVsnprintf_    wx_fixed_vsnprintf
-                #else
-                    #define wxVsnprintf_    vsnprintf
-                #endif
+        #if defined(HAVE_VSNPRINTF) \
+            || defined(__WATCOMC__)
+            #ifdef HAVE_BROKEN_VSNPRINTF_DECL
+                #define wxCRT_VsnprintfA    wx_fixed_vsnprintf
+            #else
+                #define wxCRT_VsnprintfA    vsnprintf
             #endif
             #endif
-        #endif /* Unicode/ASCII */
-    #endif /* wxVsnprintf_ */
+        #endif
+    #endif
 #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
 
 #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
 
-#ifndef wxVsnprintf_
+#ifndef wxCRT_VsnprintfW
     /* no (suitable) vsnprintf(), cook our own */
     WXDLLIMPEXP_BASE int
     /* no (suitable) vsnprintf(), cook our own */
     WXDLLIMPEXP_BASE int
-    wxVsnprintf_(wxChar *buf, size_t len, const wxChar *format, va_list argptr);
+    wxCRT_VsnprintfW(wchar_t *buf, size_t len, const wchar_t *format, va_list argptr);
+    #define wxUSE_WXVSNPRINTFW 1
+#else
+    #define wxUSE_WXVSNPRINTFW 0
+#endif
 
 
-    #define wxUSE_WXVSNPRINTF 1
+#ifndef wxCRT_VsnprintfA
+        /* no (suitable) vsnprintf(), cook our own */
+        WXDLLIMPEXP_BASE int
+        wxCRT_VsnprintfA(char *buf, size_t len, const char *format, va_list argptr);
+        #define wxUSE_WXVSNPRINTFA 1
 #else
 #else
-    #define wxUSE_WXVSNPRINTF 0
+        #define wxUSE_WXVSNPRINTFA 0
 #endif
 
 #endif
 
+// for wxString code, define wxUSE_WXVSNPRINTF to indicate that wx
+// implementation is used no matter what (in UTF-8 build, either *A or *W
+// version may be called):
+#if !wxUSE_UNICODE
+    #define wxUSE_WXVSNPRINTF wxUSE_WXVSNPRINTFA
+#elif wxUSE_UNICODE_WCHAR
+    #define wxUSE_WXVSNPRINTF wxUSE_WXVSNPRINTFW
+#elif wxUSE_UTF8_LOCALE_ONLY
+    #define wxUSE_WXVSNPRINTF wxUSE_WXVSNPRINTFA
+#else // UTF-8 under any locale
+    #define wxUSE_WXVSNPRINTF (wxUSE_WXVSNPRINTFA && wxUSE_WXVSNPRINTFW)
+#endif
+
+#define wxCRT_FprintfA       fprintf
+#define wxCRT_PrintfA        printf
+#define wxCRT_VfprintfA      vfprintf
+#define wxCRT_VprintfA       vprintf
+#define wxCRT_VsprintfA      vsprintf
+
 /*
    In Unicode mode we need to have all standard functions such as wprintf() and
    so on but not all systems have them so use our own implementations in this
 /*
    In Unicode mode we need to have all standard functions such as wprintf() and
    so on but not all systems have them so use our own implementations in this
 #if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
     #define wxNEED_WPRINTF
 #endif
 #if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
     #define wxNEED_WPRINTF
 #endif
+#if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_VSWSCANF)
+    #define wxNEED_VSWSCANF
+#endif
 
 
-/*
-   More Unicode complications: although both ANSI C and C++ define a number of
-   wide character functions such as wprintf(), not all environments have them.
-   Worse, those which do have different behaviours: under Windows, %s format
-   specifier changes its meaning in Unicode build and expects a Unicode string
-   while under Unix/POSIX it still means an ASCII string even for wprintf() and
-   %ls has to be used for wide strings.
-
-   We choose to always emulate Windows behaviour as more useful for us so even
-   if we have wprintf() we still must wrap it in a non trivial wxPrintf().
-
-*/
 
 
-#if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
+#if defined(wxNEED_WPRINTF)
     /*
     /*
-        we need to implement all wide character printf and scanf functions
-        either because we don't have them at all or because they don't have the
-        semantics we need
+        we need to implement all wide character printf functions either because
+        we don't have them at all or because they don't have the semantics we
+        need
      */
      */
-    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 */
-/* if we don't have to do the conversion */
-/*
-   However, if we don't have any vswprintf() at all we don't need to redefine
-   anything as our own wxVsnprintf_() already behaves as needed.
-*/
-#if defined(wxNEED_PRINTF_CONVERSION) && defined(wxVsnprintf_)
-    int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap );
+    int wxCRT_PrintfW( const wchar_t *format, ... );
+    int wxCRT_FprintfW( FILE *stream, const wchar_t *format, ... );
+    int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list ap );
+    int wxCRT_VprintfW( const wchar_t *format, va_list ap );
+    int wxCRT_VsprintfW( wchar_t *str, const wchar_t *format, va_list ap );
+#else /* !wxNEED_WPRINTF */
+    #define wxCRT_FprintfW      fwprintf
+    #define wxCRT_PrintfW       wprintf
+    #define wxCRT_VfprintfW     vfwprintf
+    #define wxCRT_VprintfW      vwprintf
+
+    #if defined(__WINDOWS__) && !defined(HAVE_VSWPRINTF)
+        // only non-standard vswprintf() without buffer size argument can be used here
+        #define  wxCRT_VsprintfW     vswprintf
+    #endif
+#endif /* wxNEED_WPRINTF */
+
+
+/* Required for wxScanf() etc. */
+#define wxCRT_ScanfA     scanf
+#define wxCRT_SscanfA    sscanf
+#define wxCRT_FscanfA    fscanf
+#define wxCRT_VsscanfA   vsscanf
+
+#if defined(wxNEED_WPRINTF)
+    int wxCRT_ScanfW(const wchar_t *format, ...);
+    int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...);
+    int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...);
 #else
 #else
-    #define wxCRT_Vsnprintf wxVsnprintf_
+    #define wxCRT_ScanfW     wxVMS_USE_STD wscanf
+    #define wxCRT_SscanfW    wxVMS_USE_STD swscanf
+    #define wxCRT_FscanfW    wxVMS_USE_STD fwscanf
+#endif
+#ifdef wxNEED_VSWSCANF
+    int wxCRT_VsscanfW(const wchar_t *str, const wchar_t *format, va_list ap);
+#else
+    #define wxCRT_VsscanfW   wxVMS_USE_STD vswscanf
 #endif
 #endif
-
 
 // ----------------------------------------------------------------------------
 // user-friendly wrappers to CRT functions
 
 // ----------------------------------------------------------------------------
 // user-friendly wrappers to CRT functions
     #define wxSnprintf  wxSnprintf_Impl
 #endif
 
     #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: remove this
+#if wxUSE_UNICODE
+    #define wxCRT_PrintfNative wxCRT_PrintfW
+    #define wxCRT_FprintfNative wxCRT_FprintfW
+#else
+    #define wxCRT_PrintfNative wxCRT_PrintfA
+    #define wxCRT_FprintfNative wxCRT_FprintfA
+#endif
 
 
-// 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<T> specializations for char,
-//             wchar_t, wxUniChar and wxUniCharRef to handle this correctly
 
 
-WX_DEFINE_VARARG_FUNC(int, wxPrintf, 1, (const wxString&),
-                      wxCRT_Printf, printf)
-WX_DEFINE_VARARG_FUNC(int, wxFprintf, 2, (FILE*, const wxString&),
-                      wxCRT_Fprintf, fprintf)
+WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxPrintf, 1, (const wxFormatString&),
+                              wxCRT_PrintfNative, wxCRT_PrintfA)
+inline int wxPrintf(const wxFormatString& s)
+{
+    return wxPrintf("%s", s.InputAsString());
+}
+
+WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxFprintf, 2, (FILE*, const wxFormatString&),
+                              wxCRT_FprintfNative, wxCRT_FprintfA)
+inline int wxFprintf(FILE *f, const wxFormatString& s)
+{
+    return wxFprintf(f, "%s", s.InputAsString());
+}
 
 // va_list versions of printf functions simply forward to the respective
 // CRT function; note that they assume that va_list was created using
 // wxArgNormalizer<T>!
 #if wxUSE_UNICODE_UTF8
     #if wxUSE_UTF8_LOCALE_ONLY
 
 // va_list versions of printf functions simply forward to the respective
 // CRT function; note that they assume that va_list was created using
 // wxArgNormalizer<T>!
 #if wxUSE_UNICODE_UTF8
     #if wxUSE_UTF8_LOCALE_ONLY
-        #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8)              \
-            return implUtf8 args
+        #define WX_VARARG_VFOO_IMPL(args, implW, implA)              \
+            return implA args
     #else
     #else
-        #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8)              \
-            if ( wxLocaleIsUtf8 ) return implUtf8 args;                     \
-            else return implWchar args
+        #define WX_VARARG_VFOO_IMPL(args, implW, implA)              \
+            if ( wxLocaleIsUtf8 ) return implA args;                 \
+            else return implW args
     #endif
     #endif
-#else // wxUSE_UNICODE_WCHAR / ANSI
-    #define WX_VARARG_VFOO_IMPL(args, implWchar, implUtf8)                  \
-        return implWchar args
+#elif wxUSE_UNICODE_WCHAR
+    #define WX_VARARG_VFOO_IMPL(args, implW, implA)                  \
+        return implW args
+#else // ANSI
+    #define WX_VARARG_VFOO_IMPL(args, implW, implA)                  \
+        return implA args
 #endif
 
 inline int
 wxVprintf(const wxString& format, va_list ap)
 {
 #endif
 
 inline int
 wxVprintf(const wxString& format, va_list ap)
 {
-    WX_VARARG_VFOO_IMPL((format, ap), wxCRT_Vprintf, vprintf);
+    WX_VARARG_VFOO_IMPL((wxFormatString(format), ap),
+                        wxCRT_VprintfW, wxCRT_VprintfA);
 }
 
 inline int
 wxVfprintf(FILE *f, const wxString& format, va_list ap)
 {
 }
 
 inline int
 wxVfprintf(FILE *f, const wxString& format, va_list ap)
 {
-    WX_VARARG_VFOO_IMPL((f, format, ap), wxCRT_Vfprintf, vfprintf);
+    WX_VARARG_VFOO_IMPL((f, wxFormatString(format), ap),
+                        wxCRT_VfprintfW, wxCRT_VfprintfA);
 }
 
 #undef WX_VARARG_VFOO_IMPL
 }
 
 #undef WX_VARARG_VFOO_IMPL
@@ -305,7 +338,7 @@ int WXDLLIMPEXP_BASE wxDoSprintfWchar(char *str, const wxChar *format, ...);
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(char *str, const char *format, ...);
 #endif
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(char *str, const char *format, ...);
 #endif
-WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (char*, const wxString&),
+WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (char*, const wxFormatString&),
                       wxDoSprintfWchar, wxDoSprintfUtf8)
 
 int WXDLLIMPEXP_BASE
                       wxDoSprintfWchar, wxDoSprintfUtf8)
 
 int WXDLLIMPEXP_BASE
@@ -317,7 +350,7 @@ int WXDLLIMPEXP_BASE wxDoSnprintfWchar(char *str, size_t size, const wxChar *for
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...);
 #endif
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...);
 #endif
-WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (char*, size_t, const wxString&),
+WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (char*, size_t, const wxFormatString&),
                       wxDoSnprintfWchar, wxDoSnprintfUtf8)
 
 int WXDLLIMPEXP_BASE
                       wxDoSnprintfWchar, wxDoSnprintfUtf8)
 
 int WXDLLIMPEXP_BASE
@@ -331,7 +364,7 @@ int WXDLLIMPEXP_BASE wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...);
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(wchar_t *str, const char *format, ...);
 #endif
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSprintfUtf8(wchar_t *str, const char *format, ...);
 #endif
-WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (wchar_t*, const wxString&),
+WX_DEFINE_VARARG_FUNC(int, wxSprintf, 2, (wchar_t*, const wxFormatString&),
                       wxDoSprintfWchar, wxDoSprintfUtf8)
 
 int WXDLLIMPEXP_BASE
                       wxDoSprintfWchar, wxDoSprintfUtf8)
 
 int WXDLLIMPEXP_BASE
@@ -343,7 +376,7 @@ int WXDLLIMPEXP_BASE wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...);
 #endif
 #if wxUSE_UNICODE_UTF8
 int WXDLLIMPEXP_BASE wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...);
 #endif
-WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (wchar_t*, size_t, const wxString&),
+WX_DEFINE_VARARG_FUNC(int, wxSnprintf, 3, (wchar_t*, size_t, const wxFormatString&),
                       wxDoSnprintfWchar, wxDoSnprintfUtf8)
 
 int WXDLLIMPEXP_BASE
                       wxDoSnprintfWchar, wxDoSnprintfUtf8)
 
 int WXDLLIMPEXP_BASE
@@ -362,13 +395,13 @@ wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr);
     #undef wxSnprintf
 
     #define wxPrintf(fmt, ...) \
     #undef wxSnprintf
 
     #define wxPrintf(fmt, ...) \
-            wxPrintf_Impl(wxString(fmt), __VA_ARGS__)
+            wxPrintf_Impl(wxFormatString(fmt), __VA_ARGS__)
     #define wxFprintf(f, fmt, ...) \
     #define wxFprintf(f, fmt, ...) \
-            wxFprintf_Impl(f, wxString(fmt), __VA_ARGS__)
+            wxFprintf_Impl(f, wxFormatString(fmt), __VA_ARGS__)
     #define wxSprintf(s, fmt, ...) \
     #define wxSprintf(s, fmt, ...) \
-            wxSprintf_Impl(s, wxString(fmt), __VA_ARGS__)
+            wxSprintf_Impl(s, wxFormatString(fmt), __VA_ARGS__)
     #define wxSnprintf(s, n, fmt, ...) \
     #define wxSnprintf(s, n, fmt, ...) \
-            wxSnprintf_Impl(s, n, wxString(fmt), __VA_ARGS__)
+            wxSnprintf_Impl(s, n, wxFormatString(fmt), __VA_ARGS__)
 #endif // __WATCOMC__
 
 
 #endif // __WATCOMC__
 
 
@@ -377,11 +410,78 @@ wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr);
 // 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.
 // 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.
+//
+// For compatibility with earlier wx versions, we also provide wxSscanf()
+// version with the first argument (input string) wxString; for this version,
+// the type of output string values is determined by the type of format string
+// only.
+
+#define _WX_SCANFUNC_EXTRACT_ARGS_1(x)   x
+#define _WX_SCANFUNC_EXTRACT_ARGS_2(x,y) x, y
+#define _WX_SCANFUNC_EXTRACT_ARGS(N, args) _WX_SCANFUNC_EXTRACT_ARGS_##N args
+
+#define _WX_VARARG_PASS_WRITABLE(i) a##i
+
+#define _WX_DEFINE_SCANFUNC(N, dummy1, name, impl, passfixed, numfixed, fixed)\
+    template<_WX_VARARG_JOIN(N, _WX_VARARG_TEMPL)>                            \
+    int name(_WX_SCANFUNC_EXTRACT_ARGS(numfixed, fixed),                      \
+             _WX_VARARG_JOIN(N, _WX_VARARG_ARG))                              \
+    {                                                                         \
+        return  impl(_WX_SCANFUNC_EXTRACT_ARGS(numfixed, passfixed),          \
+                     _WX_VARARG_JOIN(N, _WX_VARARG_PASS_WRITABLE));           \
+    }
+
+#define WX_DEFINE_SCANFUNC(name, numfixed, fixed, impl, passfixed)            \
+    _WX_VARARG_ITER(_WX_VARARG_MAX_ARGS,                                      \
+                    _WX_DEFINE_SCANFUNC,                                      \
+                    dummy1, name, impl, passfixed, numfixed, fixed)
+
+// this is needed to normalize the format string, see src/common/strvararg.cpp
+// for more details
+#ifdef __WINDOWS__
+    #define wxScanfConvertFormatW(fmt) fmt
+#else
+    const wxScopedWCharBuffer
+    WXDLLIMPEXP_BASE wxScanfConvertFormatW(const wchar_t *format);
+#endif
 
 
-// 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
+WX_DEFINE_SCANFUNC(wxScanf, 1, (const char *format),
+                   wxCRT_ScanfA, (format))
+WX_DEFINE_SCANFUNC(wxScanf, 1, (const wchar_t *format),
+                   wxCRT_ScanfW, (wxScanfConvertFormatW(format)))
+
+WX_DEFINE_SCANFUNC(wxFscanf, 2, (FILE *stream, const char *format),
+                   wxCRT_FscanfA, (stream, format))
+WX_DEFINE_SCANFUNC(wxFscanf, 2, (FILE *stream, const wchar_t *format),
+                   wxCRT_FscanfW, (stream, wxScanfConvertFormatW(format)))
+
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const char *str, const char *format),
+                   wxCRT_SscanfA, (str, format))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wchar_t *str, const wchar_t *format),
+                   wxCRT_SscanfW, (str, wxScanfConvertFormatW(format)))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxScopedCharBuffer& str, const char *format),
+                   wxCRT_SscanfA, (str.data(), format))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxScopedWCharBuffer& str, const wchar_t *format),
+                   wxCRT_SscanfW, (str.data(), wxScanfConvertFormatW(format)))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxString& str, const char *format),
+                   wxCRT_SscanfA, (str.mb_str(), format))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxString& str, const wchar_t *format),
+                   wxCRT_SscanfW, (str.wc_str(), wxScanfConvertFormatW(format)))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxCStrData& str, const char *format),
+                   wxCRT_SscanfA, (str.AsCharBuf(), format))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxCStrData& str, const wchar_t *format),
+                   wxCRT_SscanfW, (str.AsWCharBuf(), wxScanfConvertFormatW(format)))
+
+// Visual C++ doesn't provide vsscanf()
+#ifndef __VISUALC___
+int WXDLLIMPEXP_BASE wxVsscanf(const char *str, const char *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxScopedCharBuffer& str, const char *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxScopedWCharBuffer& str, const wchar_t *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxString& str, const char *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxString& str, const wchar_t *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxCStrData& str, const char *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxCStrData& str, const wchar_t *format, va_list ap);
+#endif // !__VISUALC__
 
 #endif /* _WX_WXCRTVARARG_H_ */
 
 #endif /* _WX_WXCRTVARARG_H_ */