DoPsPrintfFormatWchar, DoPsPrintfFormatUtf8)
 #ifdef __WATCOMC__
     // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-    WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, 1, (const char*),
-                               DoPsPrintfFormatWchar, DoPsPrintfFormatUtf8)
-    WX_DEFINE_VARARG_FUNC_VOID(PsPrintf, 1, (const wchar_t*),
-                               DoPsPrintfFormatWchar, DoPsPrintfFormatUtf8)
+    WX_VARARG_WATCOM_WORKAROUND(void, PsPrintf, 1, (const wxString&),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, PsPrintf, 1, (const wxCStrData&),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, PsPrintf, 1, (const char*),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, PsPrintf, 1, (const wchar_t*),
+                                (wxFormatString(f1)));
 #endif
 
     void PsPrint( const wxString& psdata );
 
     // 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,                            \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
+                                   1, (const wxString&),                    \
+                                   (wxFormatString(f1)))                    \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
+                                   1, (const wxCStrData&),                  \
+                                   (wxFormatString(f1)))                    \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
                                    1, (const char*),                        \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)                    \
-        WX_DEFINE_VARARG_FUNC_VOID(wxLog##level,                            \
+                                   (wxFormatString(f1)))                    \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
                                    1, (const wchar_t*),                     \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)                    \
-        WX_DEFINE_VARARG_FUNC_VOID(wxLog##level,                            \
-                                   1, (const wxCStrData&),                  \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)
+                                   (wxFormatString(f1)))
 #else
     #define DECLARE_LOG_FUNCTION_WATCOM(level)
 #endif
     // 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,                            \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
+                                   2, (argclass, const wxString&),          \
+                                   (f1, wxFormatString(f2)))                \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
+                                   2, (argclass, const wxCStrData&),        \
+                                   (f1, wxFormatString(f2)))                \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
                                    2, (argclass, const char*),              \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)                    \
-        WX_DEFINE_VARARG_FUNC_VOID(wxLog##level,                            \
+                                   (f1, wxFormatString(f2)))                \
+        WX_VARARG_WATCOM_WORKAROUND(void, wxLog##level,                     \
                                    2, (argclass, const wchar_t*),           \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)                    \
-        WX_DEFINE_VARARG_FUNC_VOID(wxLog##level,                            \
-                                   2, (argclass, const wxCStrData&),        \
-                                   wxDoLog##level##Wchar,                   \
-                                   wxDoLog##level##Utf8)
+                                   (f1, wxFormatString(f2)))
 #else
     #define DECLARE_LOG_FUNCTION2_EXP_WATCOM(level, argclass, arg, expdecl)
 #endif
         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(level, argclass, arg, expdecl)            \
     WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxString&)) \
         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)) {}
 
 // Empty Class to fake wxLogNull
 class WXDLLIMPEXP_BASE wxLogNull
 
     //               // extensions
     //               ...);
     WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo,
-                               4, (const wxString&, const wxString&,
-                                   const wxString&, const wxString&),
+                               // NB: these are not format strings, using
+                               //     wxFormatString here is a hack to get
+                               //     implicit conversion to wchar_t*/char*
+                               4, (const wxFormatString&,
+                                   const wxFormatString&,
+                                   const wxFormatString&,
+                                   const wxFormatString&),
                                VarArgInitWchar, VarArgInitUtf8)
 #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*),
-                               VarArgInitWchar, VarArgInitUtf8)
-    WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo,
-                               4, (const wchar_t*, const wchar_t*,
-                                   const wchar_t*, const wchar_t*),
-                               VarArgInitWchar, VarArgInitUtf8)
-    WX_DEFINE_VARARG_FUNC_CTOR(wxFileTypeInfo,
-                               4, (const wxCStrData&, const wxCStrData&,
-                                   const wxCStrData&, const wxCStrData&),
-                               VarArgInitWchar, VarArgInitUtf8)
+    WX_VARARG_WATCOM_WORKAROUND_CTOR(
+                                wxFileTypeInfo,
+                                4, (const wxString&,
+                                    const wxString&,
+                                    const wxString&,
+                                    const wxString&),
+                                (wxFormatString(f1),
+                                 wxFormatString(f2),
+                                 wxFormatString(f3),
+                                 wxFormatString(f4)));
+    WX_VARARG_WATCOM_WORKAROUND_CTOR(
+                                wxFileTypeInfo,
+                                4, (const wxCStrData&,
+                                    const wxCStrData&,
+                                    const wxCStrData&,
+                                    const wxCStrData&),
+                                (wxFormatString(f1),
+                                 wxFormatString(f2),
+                                 wxFormatString(f3),
+                                 wxFormatString(f4)));
+    WX_VARARG_WATCOM_WORKAROUND_CTOR(
+                                wxFileTypeInfo,
+                                4, (const char*,
+                                    const char*,
+                                    const char*,
+                                    const char*),
+                                (wxFormatString(f1),
+                                 wxFormatString(f2),
+                                 wxFormatString(f3),
+                                 wxFormatString(f4)));
+    WX_VARARG_WATCOM_WORKAROUND_CTOR(
+                                wxFileTypeInfo,
+                                4, (const wchar_t*,
+                                    const wchar_t*,
+                                    const wchar_t*,
+                                    const wchar_t*),
+                                (wxFormatString(f1),
+                                 wxFormatString(f2),
+                                 wxFormatString(f3),
+                                 wxFormatString(f4)));
 #endif
 
         // the array elements correspond to the parameters of the ctor above in
 
                                DoPrintfWchar, DoPrintfUtf8)
 #ifdef __WATCOMC__
     // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-    WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const char*),
-                               DoPrintfWchar, DoPrintfUtf8)
-    WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wchar_t*),
-                               DoPrintfWchar, DoPrintfUtf8)
-    WX_DEFINE_VARARG_FUNC_VOID(Printf, 1, (const wxCStrData&),
-                               DoPrintfWchar, DoPrintfUtf8)
+    WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const wxString&),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const wxCStrData&),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const char*),
+                                (wxFormatString(f1)));
+    WX_VARARG_WATCOM_WORKAROUND(void, Printf, 1, (const wchar_t*),
+                                (wxFormatString(f1)));
 #endif
 
 protected:
 
   WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxFormatString&),
                         DoPrintfWchar, DoPrintfUtf8)
 #ifdef __WATCOMC__
-  WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const char*),
-                        DoPrintfWchar, DoPrintfUtf8)
-  WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wchar_t*),
-                        DoPrintfWchar, DoPrintfUtf8)
-  WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxCStrData&),
-                        DoPrintfWchar, DoPrintfUtf8)
+  // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+  WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxString&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxCStrData&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const char*),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wchar_t*),
+                              (wxFormatString(f1)));
 #endif
 #endif // !wxNEEDS_WXSTRING_PRINTF_MIXIN
     // as vprintf(), returns the number of characters written or < 0 on error
                         DoFormatWchar, DoFormatUtf8)
 #ifdef __WATCOMC__
   // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-  WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const char*),
-                        DoFormatWchar, DoFormatUtf8)
-  WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wchar_t*),
-                        DoFormatWchar, DoFormatUtf8)
-  WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxCStrData&),
-                        DoFormatWchar, DoFormatUtf8)
+  WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxString&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxCStrData&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const char*),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wchar_t*),
+                              (wxFormatString(f1)));
 #endif
 #endif
     // the same as above, but takes a va_list
                         DoPrintfWchar, DoPrintfUtf8)
 #ifdef __WATCOMC__
   // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-  WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const char*),
-                        DoPrintfWchar, DoPrintfUtf8)
-  WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wchar_t*),
-                        DoPrintfWchar, DoPrintfUtf8)
-  WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxCStrData&),
-                        DoPrintfWchar, DoPrintfUtf8)
+  WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxString&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxCStrData&),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const char*),
+                              (wxFormatString(f1)));
+  WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wchar_t*),
+                              (wxFormatString(f1)));
 #endif
 #endif // wxNEEDS_WXSTRING_PRINTF_MIXIN
 
 
     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_
 
     #undef wxSnprintf
 
     #define wxPrintf(fmt, ...) \
-            wxPrintf_Impl(wxString(fmt), __VA_ARGS__)
+            wxPrintf_Impl(wxFormatString(fmt), __VA_ARGS__)
     #define wxFprintf(f, fmt, ...) \
-            wxFprintf_Impl(f, wxString(fmt), __VA_ARGS__)
+            wxFprintf_Impl(f, wxFormatString(fmt), __VA_ARGS__)
     #define wxSprintf(s, fmt, ...) \
-            wxSprintf_Impl(s, wxString(fmt), __VA_ARGS__)
+            wxSprintf_Impl(s, wxFormatString(fmt), __VA_ARGS__)
     #define wxSnprintf(s, n, fmt, ...) \
-            wxSnprintf_Impl(s, n, wxString(fmt), __VA_ARGS__)
+            wxSnprintf_Impl(s, n, wxFormatString(fmt), __VA_ARGS__)
 #endif // __WATCOMC__
 
 
 
 
 #ifdef __WATCOMC__
   // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-  void wxDoLogTrace(int mask, const wxChar *format, ...)
+  void wxDoLogTraceWchar(int mask, const wxChar *format, ...)
   {
     va_list argptr;
     va_start(argptr, format);
     va_end(argptr);
   }
 
-  void wxDoLogTrace(const char *mask, const wxChar *format, ...)
+  void wxDoLogTraceWchar(const char *mask, const wxChar *format, ...)
   {
     va_list argptr;
     va_start(argptr, format);
     va_end(argptr);
   }
 
-  void wxDoLogTrace(const wchar_t *mask, const wxChar *format, ...)
+  void wxDoLogTraceWchar(const wchar_t *mask, const wxChar *format, ...)
   {
     va_list argptr;
     va_start(argptr, format);
 
 #ifdef __WATCOMC__
 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
-void WXDLLEXPORT wxDoLogSysError(unsigned long lErrCode, const wxChar *format, ...)
+void WXDLLEXPORT wxDoLogSysErrorWchar(unsigned long lErrCode, const wxChar *format, ...)
 {
     va_list argptr;
     va_start(argptr, format);
     va_end(argptr);
 }
 
-void WXDLLEXPORT wxVLogSysError(unsigned long err, const wxChar *format, va_list argptr)
+void WXDLLEXPORT wxVLogSysError(unsigned long err, const wxString& format, va_list argptr)
     { wxVLogSysError((long)err, format, argptr); }
 #endif // __WATCOMC__