]> git.saurik.com Git - wxWidgets.git/commitdiff
reorganized, improved and hopefully simplified wxchar.h and printf() functions handli...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 25 Aug 2002 17:13:44 +0000 (17:13 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 25 Aug 2002 17:13:44 +0000 (17:13 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16767 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/wxchar.h
src/common/string.cpp
src/common/wxchar.cpp

index ee7f0b225fdecf705ce0546331eba0d8b599e873..89bf08deea1899690b9e7e19e707cb824b764517 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        wxchar.h
+// Name:        wx/wxchar.h
 // Purpose:     Declarations common to wx char/wchar_t usage (wide chars)
-// Author:      Joel Farley
-// Modified by:
+// Author:      Joel Farley, Ove Kåven
+// Modified by: Vadim Zeitlin, Robert Roebling
 // Created:     1998/06/12
 // RCS-ID:      $Id$
-// Copyright:   (c) wxWindows copyright
+// Copyright:   (c) 1998-2002 wxWindows dev team
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
     #pragma interface "wxchar.h"
 #endif
 
-// only do SBCS or _UNICODE
-#if defined (_MBCS )
-// It may be OK anyway.
-// #  error "MBCS is not supported by wxChar"
-#endif
-
 // ----------------------------------------------------------------------------
-// first deal with Unicode setting
+// first deal with Unicode setting: wxUSE_UNICODE should be defined as 0 or 1
+// and is used by wxWindows, _UNICODE and/or UNICODE may be defined or used by
+// the system headers so bring these settings in sync
 // ----------------------------------------------------------------------------
 
 // set wxUSE_UNICODE to 1 if UNICODE or _UNICODE is defined
 #if defined(_UNICODE) || defined(UNICODE)
-#  undef wxUSE_UNICODE
-#  define wxUSE_UNICODE 1
+    #undef wxUSE_UNICODE
+    #define wxUSE_UNICODE 1
 #else
-#  ifndef wxUSE_UNICODE
-#    define wxUSE_UNICODE 0
-#  endif
+    #ifndef wxUSE_UNICODE
+        #define wxUSE_UNICODE 0
+    #endif
 #endif // Unicode
 
 // and vice versa: define UNICODE and _UNICODE if wxUSE_UNICODE is 1...
 #if wxUSE_UNICODE
-#  ifndef _UNICODE
-#    define _UNICODE
-#  endif
-#  ifndef UNICODE
-#    define UNICODE
-#  endif
+    #ifndef _UNICODE
+        #define _UNICODE
+    #endif
+    #ifndef UNICODE
+        #define UNICODE
+    #endif
 #endif // Unicode
 
+// check whether we have wchar_t
+#if !defined(wxUSE_WCHAR_T)
+    #if defined(__WIN16__)
+        // no wchar_t under Win16 regadrless of compiler used
+        #define wxUSE_WCHAR_T 0
+    #elif defined(__UNIX__)
+        #if defined(HAVE_WCSTR_H) || defined(HAVE_WCHAR_H) || defined(__FreeBSD__) || defined(__DARWIN__)
+            #define wxUSE_WCHAR_T 1
+        #else
+            #define wxUSE_WCHAR_T 0
+        #endif
+    #elif defined(__GNUWIN32__) && !defined(__MINGW32__) // Cygwin (not Mingw32) doesn't have wcslen.h, needed in buffer.h
+        #define wxUSE_WCHAR_T 0
+    #elif defined(__WATCOMC__)
+        #define wxUSE_WCHAR_T 0
+    #elif defined(__VISAGECPP__) && (__IBMCPP__ < 400)
+        #define wxUSE_WCHAR_T 0
+    #else
+        // add additional compiler checks if this fails
+        #define wxUSE_WCHAR_T 1
+    #endif
+#endif // !defined(wxUSE_WCHAR_T)
+
 // Unicode support requires wchar_t
-#if wxUSE_UNICODE
-#   undef wxUSE_WCHAR_T
-#   define wxUSE_WCHAR_T 1
+#if wxUSE_UNICODE && !wxUSE_WCHAR_T
+    #error "wchar_t must be available in Unicode build"
 #endif // Unicode
 
+// ----------------------------------------------------------------------------
+// standard headers we need here
+//
+// NB: don't include any wxWindows headers here because almost of them include
+//     this one!
+// ----------------------------------------------------------------------------
+
 // Required for wxPrintf() etc
 #include <stdarg.h>
 
+#if defined(__CYGWIN__)
+    #ifndef HAVE_WCSLEN
+        #define HAVE_WCSLEN
+    #endif // !HAVE_WCSLEN
+    #include <stddef.h>
+#endif
+
+// non Unix compilers which do have wchar.h (but not tchar.h which is included
+// below and which includes wchar.h anyhow)
+#if defined(__MWERKS__) || defined(__VISAGECPP__)
+    #ifndef HAVE_WCHAR_H
+        #define HAVE_WCHAR_H
+    #endif
+#endif
+
+#if wxUSE_WCHAR_T
+    #ifdef HAVE_WCHAR_H
+        // include wchar.h to get wcslen() declaration used by wx/buffer.h
+        #include <wchar.h>
+    #elif defined(HAVE_WCSTR_H)
+        // old compilers have wcslen() here
+        #include <wcstr.h>
+    #elif defined(__FreeBSD__) || defined(__DARWIN__) || defined(__EMX__)
+        // include stdlib.h for wchar_t, wcslen is provided in wxchar.cpp
+        #include <stdlib.h>
+        size_t WXDLLEXPORT wcslen(const wchar_t *s);
+    #endif // HAVE_WCHAR_H
+#endif // wxUSE_WCHAR_T
+
 // ----------------------------------------------------------------------------
-// define wxHAVE_TCHAR_FUNCTIONS for the compilers which support the
-// wide-character functions
+// define wxHAVE_TCHAR_SUPPORT for the compilers which support the TCHAR type
+// mapped to either char or wchar_t depending on the ASCII/Unicode mode and have
+// the function mapping _tfoo() -> foo() or wfoo()
 // ----------------------------------------------------------------------------
 
 // VC++ and BC++ starting with 5.2 have TCHAR support
 #ifdef __VISUALC__
-    #define wxHAVE_TCHAR_FUNCTIONS
+    #define wxHAVE_TCHAR_SUPPORT
 #elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)
-    #define wxHAVE_TCHAR_FUNCTIONS
+    #define wxHAVE_TCHAR_SUPPORT
+    #include <ctype.h>
 #elif defined(__MINGW32__) && wxCHECK_W32API_VERSION( 1, 0 )
-    #define wxHAVE_TCHAR_FUNCTIONS
+    #define wxHAVE_TCHAR_SUPPORT
     #include <stddef.h>
     #include <string.h>
     #include <ctype.h>
-#elif defined(__CYGWIN__)
+#elif 0 && defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
+    // VZ: the old VisualAge definitions were completely wrong and had no
+    //     chance at all to work in Unicode build anyhow so let's pretend that
+    //     VisualAge does _not_ support TCHAR for the moment (as indicated by
+    //     "0 &&" above) until someone really has time to delve into Unicode
+    //     issues under OS/2
+
+    // VisualAge 4.0+ supports TCHAR
+    #define wxHAVE_TCHAR_SUPPORT
+#endif // compilers with (good) TCHAR support
+
+#ifdef wxHAVE_TCHAR_SUPPORT
+    // get TCHAR definition if we've got it
+    #include <tchar.h>
+
+    // we surely do have wchar_t if we have TCHAR
+    #ifndef wxUSE_WCHAR_T
+        #define wxUSE_WCHAR_T 1
+    #endif // !defined(wxUSE_WCHAR_T)
+
+    // and we also do have wcslen()
     #ifndef HAVE_WCSLEN
         #define HAVE_WCSLEN
-    #endif // !HAVE_WCSLEN
-    #include <stddef.h>
-    #include <wchar.h>
-#elif defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
-    // VisualAge 4.0+ supports TCHAR
-    #define wxHAVE_TCHAR_FUNCTIONS
-
-    // but not stdio.h nor time nor conversion functions
-    #define wxNO_TCHAR_STDIO
-    #define wxNO_TCHAR_STDLIB
-    #define wxNO_TCHAR_TIME
-    #define wxNO_TCHAR_LOCALE
-    //
-    // supplemental VA V4 defs so at least we know what these are
-    // just define to standard defs
-    //
-
-    // for wcslen
-    #include <wchar.h>
-
-    // locale.h functons -- not defined in tchar.h
-    #define  wxSetlocale setlocale
-    // some stdio functions are defined others are not
-    // these are not
-    #define  wxFgetchar  fgetchar
-    #define  wxFopen     fopen
-    #define  wxFputchar  fputchar
-    #define  wxFreopen   freopen
-    #define  wxGets      gets
-    #define  wxPerror    perror
-    #define  wxPuts      puts
-    #define  wxRemove    remove
-    #define  wxRename    rename
-    #define  wxTmpnam    tmpnam
-    #define  wxUngetc    ungetc
-    #define  wxVsscanf   vsscanf
-    // stdlib not defined in VA V4
-    #if !wxUSE_UNICODE
-    #  define  wxAtof      atof
-    #endif
-    #define  wxAtoi      atoi
-    #define  wxAtol      atol
-    #define  wxGetenv    getenv
-    #define  wxSystem    system
-    // time.h functions  -- none defined in tchar.h
-    #define  wxAsctime   asctime
-    #define  wxCtime     ctime
-#elif defined(__MWERKS__) || defined(__VISAGECPP__)
-    // for wcslen
-    #if wxUSE_WCHAR_T
-    #include <wchar.h>
     #endif
-#endif // compilers with (good) TCHAR support
+#endif // wxHAVE_TCHAR_SUPPORT
+
+// ----------------------------------------------------------------------------
+// define wxChar type
+// ----------------------------------------------------------------------------
+
+// TODO: define wxCharInt to be equal to either int or wint_t?
 
-#ifdef wxHAVE_TCHAR_FUNCTIONS
-#  define HAVE_WCSLEN 1
+#if !wxUSE_UNICODE
+    typedef char wxChar;
+    typedef signed char wxSChar;
+    typedef unsigned char wxUChar;
+#else // Unicode
+    // VZ: note that VC++ defines _T[SU]CHAR simply as wchar_t and not as
+    //     signed/unsigned version of it which (a) makes sense to me (unlike
+    //     char wchar_t is always unsigned) and (b) was how the previous
+    //     definitions worked so keep it like this
+
+    // GNU libc has __WCHAR_TYPE__ which requires special treatment, see
+    // comment below
+    #if !defined(__WCHAR_TYPE__) || \
+        (!defined(__GNUC__) || wxCHECK_GCC_VERSION(2, 96))
+        // standard case
+        typedef wchar_t wxChar;
+        typedef wchar_t wxSChar;
+        typedef wchar_t wxUChar;
+    #else // __WCHAR_TYPE__ and gcc < 2.96
+        // VS: wxWindows used to define wxChar as __WCHAR_TYPE__ here. However,
+        //     this doesn't work with new GCC 3.x compilers because wchar_t is
+        //     C++'s builtin type in the new standard. OTOH, old compilers (GCC
+        //     2.x) won't accept new definition of wx{S,U}Char, therefore we
+        //     have to define wxChar conditionally depending on detected
+        //     compiler & compiler version.
+        //     with old definition of wxChar.
+        typedef __WCHAR_TYPE__ wxChar;
+        typedef __WCHAR_TYPE__ wxSChar;
+        typedef __WCHAR_TYPE__ wxUChar;
+    #endif // __WCHAR_TYPE__
+#endif // ASCII/Unicode
 
-#  include <tchar.h>
+// ----------------------------------------------------------------------------
+// define _T() and related macros
+// ----------------------------------------------------------------------------
 
-#  if wxUSE_UNICODE // temporary - preserve binary compatibility
-#if defined(__GNUWIN32__)
-    #define _TCHAR   TCHAR
-    #define _TSCHAR  TCHAR
-    #define _TUCHAR  TCHAR
+// BSD systems define _T() to be something different, override it
+#if defined(__FreeBSD__) || defined(__DARWIN__)
+    #undef _T
 #endif
 
-typedef  _TCHAR      wxChar;
-typedef  _TSCHAR     wxSChar;
-typedef  _TUCHAR     wxUChar;
-#  else
-#    define wxChar char
-#    define wxSChar signed char
-#    define wxUChar unsigned char
-#  endif
+// could already be defined by tchar.h (it's quasi standard)
+#ifndef _T
+    #if !wxUSE_UNICODE
+        #define _T(x) x
+    #else // Unicode
+        #define _T(x) L ## x
+    #endif // ASCII/Unicode
+#endif // !defined(_T)
 
-    // wchar_t is available
-    #ifndef wxUSE_WCHAR_T
-        #define wxUSE_WCHAR_T 1
-    #endif // !defined(wxUSE_WCHAR_T)
+// although global macros with such names are normally bad, we want to have
+// another name for _T() which should be used to avoid confusion between _T()
+// and _() in wxWindows sources
+#define wxT(x)       _T(x)
 
-   // ctype.h functions
-#ifndef wxNO_TCHAR_CTYPE
-#ifdef __BORLANDC__
-#  include <ctype.h>
+// Unicode-friendly __FILE__, __DATE__ and __TIME__ analogs
+#ifndef __TFILE__
+    #define __XFILE__(x) wxT(x)
+    #define __TFILE__ __XFILE__(__FILE__)
 #endif
-#  define  wxIsalnum   _istalnum
-#  define  wxIsalpha   _istalpha
-#  define  wxIsctrl    _istctrl
-#  define  wxIsdigit   _istdigit
-#  define  wxIsgraph   _istgraph
-#  define  wxIslower   _istlower
-#  define  wxIsprint   _istprint
-#  define  wxIspunct   _istpunct
-#  define  wxIsspace   _istspace
-#  define  wxIsupper   _istupper
-#  define  wxIsxdigit  _istxdigit
-#  define  wxTolower   _totlower
-#  define  wxToupper   _totupper
-#endif // wxNO_TCHAR_CTYPE
-
-   // locale.h functons
-#ifndef wxNO_TCHAR_LOCALE
-#  define  wxSetlocale _tsetlocale
-#endif // wxNO_TCHAR_LOCALE
-
-   // string.h functions
-#ifndef wxNO_TCHAR_STRING
-#  define  wxStrcat    _tcscat
-#  define  wxStrchr    _tcschr
-#  define  wxStrcmp    _tcscmp
-#  define  wxStrcoll   _tcscoll
-#  define  wxStrcpy    _tcscpy
-#  define  wxStrcspn   _tcscspn
-#  define  wxStrftime  _tcsftime
-#  define  wxStricmp   _tcsicmp
-#  define  wxStrnicmp  _tcsnicmp
-#  define  wxStrlen_   _tcslen // used in wxStrlen inline function
-#  define  wxStrncat   _tcsncat
-#  define  wxStrncmp   _tcsncmp
-#  define  wxStrncpy   _tcsncpy
-#  define  wxStrpbrk   _tcspbrk
-#  define  wxStrrchr   _tcsrchr
-#  define  wxStrspn    _tcsspn
-#  define  wxStrstr    _tcsstr
-#  define  wxStrtod    _tcstod
-#  define  wxStrtol    _tcstol
-#  define  wxStrtoul   _tcstoul
-#  define  wxStrxfrm   _tcsxfrm
-#endif // wxNO_TCHAR_STRING
-
-   // stdio.h functions
-#ifndef wxNO_TCHAR_STDIO
-#  if wxUSE_UNICODE_MSLU
-#    define  wxRemove    wxMSLU__tremove
-#    define  wxRename    wxMSLU__trename
-#  else
-#    define  wxRemove    _tremove
-#    define  wxRename    _trename
-#  endif
-#  define  wxFgetc     _fgettc
-#  define  wxFgetchar  _fgettchar
-#  define  wxFgets     _fgetts
-#  define  wxFopen     _tfopen
-#  define  wxFputc     _fputtc
-#  define  wxFputchar  _fputtchar
-#  define  wxFprintf   _ftprintf
-#  define  wxFreopen   _tfreopen
-#  define  wxFscanf    _ftscanf
-#  define  wxGetc      _gettc
-#  define  wxGetchar   _gettchar
-#  define  wxGets      _getts
-#  define  wxPerror    _tperror
-#  define  wxPrintf    _tprintf
-#  define  wxPutc      _puttc
-#  define  wxPutchar   _puttchar
-#  define  wxPuts      _putts
-#  define  wxScanf     _tscanf
-#  define  wxSprintf   _stprintf
-#  define  wxSscanf    _stscanf
-#  define  wxTmpnam    _ttmpnam
-#  define  wxUngetc    _tungetc
-#  define  wxVfprint   _vftprintf
-#  define  wxVprintf   _vtprintf
-#  define  wxVsscanf   _vstscanf
-#  define  wxVsprintf  _vstprintf
-#elif defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
-    // it has some stdio.h functions, apparently
-#  define  wxFgetc     _fgettc
-#  define  wxFgets     _fgetts
-#  define  wxFputc     _fputtc
-#  define  wxFprintf   _ftprintf
-#  define  wxFscanf    _ftscanf
-#  define  wxGetc      _gettc
-#  define  wxGetchar   _gettchar
-#  define  wxPrintf    _tprintf
-#  define  wxPutc      _puttc
-#  define  wxPutchar   _puttchar
-#  define  wxScanf     _tscanf
-#  define  wxSprintf   _stprintf
-#  define  wxSscanf    _stscanf
-#  define  wxVfprint   _vftprintf
-#  define  wxVprintf   _vtprintf
-#  define  wxVsprintf  _vstprintf
-#endif // wxNO_TCHAR_STDIO
-
-   // stdlib.h functions
-#ifndef wxNO_TCHAR_STDLIB
-#  if !wxUSE_UNICODE
-#    define  wxAtof    atof
-#  endif
-#  define  wxAtoi      _ttoi
-#  define  wxAtol      _ttol
-#  define  wxGetenv    _tgetenv
-#  define  wxSystem    _tsystem
-#endif // wxNO_TCHAR_STDLIB
-
-   // time.h functions
-#ifndef wxNO_TCHAR_TIME
-#  define  wxAsctime   _tasctime
-#  define  wxCtime     _tctime
-#endif // wxNO_TCHAR_TIME
 
-#else // !TCHAR-aware compilers
+#ifndef __TDATE__
+    #define __XDATE__(x) wxT(x)
+    #define __TDATE__ __XDATE__(__DATE__)
+#endif
 
-// check whether we should include wchar.h or equivalent
-#  if !defined(wxUSE_WCHAR_T)
-#    if defined(__VISUALC__) && (__VISUALC__ < 900)
-#      define wxUSE_WCHAR_T 0 // wchar_t is not available for MSVC++ 1.5
-#    elif defined(__UNIX__)
-#      if defined(HAVE_WCSTR_H) || defined(HAVE_WCHAR_H) || defined(__FreeBSD__) || defined(__DARWIN__)
-#        define wxUSE_WCHAR_T 1
-#      else
-#        define wxUSE_WCHAR_T 0
-#      endif
-#    elif defined(__GNUWIN32__) && !defined(__MINGW32__) // Cygwin (not Mingw32) doesn't have wcslen.h, needed in buffer.h
-#      define wxUSE_WCHAR_T 0
-#    elif defined(__BORLANDC__) // WIN16 BC++
-#      define wxUSE_WCHAR_T 0
-#    elif defined(__WATCOMC__)
-#      define wxUSE_WCHAR_T 0
-#    elif defined(__VISAGECPP__) && (__IBMCPP__ < 400)
-#      define wxUSE_WCHAR_T 0
-#    else
-       // add additional compiler checks if this fails
-#      define wxUSE_WCHAR_T 1
-#    endif
-#  endif // !defined(wxUSE_WCHAR_T)
-
-#   if wxUSE_WCHAR_T
-#       ifdef HAVE_WCHAR_H
-            // include wchar.h to get wcslen() declaration used by wx/buffer.h
-            // stddef.h is needed for Cygwin
-#           include <stddef.h>
-#           include <wchar.h>
-#       elif defined(HAVE_WCSTR_H)
-            // old compilers have wcslen() here
-#           include <wcstr.h>
-#       elif defined(__FreeBSD__) || defined(__DARWIN__) || defined(__EMX__)
-            // include stdlib.h for wchar_t, wcslen is provided in wxchar.cpp
-#           include <stdlib.h>
-            size_t WXDLLEXPORT wcslen(const wchar_t *s);
-#       endif // HAVE_WCHAR_H
-#   endif // wxUSE_WCHAR_T
-
-// check whether we are doing Unicode
-#  if wxUSE_UNICODE
-
-#    include <wctype.h>
-
-// this is probably glibc-specific
-#    if defined(__WCHAR_TYPE__)
-
-// VS: wxWindows used to define wxChar as __WCHAR_TYPE__ here. However, this doesn't
-//     work with new GCC 3.x compilers because wchar_t is C++'s builtin type in the new
-//     standard. OTOH, old compilers (GCC 2.x) won't accept new definition
-//     of wx{S,U}Char, therefore we have to define wxChar conditionally depending on
-//     detected compiler & compiler version.
-//     The most complicated case is the infamous so-called "gcc-2.96" which does not
-//     accept new definition of wxSChar but doesn't work with old definition of wxChar.
-#if defined(__GNUC__) && (__GNUC__ >= 3)
-    // modern C++ compiler
-    typedef wchar_t                 wxChar;
-    typedef signed wchar_t          wxSChar;
-    typedef unsigned wchar_t        wxUChar;
-#else
-    #if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 96)
-    typedef wchar_t                 wxChar;
-    #else
-    typedef __WCHAR_TYPE__          wxChar;
-    #endif
-    typedef signed __WCHAR_TYPE__   wxSChar;
-    typedef unsigned __WCHAR_TYPE__ wxUChar;
+#ifndef __TTIME__
+    #define __XTIME__(x) wxT(x)
+    #define __TTIME__ __XTIME__(__TIME__)
 #endif
 
-#      define _T(x)                   L##x
-
-       // ctype.h functions (wctype.h)
-#      define  wxIsalnum   iswalnum
-#      define  wxIsalpha   iswalpha
-#      define  wxIsctrl    iswcntrl
-#      define  wxIsdigit   iswdigit
-#      define  wxIsgraph   iswgraph
-#      define  wxIslower   iswlower
-#      define  wxIsprint   iswprint
-#      define  wxIspunct   iswpunct
-#      define  wxIsspace   iswspace
-#      define  wxIsupper   iswupper
-#      define  wxIsxdigit  iswxdigit
-
-#      if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)
-       // /usr/include/wctype.h incorrectly declares translations tables which
-       // provokes tons of compile-time warnings - try to correct this
-#        define  wxTolower(wc)   towctrans((wc), (wctrans_t)__ctype_tolower)
-#        define  wxToupper(wc)   towctrans((wc), (wctrans_t)__ctype_toupper)
-#      else
-#        define  wxTolower   towlower
-#        define  wxToupper   towupper
-#      endif // gcc/!gcc
-
-       // string.h functions (wchar.h)
-#      define  wxStrcat    wcscat
-#      define  wxStrchr    wcschr
-#      define  wxStrcmp    wcscmp
-#      define  wxStrcoll   wcscoll
-#      define  wxStrcpy    wcscpy
-#      define  wxStrcspn   wcscspn
-#      define  wxStrlen_   wcslen // used in wxStrlen inline function
-#      define  wxStrncat   wcsncat
-#      define  wxStrncmp   wcsncmp
-#      define  wxStrncpy   wcsncpy
-#      define  wxStrpbrk   wcspbrk
-#      define  wxStrrchr   wcsrchr
-#      define  wxStrspn    wcsspn
-#      define  wxStrstr    wcsstr
-#      define  wxStrtod    wcstod
-#      define  wxStrtok    wcstok
-#      define  wxStrtol    wcstol
-#      define  wxStrtoul   wcstoul
-#      define  wxStrxfrm   wcsxfrm
-
-#      define  wxFgetc     fgetwc
-#      define  wxFgetchar  fgetwchar
-#      define  wxFgets     fgetws
-#      define  wxFputc     fputwc
-#      define  wxFputchar  fputwchar
-#      define  wxGetc      getwc
-#      define  wxGetchar   getwchar
-#      define  wxGets      getws
-#      define  wxPutc      wputc
-#      define  wxPutchar   wputchar
-#      define  wxPuts      putws
-#      define  wxUngetc    ungetwc
-
-// we need %s to %ls conversion for printf and scanf etc
-#      define wxNEED_PRINTF_CONVERSION
-#      define wxHAS_VSNPRINTF
-#      define wxHAS_SNPRINTF
-
-// glibc doesn't have wc equivalents of the other stuff
-#      define wxNEED_WX_STDIO_H
-#      define wxNEED_WX_STDLIB_H
-#      define wxNEED_WX_TIME_H
-
-#    else//!glibc
-#      error   "Please define your compiler's Unicode conventions in wxChar.h"
-#    endif
-#  else//!Unicode
-
-#    include <ctype.h>
-#    include <string.h>
-
-    typedef char            wxChar;
-    typedef signed char     wxSChar;
-    typedef unsigned char   wxUChar;
-
-#   if defined(__FreeBSD__) || defined(__DARWIN__)
-#     undef _T
-#   endif
-
-#   if !defined(__MINGW32__) || !defined(_T)
-#     define _T(x)           x
-#   endif
-
-     // ctype.h functions
-#   define  wxIsalnum   isalnum
-#   define  wxIsalpha   isalpha
-#   define  wxIsctrl    isctrl
-#   define  wxIsdigit   isdigit
-#   define  wxIsgraph   isgraph
-#   define  wxIslower   islower
-#   define  wxIsprint   isprint
-#   define  wxIspunct   ispunct
-#   define  wxIsspace   isspace
-#   define  wxIsupper   isupper
-#   define  wxIsxdigit  isxdigit
-#   define  wxTolower   tolower
-#   define  wxToupper   toupper
+// ----------------------------------------------------------------------------
+// define wxFoo() function for each standard foo() function whose signature
+// (exceptionally including the return type) includes any mention of char:
+// wxFoo() is going to be a Unicode-friendly version of foo(), i.e. will have
+// the same signature but with char replaced by wxChar which allows us to use
+// it in Unicode build as well
+// ----------------------------------------------------------------------------
+
+#ifdef wxHAVE_TCHAR_SUPPORT
+    // ctype.h functions
+    #define  wxIsalnum   _istalnum
+    #define  wxIsalpha   _istalpha
+    #define  wxIsctrl    _istctrl
+    #define  wxIsdigit   _istdigit
+    #define  wxIsgraph   _istgraph
+    #define  wxIslower   _istlower
+    #define  wxIsprint   _istprint
+    #define  wxIspunct   _istpunct
+    #define  wxIsspace   _istspace
+    #define  wxIsupper   _istupper
+    #define  wxIsxdigit  _istxdigit
+    #define  wxTolower   _totlower
+    #define  wxToupper   _totupper
 
     // locale.h functons
-#   define  wxSetlocale setlocale
+    #define  wxSetlocale _tsetlocale
 
     // string.h functions
-    // #define  wxStricmp   strcasecmp
-    // wxStricmp is defined below!!
-
-    #ifdef HAVE_STRTOK_R
-        #define  wxStrtok(str, sep, last)    strtok_r(str, sep, last)
+    #define  wxStrcat    _tcscat
+    #define  wxStrchr    _tcschr
+    #define  wxStrcmp    _tcscmp
+    #define  wxStrcoll   _tcscoll
+    #define  wxStrcpy    _tcscpy
+    #define  wxStrcspn   _tcscspn
+    #define  wxStrftime  _tcsftime
+    #define  wxStricmp   _tcsicmp
+    #define  wxStrnicmp  _tcsnicmp
+    #define  wxStrlen_   _tcslen        // used in wxStrlen inline function
+    #define  wxStrncat   _tcsncat
+    #define  wxStrncmp   _tcsncmp
+    #define  wxStrncpy   _tcsncpy
+    #define  wxStrpbrk   _tcspbrk
+    #define  wxStrrchr   _tcsrchr
+    #define  wxStrspn    _tcsspn
+    #define  wxStrstr    _tcsstr
+    #define  wxStrtod    _tcstod
+    #define  wxStrtol    _tcstol
+    #define  wxStrtoul   _tcstoul
+    #define  wxStrxfrm   _tcsxfrm
+
+    // stdio.h functions
+    #define  wxFgetc     _fgettc
+    #define  wxFgetchar  _fgettchar
+    #define  wxFgets     _fgetts
+    #define  wxFopen     _tfopen
+    #define  wxFputc     _fputtc
+    #define  wxFputchar  _fputtchar
+    #define  wxFprintf   _ftprintf
+    #define  wxFputs     _fputts
+    #define  wxFreopen   _tfreopen
+    #define  wxFscanf    _ftscanf
+    #define  wxGetc      _gettc
+    #define  wxGetchar   _gettchar
+    #define  wxGets      _getts
+    #define  wxPerror    _tperror
+    #define  wxPrintf    _tprintf
+    #define  wxPutc      _puttc
+    #define  wxPutchar   _puttchar
+    #define  wxPuts      _putts
+    #define  wxScanf     _tscanf
+    #define  wxSprintf   _stprintf
+    #define  wxSscanf    _stscanf
+    #define  wxTmpnam    _ttmpnam
+    #define  wxUngetc    _tungetc
+    #define  wxVfprintf  _vftprintf
+    #define  wxVprintf   _vtprintf
+    #define  wxVsscanf   _vstscanf
+    #define  wxVsprintf  _vstprintf
+
+    // special case: these functions are missing under Win9x with Unicows so we
+    // have to implement them ourselves
+    #if wxUSE_UNICODE_MSLU
+        #define  wxRemove    wxMSLU__tremove
+        #define  wxRename    wxMSLU__trename
     #else
-        #define  wxStrtok(str, sep, last)    strtok(str, sep)
+        #define  wxRemove    _tremove
+        #define  wxRename    _trename
     #endif
 
-     // leave the rest to defaults below
-#   define wxNEED_WX_STRING_H
-#   define wxNEED_WX_STDIO_H
-#   define wxNEED_WX_STDLIB_H
-#   define wxNEED_WX_TIME_H
+    // stdlib.h functions
+    #define  wxAtoi      _ttoi
+    #define  wxAtol      _ttol
+    // #define  wxAtof   _tttof -- notice that there is no such thing (why?)
+    #define  wxGetenv    _tgetenv
+    #define  wxSystem    _tsystem
 
-#  endif//Unicode
-#endif//TCHAR-aware compilers
+    // time.h functions
+    #define  wxAsctime   _tasctime
+    #define  wxCtime     _tctime
+#else // !TCHAR-aware compilers
+    #if wxUSE_UNICODE
+        #include <wctype.h>
+
+        // this is probably glibc-specific
+        #if defined(__WCHAR_TYPE__)
+            // ctype.h functions (wctype.h)
+            #define  wxIsalnum   iswalnum
+            #define  wxIsalpha   iswalpha
+            #define  wxIsctrl    iswcntrl
+            #define  wxIsdigit   iswdigit
+            #define  wxIsgraph   iswgraph
+            #define  wxIslower   iswlower
+            #define  wxIsprint   iswprint
+            #define  wxIspunct   iswpunct
+            #define  wxIsspace   iswspace
+            #define  wxIsupper   iswupper
+            #define  wxIsxdigit  iswxdigit
+
+            #if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)
+                // /usr/include/wctype.h incorrectly declares translations
+                // tables which provokes tons of compile-time warnings -- try
+                // to correct this
+                #define  wxTolower(wc)   towctrans((wc), (wctrans_t)__ctype_tolower)
+                #define  wxToupper(wc)   towctrans((wc), (wctrans_t)__ctype_toupper)
+            #else // !glibc 2.0
+                #define  wxTolower   towlower
+                #define  wxToupper   towupper
+            #endif // gcc/!gcc
+
+            // string.h functions (wchar.h)
+            #define  wxStrcat    wcscat
+            #define  wxStrchr    wcschr
+            #define  wxStrcmp    wcscmp
+            #define  wxStrcoll   wcscoll
+            #define  wxStrcpy    wcscpy
+            #define  wxStrcspn   wcscspn
+            #define  wxStrlen_   wcslen // used in wxStrlen inline function
+            #define  wxStrncat   wcsncat
+            #define  wxStrncmp   wcsncmp
+            #define  wxStrncpy   wcsncpy
+            #define  wxStrpbrk   wcspbrk
+            #define  wxStrrchr   wcsrchr
+            #define  wxStrspn    wcsspn
+            #define  wxStrstr    wcsstr
+            #define  wxStrtod    wcstod
+            #define  wxStrtok    wcstok
+            #define  wxStrtol    wcstol
+            #define  wxStrtoul   wcstoul
+            #define  wxStrxfrm   wcsxfrm
+
+            #define  wxFgetc     fgetwc
+            #define  wxFgetchar  fgetwchar
+            #define  wxFgets     fgetws
+            #define  wxFputc     fputwc
+            #define  wxFputchar  fputwchar
+            #define  wxGetc      getwc
+            #define  wxGetchar   getwchar
+            #define  wxGets      getws
+            #define  wxUngetc    ungetwc
+
+            #ifdef HAVE_FPUTWC
+                #define  wxPutc      wputc
+                #define  wxPutchar   wputchar
+                #define  wxPuts      putws
+                #define  wxFputs     fputws
+            #else
+                #include <stdio.h>
+
+                int wxFputs(const wxChar *ch, FILE *stream);
+                int wxPutc(wxChar ch, FILE *stream);
+
+                #define wxPuts(ws) wxFputs(ws, stdout)
+                #define wxPutchar(wch) wxPutc(wch, stdout)
+            #endif
+
+            // we need %s to %ls conversion for printf and scanf etc
+            #define wxNEED_PRINTF_CONVERSION
+
+            // glibc doesn't have wide char equivalents of the other stuff so
+            // use our own versions
+            #define wxNEED_WX_STDIO_H
+            #define wxNEED_WX_STDLIB_H
+            #define wxNEED_WX_TIME_H
+        #else // !glibc
+            #error  "Please define wide character functions for your environment"
+        #endif
+    #else // ASCII
+        #include <ctype.h>
+        #include <string.h>
+
+        // ctype.h functions
+        #define  wxIsalnum   isalnum
+        #define  wxIsalpha   isalpha
+        #define  wxIsctrl    isctrl
+        #define  wxIsdigit   isdigit
+        #define  wxIsgraph   isgraph
+        #define  wxIslower   islower
+        #define  wxIsprint   isprint
+        #define  wxIspunct   ispunct
+        #define  wxIsspace   isspace
+        #define  wxIsupper   isupper
+        #define  wxIsxdigit  isxdigit
+        #define  wxTolower   tolower
+        #define  wxToupper   toupper
+
+         // locale.h functons
+        #define  wxSetlocale setlocale
+
+         // string.h functions
+        #define  wxStrcat    strcat
+        #define  wxStrchr    strchr
+        #define  wxStrcmp    strcmp
+        #define  wxStrcoll   strcoll
+        #define  wxStrcpy    strcpy
+        #define  wxStrcspn   strcspn
+        #if !defined(__MWERKS__) || !defined(__WXMAC__)
+            #define  wxStrdup    strdup
+        #endif
+        // wxStricmp and wxStrnicmp are defined below
+        #define  wxStrlen_   strlen // used in wxStrlen inline function
+        #define  wxStrncat   strncat
+        #define  wxStrncmp   strncmp
+        #define  wxStrncpy   strncpy
+        #define  wxStrpbrk   strpbrk
+        #define  wxStrrchr   strrchr
+        #define  wxStrspn    strspn
+        #define  wxStrstr    strstr
+        #define  wxStrtod    strtod
+        #ifdef HAVE_STRTOK_R
+            #define  wxStrtok(str, sep, last)    strtok_r(str, sep, last)
+        #else
+            #define  wxStrtok(str, sep, last)    strtok(str, sep)
+        #endif
+        #define  wxStrtol    strtol
+        #define  wxStrtoul   strtoul
+        #define  wxStrxfrm   strxfrm
+
+        // stdio.h functions
+        #define  wxFopen     fopen
+        #define  wxFreopen   freopen
+        #define  wxPerror    perror
+        #define  wxRemove    remove
+        #define  wxRename    rename
+        #define  wxTmpnam    tmpnam
+
+        #define  wxFgetc     fgetc
+        #define  wxFgetchar  fgetchar
+        #define  wxFgets     fgets
+        #define  wxFputc     fputc
+        #define  wxFputchar  fputchar
+        #define  wxFprintf   fprintf
+        #define  wxFscanf    fscanf
+        #define  wxGetc      getc
+        #define  wxGetchar   getchar
+        #define  wxGets      gets
+        #define  wxPrintf    printf
+        #define  wxPutc      putc
+        #define  wxPutchar   putchar
+        #define  wxPuts      puts
+        #define  wxScanf     scanf
+        #define  wxSprintf   sprintf
+        #define  wxSscanf    sscanf
+        #define  wxUngetc    ungetc
+        #define  wxVfprintf  vfprintf
+        #define  wxVprintf   vprintf
+        #define  wxVsscanf   vsscanf
+        #define  wxVsprintf  vsprintf
+
+        // stdlib.h functions
+        #define  wxAtof      atof
+        #define  wxAtoi      atoi
+        #define  wxAtol      atol
+        #define  wxGetenv    getenv
+        #define  wxSystem    system
+
+        // time.h functions
+        #define  wxAsctime   asctime
+        #define  wxCtime     ctime
+        #define  wxStrftime  strftime
+    #endif // Unicode/ASCII
+#endif // TCHAR-aware compilers/the others
 
-// define wxStricmp for various compilers without Unicode possibilities
-#if !defined(wxStricmp) && !wxUSE_UNICODE
-#  if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__SALFORDC__) || defined(__VISAGECPP__) || defined(__EMX__) || defined(__DJGPP__)
-#    define wxStricmp stricmp
-#    define wxStrnicmp strnicmp
-#  elif defined(__SC__) || defined(__VISUALC__) || (defined(__MWERKS__) && defined(__INTEL__))
-#    define wxStricmp _stricmp
-#    define wxStrnicmp _strnicmp
-#  elif defined(__UNIX__) || defined(__GNUWIN32__)
-#    define wxStricmp strcasecmp
-#    define wxStrnicmp strncasecmp
-#  elif defined(__MWERKS__) && !defined(__INTEL__)
-     // use wxWindows' implementation
-#  else
-     // if you leave wxStricmp undefined, wxWindows' implementation will be used
-#    error  "Please define string case-insensitive compare for your OS/compiler"
-#  endif
-#endif
+// ----------------------------------------------------------------------------
+// various special cases
+// ----------------------------------------------------------------------------
 
-// if we need to define for standard headers, and we're not using Unicode,
-// just define to standard C library routines
-#if !wxUSE_UNICODE
-#  ifdef wxNEED_WX_STRING_H
-#    define  wxStrcat    strcat
-#    define  wxStrchr    strchr
-#    define  wxStrcmp    strcmp
-#    define  wxStrcoll   strcoll
-#    define  wxStrcpy    strcpy
-#    define  wxStrcspn   strcspn
-#if !defined(__MWERKS__) || !defined(__WXMAC__)
-#    define  wxStrdup    strdup
-#endif
-#    define  wxStrlen_   strlen // used in wxStrlen inline function
-#    define  wxStrncat   strncat
-#    define  wxStrncmp   strncmp
-#    define  wxStrncpy   strncpy
-#    define  wxStrpbrk   strpbrk
-#    define  wxStrrchr   strrchr
-#    define  wxStrspn    strspn
-#    define  wxStrstr    strstr
-#    define  wxStrtod    strtod
-#    define  wxStrtol    strtol
-#    define  wxStrtoul   strtoul
-#    define  wxStrxfrm   strxfrm
-#    undef wxNEED_WX_STRING_H
-#  endif
-
-#  ifdef wxNEED_WX_STDIO_H
-#    define  wxFopen     fopen
-#    define  wxFreopen   freopen
-#    define  wxPerror    perror
-#    define  wxRemove    remove
-#    define  wxRename    rename
-#    define  wxTmpnam    tmpnam
-
-#    define  wxFgetc     fgetc
-#    define  wxFgetchar  fgetchar
-#    define  wxFgets     fgets
-#    define  wxFputc     fputc
-#    define  wxFputchar  fputchar
-#    define  wxFprintf   fprintf
-#    define  wxFscanf    fscanf
-#    define  wxGetc      getc
-#    define  wxGetchar   getchar
-#    define  wxGets      gets
-#    define  wxPrintf    printf
-#    define  wxPutc      putc
-#    define  wxPutchar   putchar
-#    define  wxPuts      puts
-#    define  wxScanf     scanf
-#    define  wxSprintf   sprintf
-#    define  wxSscanf    sscanf
-#    define  wxUngetc    ungetc
-#    define  wxVfprint   vfprintf
-#    define  wxVprintf   vprintf
-#    define  wxVsscanf   vsscanf
-#    define  wxVsprintf  vsprintf
-#    undef wxNEED_WX_STDIO_H
-#  endif
-
-
-#  ifdef wxNEED_WX_STDLIB_H
-#    define  wxAtof      atof
-#    define  wxAtoi      atoi
-#    define  wxAtol      atol
-#    define  wxGetenv    getenv
-#    define  wxSystem    system
-#    undef wxNEED_WX_STDLIB_H
-#  endif
-
-#  ifdef wxNEED_WX_TIME_H
-#    define  wxAsctime   asctime
-#    define  wxCtime     ctime
-#    define  wxStrftime  strftime
-#    undef wxNEED_WX_TIME_H
-#  endif
-#endif //!Unicode
+// define wxStricmp and wxStrnicmp for various compilers
+//
+// note that in Unicode mode we definitely are going to need our own version
+#if !defined(wxStricmp) && !wxUSE_UNICODE
+    #if defined(__BORLANDC__) || defined(__WATCOMC__) || \
+            defined(__SALFORDC__) || defined(__VISAGECPP__) || \
+            defined(__EMX__) || defined(__DJGPP__)
+        #define wxStricmp stricmp
+        #define wxStrnicmp strnicmp
+    #elif defined(__SC__) || defined(__VISUALC__) || \
+            (defined(__MWERKS__) && defined(__INTEL__))
+        #define wxStricmp _stricmp
+        #define wxStrnicmp _strnicmp
+    #elif defined(__UNIX__) || defined(__GNUWIN32__)
+        #define wxStricmp strcasecmp
+        #define wxStrnicmp strncasecmp
+    // #else -- use wxWindows implementation
+    #endif
+#endif // !defined(wxStricmp)
 
 // checks whether the passed in pointer is NULL and if the string is empty
 inline bool wxIsEmpty(const wxChar *p) { return !p || !*p; }
 
-#ifndef wxNEED_WX_STRING_H
 // safe version of strlen() (returns 0 if passed NULL pointer)
-inline size_t wxStrlen(const wxChar *psz)
-   { return psz ? wxStrlen_(psz) : 0; }
-#endif
+inline size_t wxStrlen(const wxChar *psz) { return psz ? wxStrlen_(psz) : 0; }
 
+// define wxWcslen() which should be always available if wxUSE_WCHAR_T == 1 (as
+// it's used in wx/buffer.h)
 #if wxUSE_WCHAR_T
-// multibyte<->widechar conversion
-WXDLLEXPORT size_t wxMB2WC(wchar_t *buf, const char *psz, size_t n);
-WXDLLEXPORT size_t wxWC2MB(char *buf, const wchar_t *psz, size_t n);
-#  if wxUSE_UNICODE
-#    define wxMB2WX wxMB2WC
-#    define wxWX2MB wxWC2MB
-#    define wxWC2WX wxStrncpy
-#    define wxWX2WC wxStrncpy
-#  else
-#    define wxMB2WX wxStrncpy
-#    define wxWX2MB wxStrncpy
-#    define wxWC2WX wxWC2MB
-#    define wxWX2WC wxMB2WC
-#  endif
-#else
-// No wxUSE_WCHAR_T: we have to do something (JACS)
-#  define wxMB2WC wxStrncpy
-#  define wxWC2MB wxStrncpy
-#  define wxMB2WX wxStrncpy
-#  define wxWX2MB wxStrncpy
-#  define wxWC2WX wxWC2MB
-#  define wxWX2WC wxMB2WC
-#endif
+    #ifdef HAVE_WCSLEN
+        #define wxWcslen wcslen
+    #else
+        inline size_t wxWcslen(const wchar_t *s)
+        {
+            size_t n = 0;
+            while ( *s++ )
+                n++;
+
+            return n;
+        }
+    #endif
+#endif // wxUSE_WCHAR_T
 
 WXDLLEXPORT bool wxOKlibc(); // for internal use
 
-// We need conversion from %s to %ls in Unicode mode under Unix
-#ifdef wxNEED_PRINTF_CONVERSION
+// ----------------------------------------------------------------------------
+// printf() family saga
+// ----------------------------------------------------------------------------
 
-#include <stdio.h>  // need FILE
+/*
+   First of all, we always want to define safe snprintf() function to be used
+   instead of sprintf(). Some compilers already have it (or rather vsnprintf()
+   which we really need...), otherwise we implement it using our own printf()
+   code.
+
+   We define function with a trailing underscore here because the real one is a
+   wrapper around it as explained below
+ */
+#ifdef wxHAVE_TCHAR_SUPPORT
+    #define wxVsnprintf_    _vsntprintf
+    #define wxSnprintf_     _sntprintf
+#else // !TCHAR
+    #if wxUSE_UNICODE
+        #if defined(HAVE_VSWPRINTF)
+            #define wxVsnprintf_    vswprintf
+        #endif
+    #else // ASCII
+        #if (defined(HAVE_VSNPRINTF) || defined(__WXMAC__))
+            // assume we have snprintf() too if we have vsnprintf()
+            #define wxVsnprintf_    vsnprintf
+            #define wxSnprintf_     snprintf
+        #endif
+    #endif
+#endif // TCHAR/!TCHAR
+
+#ifndef wxVsnprintf_
+    // no [v]snprintf(), cook our own
+    WXDLLEXPORT int wxSnprintf_(wxChar *buf, size_t len, const wxChar *format,
+                                ...) ATTRIBUTE_PRINTF_3;
+    WXDLLEXPORT int wxVsnprintf_(wxChar *buf, size_t len, const wxChar *format,
+                                 va_list argptr);
+#endif
 
-int wxScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2;
-int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
-int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
-int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap );
-int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2;
-int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_4;
-int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
-int wxFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
-int wxVfprint( const wxChar *format, va_list ap );
-int wxVprintf( const wxChar *format, va_list ap );
-int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap );
-int wxVsprintf( wxChar *str, const wxChar *format, va_list ap );
+/*
+   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
+   case.
+ */
+#if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
+    #define wxNEED_WPRINTF
+#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().
+
+   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.
+*/
+#ifndef wxVsnprintf_
+    #undef wxNEED_PRINTF_CONVERSION
+#endif
+
+#if defined(wxNEED_PRINTF_CONVERSION) || 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
+
+    #include <stdio.h>  // for FILE
+
+    int wxScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2;
+    int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
+    int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
+    int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap );
+    int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2;
+    int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
+    int wxFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3;
+    int wxVfprintf( FILE *stream, const wxChar *format, va_list ap );
+    int wxVprintf( const wxChar *format, va_list ap );
+    int wxVsprintf( wxChar *str, const wxChar *format, va_list ap );
+
+    // these 2 can be simply mapped to the versions with underscore at the end
+    // if we don't have to do the conversion
+    #ifdef wxNEED_PRINTF_CONVERSION
+        int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_4;
+        int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap );
+    #else
+        #define wxSnprintf wxSnprintf_
+        #define wxVsnprintf wxVsnprintf_
+    #endif
 #endif // wxNEED_PRINTF_CONVERSION
 
-#if !defined(wxSnprintf) && !defined(wxHAS_SNPRINTF)
-// wxSnprintf() is like snprintf() if it's available and sprintf() (always
-// available, but dangerous!) if not.
-WXDLLEXPORT int wxSnprintf(wxChar *buf, size_t len,
-                                  const wxChar *format,
-                                  ...) ATTRIBUTE_PRINTF_3;
-#endif
+// ----------------------------------------------------------------------------
+// various functions which might not be available in libc and for which we
+// provide our own replacements in wxchar.cpp
+// ----------------------------------------------------------------------------
 
-#if !defined(wxVsnprintf) && !defined(wxHAS_VSNPRINTF)
-// and wxVsnprintf() is like vsnprintf() or vsprintf()
-WXDLLEXPORT int wxVsnprintf(wxChar *buf, size_t len,
-                                   const wxChar *format,
-                                   va_list argptr);
-#endif
+// ctype.h functions
+//
+// VZ: note that this is never defined currently
+#ifdef wxNEED_WX_CTYPE_H
+    WXDLLEXPORT int wxIsalnum(wxChar ch);
+    WXDLLEXPORT int wxIsalpha(wxChar ch);
+    WXDLLEXPORT int wxIsctrl(wxChar ch);
+    WXDLLEXPORT int wxIsdigit(wxChar ch);
+    WXDLLEXPORT int wxIsgraph(wxChar ch);
+    WXDLLEXPORT int wxIslower(wxChar ch);
+    WXDLLEXPORT int wxIsprint(wxChar ch);
+    WXDLLEXPORT int wxIspunct(wxChar ch);
+    WXDLLEXPORT int wxIsspace(wxChar ch);
+    WXDLLEXPORT int wxIsupper(wxChar ch);
+    WXDLLEXPORT int wxIsxdigit(wxChar ch);
+    WXDLLEXPORT int wxTolower(wxChar ch);
+    WXDLLEXPORT int wxToupper(wxChar ch);
+#endif // wxNEED_WX_CTYPE_H
+
+// under VC++ 6.0 isspace() returns 1 for 8 bit chars which completely breaks
+// the file parsing -- this may be true for 5.0 as well, update #ifdef then
+#if defined(__VISUALC__) && (__VISUALC__ >= 1200) && !wxUSE_UNICODE
+    #undef wxIsspace
+    #define wxIsspace(c) ((((unsigned)c) < 128) && isspace(c))
+#endif // VC++
+
+
+// string.h functions
+//
+// VZ: this is never defined neither currently
+#ifdef wxNEED_WX_STRING_H
+    WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src);
+    WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c);
+    WXDLLEXPORT wxChar * wxStrchr(wxChar *s, wxChar c)
+        { return (wxChar *)wxStrchr((const wxChar *)s, c); }
+    WXDLLEXPORT int      wxStrcmp(const wxChar *s1, const wxChar *s2);
+    WXDLLEXPORT int      wxStrcoll(const wxChar *s1, const wxChar *s2);
+    WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src);
+    WXDLLEXPORT size_t   wxStrcspn(const wxChar *s, const wxChar *reject);
+    WXDLLEXPORT size_t   wxStrlen(const wxChar *s);
+    WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n);
+    WXDLLEXPORT int      wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n);
+    WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n);
+    WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept);
+    WXDLLEXPORT wxChar * wxStrpbrk(wxChar *s, const wxChar *accept)
+        { return (wxChar *)wxStrpbrk((const wxChar *)s, accept); }
+    WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c);
+    WXDLLEXPORT wxChar * wxStrrchr(wxChar *s, wxChar c)
+        { return (wxChar *)wxStrrchr((const wxChar *)s, c); }
+    WXDLLEXPORT size_t   wxStrspn(const wxChar *s, const wxChar *accept);
+    WXDLLEXPORT const wxChar * wxStrstr(const wxChar *haystack, const wxChar *needle);
+    WXDLLEXPORT wxChar *wxStrstr(wxChar *haystack, const wxChar *needle)
+        { return (wxChar *)wxStrstr((const wxChar *)haystack, needle); }
+    WXDLLEXPORT double   wxStrtod(const wxChar *nptr, wxChar **endptr);
+    WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base);
+    WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base);
+    WXDLLEXPORT size_t   wxStrxfrm(wxChar *dest, const wxChar *src, size_t n);
+#endif // wxNEED_WX_STRING_H
 
-// if libc versions are not available, use replacements defined in wxchar.cpp
 #ifndef wxStrdup
 WXDLLEXPORT wxChar * wxStrdup(const wxChar *psz);
 #endif
 
 #ifndef wxStricmp
-WXDLLEXPORT int      wxStricmp(const wxChar *psz1, const wxChar *psz2);
+WXDLLEXPORT int wxStricmp(const wxChar *psz1, const wxChar *psz2);
 #endif
 
 #ifndef wxStrnicmp
-WXDLLEXPORT int      wxStrnicmp(const wxChar *psz1, const wxChar *psz2, size_t len);
+WXDLLEXPORT int wxStrnicmp(const wxChar *psz1, const wxChar *psz2, size_t len);
 #endif
 
 #ifndef wxStrtok
@@ -660,64 +735,23 @@ WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_pt
 #endif
 
 #ifndef wxSetlocale
-class wxWCharBuffer;
+class WXDLLEXPORT wxWCharBuffer;
 WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale);
 #endif
 
-#ifdef wxNEED_WX_CTYPE_H
-WXDLLEXPORT int wxIsalnum(wxChar ch);
-WXDLLEXPORT int wxIsalpha(wxChar ch);
-WXDLLEXPORT int wxIsctrl(wxChar ch);
-WXDLLEXPORT int wxIsdigit(wxChar ch);
-WXDLLEXPORT int wxIsgraph(wxChar ch);
-WXDLLEXPORT int wxIslower(wxChar ch);
-WXDLLEXPORT int wxIsprint(wxChar ch);
-WXDLLEXPORT int wxIspunct(wxChar ch);
-WXDLLEXPORT int wxIsspace(wxChar ch);
-WXDLLEXPORT int wxIsupper(wxChar ch);
-WXDLLEXPORT int wxIsxdigit(wxChar ch);
-WXDLLEXPORT int wxTolower(wxChar ch);
-WXDLLEXPORT int wxToupper(wxChar ch);
-#endif
+// stdio.h functions
+#ifdef wxNEED_WX_STDIO_H
+    #include <stdio.h>
+    WXDLLEXPORT FILE *   wxFopen(const wxChar *path, const wxChar *mode);
+    WXDLLEXPORT FILE *   wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream);
+    WXDLLEXPORT int      wxRemove(const wxChar *path);
+    WXDLLEXPORT int      wxRename(const wxChar *oldpath, const wxChar *newpath);
 
-#ifdef wxNEED_WX_STRING_H
-WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src);
-WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c);
-WXDLLEXPORT wxChar * wxStrchr(wxChar *s, wxChar c)
-    { return (wxChar *)wxStrchr((const wxChar *)s, c); }
-WXDLLEXPORT int      wxStrcmp(const wxChar *s1, const wxChar *s2);
-WXDLLEXPORT int      wxStrcoll(const wxChar *s1, const wxChar *s2);
-WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src);
-WXDLLEXPORT size_t   wxStrcspn(const wxChar *s, const wxChar *reject);
-WXDLLEXPORT size_t   wxStrlen(const wxChar *s);
-WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n);
-WXDLLEXPORT int      wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n);
-WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n);
-WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept);
-WXDLLEXPORT wxChar * wxStrpbrk(wxChar *s, const wxChar *accept)
-    { return (wxChar *)wxStrpbrk((const wxChar *)s, accept); }
-WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c);
-WXDLLEXPORT wxChar * wxStrrchr(wxChar *s, wxChar c)
-    { return (wxChar *)wxStrrchr((const wxChar *)s, c); }
-WXDLLEXPORT size_t   wxStrspn(const wxChar *s, const wxChar *accept);
-WXDLLEXPORT const wxChar * wxStrstr(const wxChar *haystack, const wxChar *needle);
-WXDLLEXPORT wxChar *wxStrstr(wxChar *haystack, const wxChar *needle)
-    { return (wxChar *)wxStrstr((const wxChar *)haystack, needle); }
-WXDLLEXPORT double   wxStrtod(const wxChar *nptr, wxChar **endptr);
-WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base);
-WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base);
-WXDLLEXPORT size_t   wxStrxfrm(wxChar *dest, const wxChar *src, size_t n);
-#endif
+    // *printf() family is handled separately
+#endif // wxNEED_WX_STDIO_H
 
-#ifdef wxNEED_WX_STDIO_H
-#  include <stdio.h>
-#  include <stdarg.h>
-WXDLLEXPORT FILE *   wxFopen(const wxChar *path, const wxChar *mode);
-WXDLLEXPORT FILE *   wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream);
-WXDLLEXPORT int      wxRemove(const wxChar *path);
-WXDLLEXPORT int      wxRename(const wxChar *oldpath, const wxChar *newpath);
-#endif
 
+// stdlib.h functions
 #ifndef wxAtof
 WXDLLEXPORT double   wxAtof(const wxChar *psz);
 #endif
@@ -729,42 +763,42 @@ WXDLLEXPORT wxChar * wxGetenv(const wxChar *name);
 WXDLLEXPORT int      wxSystem(const wxChar *psz);
 #endif
 
-#ifdef wxNEED_WX_TIME_H
-WXDLLEXPORT size_t   wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const struct tm *tm);
-#endif
 
-// under VC++ 6.0 isspace() returns 1 for 8 bit chars which completely breaks
-// the file parsing - this may be true for 5.0 as well, update #ifdef then
-#if defined(__VISUALC__) && (__VISUALC__ >= 1200) && !wxUSE_UNICODE
-    #undef wxIsspace
-    #define wxIsspace(c) ((((unsigned)c) < 128) && isspace(c))
-#endif // VC++
+// time.h functions
+#ifdef wxNEED_WX_TIME_H
+    WXDLLEXPORT size_t wxStrftime(wxChar *s, size_t max,
+                                  const wxChar *fmt, const struct tm *tm);
+#endif // wxNEED_WX_TIME_H
 
 // ----------------------------------------------------------------------------
-// common macros which are always defined
+// multibyte to wide char conversion functions and macros
 // ----------------------------------------------------------------------------
 
-// although global macros with such names are really bad, we want to have
-// another name for _T() which should be used to avoid confusion between _T()
-// and _() in wxWindows sources
-#define wxT(x)       _T(x)
-
-// Unicode-friendly __FILE__, __DATE__ and __TIME__ analogs
-#ifndef __TFILE__
-    #define __XFILE__(x) wxT(x)
-    #define __TFILE__ __XFILE__(__FILE__)
-#endif
-
-#ifndef __TDATE__
-    #define __XDATE__(x) wxT(x)
-    #define __TDATE__ __XDATE__(__DATE__)
-#endif
-
-#ifndef __TTIME__
-    #define __XTIME__(x) wxT(x)
-    #define __TTIME__ __XTIME__(__TIME__)
+#if wxUSE_WCHAR_T
+    // multibyte<->widechar conversion
+    WXDLLEXPORT size_t wxMB2WC(wchar_t *buf, const char *psz, size_t n);
+    WXDLLEXPORT size_t wxWC2MB(char *buf, const wchar_t *psz, size_t n);
+
+    #if wxUSE_UNICODE
+        #define wxMB2WX wxMB2WC
+        #define wxWX2MB wxWC2MB
+        #define wxWC2WX wxStrncpy
+        #define wxWX2WC wxStrncpy
+    #else
+        #define wxMB2WX wxStrncpy
+        #define wxWX2MB wxStrncpy
+        #define wxWC2WX wxWC2MB
+        #define wxWX2WC wxMB2WC
+    #endif
+#else // !wxUSE_UNICODE
+    // No wxUSE_WCHAR_T: we have to do something (JACS)
+    #define wxMB2WC wxStrncpy
+    #define wxWC2MB wxStrncpy
+    #define wxMB2WX wxStrncpy
+    #define wxWX2MB wxStrncpy
+    #define wxWC2WX wxWC2MB
+    #define wxWX2WC wxMB2WC
 #endif
 
-#endif
-  //_WX_WXCHAR_H_
+#endif //_WX_WXCHAR_H_
 
index 77af363cb5f986680d60b0397c4cbf821e48c50c..e2563e5c824bc1bfc8e07aafc5443a0fbb827964 100644 (file)
   #include <clib.h>
 #endif
 
-#if wxUSE_UNICODE
-    #undef wxUSE_EXPERIMENTAL_PRINTF
-    #ifndef wvsnprintf
-        #define wxUSE_EXPERIMENTAL_PRINTF 1
-    #endif
-#endif
-
 // allocating extra space for each string consumes more memory but speeds up
 // the concatenation operations (nLen is the current string's length)
 // NB: EXTRA_ALLOC must be >= 0!
@@ -88,54 +81,6 @@ static const struct
 // empty C style string: points to 'string data' byte of g_strEmpty
 extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy;
 
-// ----------------------------------------------------------------------------
-// conditional compilation
-// ----------------------------------------------------------------------------
-
-#if !defined(__WXSW__) && wxUSE_UNICODE
-  #ifdef wxUSE_EXPERIMENTAL_PRINTF
-    #undef wxUSE_EXPERIMENTAL_PRINTF
-  #endif
-  #define wxUSE_EXPERIMENTAL_PRINTF 1
-#endif
-
-// we want to find out if the current platform supports vsnprintf()-like
-// function: for Unix this is done with configure, for Windows we test the
-// compiler explicitly.
-//
-// FIXME currently, this is only for ANSI (!Unicode) strings, so we call this
-//       function wxVsnprintfA (A for ANSI), should also find one for Unicode
-//       strings in Unicode build
-#ifdef __WXMSW__
-    #if defined(__VISUALC__) || (defined(__MINGW32__) && wxUSE_NORLANDER_HEADERS)
-        #define wxVsnprintfA     _vsnprintf
-    #endif
-#elif defined(__WXMAC__)
-    #define wxVsnprintfA       vsnprintf
-#else   // !Windows
-    #ifdef HAVE_VSNPRINTF
-        #define wxVsnprintfA       vsnprintf
-    #endif
-#endif  // Windows/!Windows
-
-#ifndef wxVsnprintfA
-    // in this case we'll use vsprintf() (which is ANSI and thus should be
-    // always available), but it's unsafe because it doesn't check for buffer
-    // size - so give a warning
-    #define wxVsnprintfA(buf, len, format, arg) vsprintf(buf, format, arg)
-
-    #if defined(__VISUALC__)
-        #pragma message("Using sprintf() because no snprintf()-like function defined")
-    #elif defined(__GNUG__)
-        #warning "Using sprintf() because no snprintf()-like function defined"
-    #endif //compiler
-#endif // no vsnprintf
-
-#if defined(_AIX)
-  // AIX has vsnprintf, but there's no prototype in the system headers.
-  extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap);
-#endif
-
 // ----------------------------------------------------------------------------
 // global functions
 // ----------------------------------------------------------------------------
@@ -196,15 +141,15 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
   class Averager
   {
   public:
-    Averager(const char *sz) { m_sz = sz; m_nTotal = m_nCount = 0; }
+    Averager(const wxChar *sz) { m_sz = sz; m_nTotal = m_nCount = 0; }
    ~Averager()
-   { printf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); }
+   { wxPrintf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); }
 
     void Add(size_t n) { m_nTotal += n; m_nCount++; }
 
   private:
     size_t m_nCount, m_nTotal;
-    const char *m_sz;
+    const wxChar *m_sz;
   } g_averageLength("allocation size"),
     g_averageSummandLength("summand length"),
     g_averageConcatHit("hit probability in concat"),
@@ -235,8 +180,9 @@ wxString::wxString(wxChar ch, size_t nLength)
     }
 
 #if wxUSE_UNICODE
-    // memset only works on char
-    for (size_t n=0; n<nLength; n++) m_pchData[n] = ch;
+    // memset only works on chars
+    for ( size_t n = 0; n < nLength; n++ )
+        m_pchData[n] = ch;
 #else
     memset(m_pchData, ch, nLength);
 #endif
@@ -1273,281 +1219,38 @@ int wxString::Printf(const wxChar *pszFormat, ...)
 
 int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
 {
-#if wxUSE_EXPERIMENTAL_PRINTF
-  // the new implementation
-
-  // buffer to avoid dynamic memory allocation each time for small strings
-  char szScratch[1024];
-
-  Reinit();
-  for (size_t n = 0; pszFormat[n]; n++)
-    if (pszFormat[n] == wxT('%')) {
-      static char s_szFlags[256] = "%";
-      size_t flagofs = 1;
-      bool adj_left = FALSE, in_prec = FALSE,
-           prec_dot = FALSE, done = FALSE;
-      int ilen = 0;
-      size_t min_width = 0, max_width = wxSTRING_MAXLEN;
-      do {
-#define CHECK_PREC if (in_prec && !prec_dot) { s_szFlags[flagofs++] = '.'; prec_dot = TRUE; }
-        switch (pszFormat[++n]) {
-        case wxT('\0'):
-          done = TRUE;
-          break;
-        case wxT('%'):
-          *this += wxT('%');
-          done = TRUE;
-          break;
-        case wxT('#'):
-        case wxT('0'):
-        case wxT(' '):
-        case wxT('+'):
-        case wxT('\''):
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('-'):
-          CHECK_PREC
-          adj_left = TRUE;
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('.'):
-          CHECK_PREC
-          in_prec = TRUE;
-          prec_dot = FALSE;
-          max_width = 0;
-          // dot will be auto-added to s_szFlags if non-negative number follows
-          break;
-        case wxT('h'):
-          ilen = -1;
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('l'):
-          ilen = 1;
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('q'):
-        case wxT('L'):
-          ilen = 2;
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('Z'):
-          ilen = 3;
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          break;
-        case wxT('*'):
-          {
-            int len = va_arg(argptr, int);
-            if (in_prec) {
-              if (len<0) break;
-              CHECK_PREC
-              max_width = len;
-            } else {
-              if (len<0) {
-                adj_left = !adj_left;
-                s_szFlags[flagofs++] = '-';
-                len = -len;
-              }
-              min_width = len;
-            }
-            flagofs += ::sprintf(s_szFlags+flagofs,"%d",len);
-          }
-          break;
-        case wxT('1'): case wxT('2'): case wxT('3'):
-        case wxT('4'): case wxT('5'): case wxT('6'):
-        case wxT('7'): case wxT('8'): case wxT('9'):
-          {
-            int len = 0;
-            CHECK_PREC
-            while ((pszFormat[n]>=wxT('0')) && (pszFormat[n]<=wxT('9'))) {
-              s_szFlags[flagofs++] = pszFormat[n];
-              len = len*10 + (pszFormat[n] - wxT('0'));
-              n++;
-            }
-            if (in_prec) max_width = len;
-            else min_width = len;
-            n--; // the main loop pre-increments n again
-          }
-          break;
-        case wxT('d'):
-        case wxT('i'):
-        case wxT('o'):
-        case wxT('u'):
-        case wxT('x'):
-        case wxT('X'):
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          s_szFlags[flagofs] = '\0';
-          if (ilen == 0 ) {
-            int val = va_arg(argptr, int);
-            ::sprintf(szScratch, s_szFlags, val);
-          }
-          else if (ilen == -1) {
-            short int val = va_arg(argptr, short int);
-            ::sprintf(szScratch, s_szFlags, val);
-          }
-          else if (ilen == 1) {
-            long int val = va_arg(argptr, long int);
-            ::sprintf(szScratch, s_szFlags, val);
-          }
-          else if (ilen == 2) {
-#if SIZEOF_LONG_LONG
-            long long int val = va_arg(argptr, long long int);
-            ::sprintf(szScratch, s_szFlags, val);
-#else
-            long int val = va_arg(argptr, long int);
-            ::sprintf(szScratch, s_szFlags, val);
-#endif
-          }
-          else if (ilen == 3) {
-            size_t val = va_arg(argptr, size_t);
-            ::sprintf(szScratch, s_szFlags, val);
-          }
-          *this += wxString(szScratch);
-          done = TRUE;
-          break;
-        case wxT('e'):
-        case wxT('E'):
-        case wxT('f'):
-        case wxT('g'):
-        case wxT('G'):
-          CHECK_PREC
-          s_szFlags[flagofs++] = pszFormat[n];
-          s_szFlags[flagofs] = '\0';
-          if (ilen == 2) {
-            long double val = va_arg(argptr, long double);
-            ::sprintf(szScratch, s_szFlags, val);
-          } else {
-            double val = va_arg(argptr, double);
-            ::sprintf(szScratch, s_szFlags, val);
-          }
-          *this += wxString(szScratch);
-          done = TRUE;
-          break;
-        case wxT('p'):
-          {
-            void *val = va_arg(argptr, void *);
-            CHECK_PREC
-            s_szFlags[flagofs++] = pszFormat[n];
-            s_szFlags[flagofs] = '\0';
-            ::sprintf(szScratch, s_szFlags, val);
-            *this += wxString(szScratch);
-            done = TRUE;
-          }
-          break;
-        case wxT('c'):
-          {
-            wxChar val = va_arg(argptr, int);
-            // we don't need to honor padding here, do we?
-            *this += val;
-            done = TRUE;
-          }
-          break;
-        case wxT('s'):
-          if (ilen == -1) {
-            // wx extension: we'll let %hs mean non-Unicode strings
-            char *val = va_arg(argptr, char *);
-#if wxUSE_UNICODE
-            // ASCII->Unicode constructor handles max_width right
-            wxString s(val, wxConvLibc, max_width);
-#else
-            size_t len = wxSTRING_MAXLEN;
-            if (val) {
-              for (len = 0; val[len] && (len<max_width); len++);
-            } else val = wxT("(null)");
-            wxString s(val, len);
-#endif
-            if (s.Len() < min_width)
-              s.Pad(min_width - s.Len(), wxT(' '), adj_left);
-            *this += s;
-          } else {
-            wxChar *val = va_arg(argptr, wxChar *);
-            size_t len = wxSTRING_MAXLEN;
-            if (val) {
-              for (len = 0; val[len] && (len<max_width); len++);
-            } else val = wxT("(null)");
-            wxString s(val, len);
-            if (s.Len() < min_width)
-              s.Pad(min_width - s.Len(), wxT(' '), adj_left);
-            *this += s;
-          }
-          done = TRUE;
-          break;
-        case wxT('n'):
-          if (ilen == 0) {
-            int *val = va_arg(argptr, int *);
-            *val = Len();
-          }
-          else if (ilen == -1) {
-            short int *val = va_arg(argptr, short int *);
-            *val = Len();
-          }
-          else if (ilen >= 1) {
-            long int *val = va_arg(argptr, long int *);
-            *val = Len();
-          }
-          done = TRUE;
-          break;
-        default:
-          if (wxIsalpha(pszFormat[n]))
-            // probably some flag not taken care of here yet
-            s_szFlags[flagofs++] = pszFormat[n];
-          else {
-            // bad format
-            *this += wxT('%'); // just to pass the glibc tst-printf.c
-            n--;
-            done = TRUE;
-          }
-          break;
+    int size = 1024;
+    for ( ;; )
+    {
+        wxChar *buf = GetWriteBuf(size + 1);
+        if ( !buf )
+        {
+            // out of memory
+            return -1;
         }
-#undef CHECK_PREC
-      } while (!done);
-    } else *this += pszFormat[n];
 
-#else
-  // buffer to avoid dynamic memory allocation each time for small strings
-  char szScratch[1024];
-
-  // NB: wxVsnprintf() may return either less than the buffer size or -1 if
-  //     there is not enough place depending on implementation
-  int iLen = wxVsnprintfA(szScratch, WXSIZEOF(szScratch), (char *)pszFormat, argptr);
-  if ( iLen != -1 ) {
-    // the whole string is in szScratch
-    *this = szScratch;
-  }
-  else {
-      bool outOfMemory = FALSE;
-      int size = 2*WXSIZEOF(szScratch);
-      while ( !outOfMemory ) {
-          char *buf = GetWriteBuf(size);
-          if ( buf )
-            iLen = wxVsnprintfA(buf, size, pszFormat, argptr);
-          else
-            outOfMemory = TRUE;
-
-          UngetWriteBuf();
-
-          if ( iLen != -1 ) {
-              // ok, there was enough space
-              break;
-          }
+        int len = wxVsnprintf(buf, size, pszFormat, argptr);
 
-          // still not enough, double it again
-          size *= 2;
-      }
+        // some implementations of vsnprintf() don't NUL terminate the string
+        // if there is not enough space for it so always do it manually
+        buf[size] = _T('\0');
 
-      if ( outOfMemory ) {
-          // out of memory
-          return -1;
-      }
-  }
-#endif // wxUSE_EXPERIMENTAL_PRINTF/!wxUSE_EXPERIMENTAL_PRINTF
+        UngetWriteBuf();
+
+        if ( len >= 0 )
+        {
+            // ok, there was enough space
+            break;
+        }
+
+        // still not enough, double it again
+        size *= 2;
+    }
+
+    // we could have overshot
+    Shrink();
 
-  return Len();
+    return Len();
 }
 
 // ----------------------------------------------------------------------------
index 2f030b8ed9152c38e54c50eff5761184cf01cf83..a161262499f3515c3dd57090fd3c4398651fffa0 100644 (file)
@@ -98,8 +98,8 @@ bool WXDLLEXPORT wxOKlibc()
     // this is UTF-8 allright, check whether that's what we want
     char *cur_locale = setlocale(LC_CTYPE, NULL);
     if ((strlen(cur_locale) < 4) ||
-       (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
-       (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
+            (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
+            (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
       // nope, don't use libc conversion
       return FALSE;
     }
@@ -117,301 +117,746 @@ size_t   WXDLLEXPORT wcslen(const wchar_t *s)
 }
 #endif
 
-#ifdef wxNEED_PRINTF_CONVERSION
+// ============================================================================
+// printf() functions business
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// implement [v]snprintf() if the system doesn't provide a safe one
+// ----------------------------------------------------------------------------
+
+#if !defined(wxVsnprintf_)
+int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
+                             const wxChar *format, va_list argptr)
+{
+    // buffer to avoid dynamic memory allocation each time for small strings
+    char szScratch[1024];
+
+    // number of characters in the buffer so far, must be less than lenMax
+    size_t lenCur = 0;
 
-#define CONVERT_FORMAT_1  \
-    wxChar *new_format = (wxChar*) format; \
-    size_t old_len = wxStrlen( format ); \
-    int n = 0; \
-    size_t i; \
-    for (i = 0; i < old_len; i++) \
-    { \
-        if ( (format[i] == L'%') && \
-             ((i < old_len) && ((format[i+1] == L's') || (format[i+1] == L'c'))) && \
-             ((i == 0) || (format[i-1] != L'%')) ) \
-        { \
-            n++; \
-        } \
-    } \
- \
-    if (n > 0) \
-    { \
-        new_format = new wxChar[old_len+n+1]; \
-        wxChar *s = new_format; \
- \
-        for (i = 0; i < old_len+1; i++) \
-        { \
-            if ( (format[i] == L'%') && \
-                 ((i < old_len) && ((format[i+1] == L's') || (format[i+1] == L'c'))) && \
-                 ((i == 0) || (format[i-1] != L'%')) ) \
-            { \
-                *s = L'%'; \
-                s++; \
-                *s = L'l'; \
-                s++; \
-            } \
-            else \
-            { \
-                *s = format[i]; \
-                s++; \
-            } \
-        } \
+    for (size_t n = 0; format[n]; n++)
+    {
+        if (format[n] == wxT('%')) {
+            static char s_szFlags[256] = "%";
+            size_t flagofs = 1;
+            bool adj_left = FALSE,
+                 in_prec = FALSE,
+                 prec_dot = FALSE,
+                 done = FALSE;
+            int ilen = 0;
+            size_t min_width = 0,
+                   max_width = wxSTRING_MAXLEN;
+            do {
+
+#define CHECK_PREC \
+                if (in_prec && !prec_dot) \
+                { \
+                    s_szFlags[flagofs++] = '.'; \
+                    prec_dot = TRUE; \
+                }
+
+#define APPEND_CH(ch) \
+                if ( lenCur == lenMax ) \
+                    return -1; \
+                \
+                buf[lenCur++] = ch
+
+#define APPEND_STR(s) \
+                for ( const char *p = s; *p; p++ ) \
+                { \
+                    APPEND_CH((wchar_t)(*p)); \
+                }
+
+#define APPEND_WSTR(s) \
+                for ( const wchar_t *p = s; *p; p++ ) \
+                { \
+                    APPEND_CH(*p); \
+                }
+
+                switch (format[++n]) {
+                    case wxT('\0'):
+                        APPEND_CH(_T('\0'));
+
+                        done = TRUE;
+                        break;
+
+                    case wxT('%'):
+                        APPEND_CH(_T('%'));
+                        done = TRUE;
+                        break;
+
+                    case wxT('#'):
+                    case wxT('0'):
+                    case wxT(' '):
+                    case wxT('+'):
+                    case wxT('\''):
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('-'):
+                        CHECK_PREC
+                        adj_left = TRUE;
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('.'):
+                        CHECK_PREC
+                            in_prec = TRUE;
+                        prec_dot = FALSE;
+                        max_width = 0;
+                        // dot will be auto-added to s_szFlags if non-negative number follows
+                        break;
+
+                    case wxT('h'):
+                        ilen = -1;
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('l'):
+                        ilen = 1;
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('q'):
+                    case wxT('L'):
+                        ilen = 2;
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('Z'):
+                        ilen = 3;
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        break;
+
+                    case wxT('*'):
+                        {
+                            int len = va_arg(argptr, int);
+                            if (in_prec) {
+                                if (len<0) break;
+                                CHECK_PREC
+                                    max_width = len;
+                            } else {
+                                if (len<0) {
+                                    adj_left = !adj_left;
+                                    s_szFlags[flagofs++] = '-';
+                                    len = -len;
+                                }
+                                min_width = len;
+                            }
+                            flagofs += ::sprintf(s_szFlags+flagofs,"%d",len);
+                        }
+                        break;
+
+                    case wxT('1'): case wxT('2'): case wxT('3'):
+                    case wxT('4'): case wxT('5'): case wxT('6'):
+                    case wxT('7'): case wxT('8'): case wxT('9'):
+                        {
+                            int len = 0;
+                            CHECK_PREC
+                                while ((format[n]>=wxT('0')) && (format[n]<=wxT('9'))) {
+                                    s_szFlags[flagofs++] = format[n];
+                                    len = len*10 + (format[n] - wxT('0'));
+                                    n++;
+                                }
+                            if (in_prec) max_width = len;
+                            else min_width = len;
+                            n--; // the main loop pre-increments n again
+                        }
+                        break;
+
+                    case wxT('d'):
+                    case wxT('i'):
+                    case wxT('o'):
+                    case wxT('u'):
+                    case wxT('x'):
+                    case wxT('X'):
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        s_szFlags[flagofs] = '\0';
+                        if (ilen == 0 ) {
+                            int val = va_arg(argptr, int);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        }
+                        else if (ilen == -1) {
+                            short int val = va_arg(argptr, short int);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        }
+                        else if (ilen == 1) {
+                            long int val = va_arg(argptr, long int);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        }
+                        else if (ilen == 2) {
+#if SIZEOF_LONG_LONG
+                            long long int val = va_arg(argptr, long long int);
+                            ::sprintf(szScratch, s_szFlags, val);
+#else
+                            long int val = va_arg(argptr, long int);
+                            ::sprintf(szScratch, s_szFlags, val);
+#endif
+                        }
+                        else if (ilen == 3) {
+                            size_t val = va_arg(argptr, size_t);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        }
+
+                        APPEND_STR(szScratch);
+
+                        done = TRUE;
+                        break;
+
+                    case wxT('e'):
+                    case wxT('E'):
+                    case wxT('f'):
+                    case wxT('g'):
+                    case wxT('G'):
+                        CHECK_PREC
+                        s_szFlags[flagofs++] = format[n];
+                        s_szFlags[flagofs] = '\0';
+                        if (ilen == 2) {
+                            long double val = va_arg(argptr, long double);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        } else {
+                            double val = va_arg(argptr, double);
+                            ::sprintf(szScratch, s_szFlags, val);
+                        }
+
+                        APPEND_STR(szScratch);
+
+                        done = TRUE;
+                        break;
+
+                    case wxT('p'):
+                        {
+                            void *val = va_arg(argptr, void *);
+                            CHECK_PREC
+                                s_szFlags[flagofs++] = format[n];
+                            s_szFlags[flagofs] = '\0';
+                            ::sprintf(szScratch, s_szFlags, val);
+
+                            APPEND_STR(szScratch);
+
+                            done = TRUE;
+                        }
+                        break;
+
+                    case wxT('c'):
+                        {
+                            wxChar val = va_arg(argptr, int);
+                            // we don't need to honor padding here, do we?
+                            APPEND_CH(val);
+
+                            done = TRUE;
+                        }
+                        break;
+
+                    case wxT('s'):
+                        if (ilen == -1) {
+                            // wx extension: we'll let %hs mean non-Unicode strings
+                            char *val = va_arg(argptr, char *);
+#if wxUSE_UNICODE
+                            // ASCII->Unicode constructor handles max_width right
+                            wxString s(val, wxConvLibc, max_width);
+#else
+                            size_t len = wxSTRING_MAXLEN;
+                            if (val) {
+                                for (len = 0; val[len] && (len<max_width); len++);
+                            } else val = wxT("(null)");
+                            wxString s(val, len);
+#endif
+                            if (s.Len() < min_width)
+                                s.Pad(min_width - s.Len(), wxT(' '), adj_left);
+
+                            APPEND_WSTR(s);
+                        } else {
+                            wxChar *val = va_arg(argptr, wxChar *);
+                            size_t len = wxSTRING_MAXLEN;
+                            if (val) {
+                                for (len = 0; val[len] && (len<max_width); len++);
+                            } else val = wxT("(null)");
+                            wxString s(val, len);
+                            if (s.Len() < min_width)
+                                s.Pad(min_width - s.Len(), wxT(' '), adj_left);
+
+                            APPEND_WSTR(s);
+                        }
+                        done = TRUE;
+                        break;
+
+                    case wxT('n'):
+                        if (ilen == 0) {
+                            int *val = va_arg(argptr, int *);
+                            *val = lenCur;
+                        }
+                        else if (ilen == -1) {
+                            short int *val = va_arg(argptr, short int *);
+                            *val = lenCur;
+                        }
+                        else if (ilen >= 1) {
+                            long int *val = va_arg(argptr, long int *);
+                            *val = lenCur;
+                        }
+                        done = TRUE;
+                        break;
+
+                    default:
+                        if (wxIsalpha(format[n]))
+                            // probably some flag not taken care of here yet
+                            s_szFlags[flagofs++] = format[n];
+                        else {
+                            // bad format
+                            APPEND_CH(_T('%')); // just to pass the glibc tst-printf.c
+                            n--;
+                            done = TRUE;
+                        }
+                        break;
+                }
+            } while (!done);
+        }
+        else
+        {
+            APPEND_CH(format[n]);
+        }
     }
 
-#define CONVERT_FORMAT_2 \
-    if (n > 0) \
-        delete [] new_format;
-    
+    return lenCur;
+}
 
-int wxScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
-{
-    CONVERT_FORMAT_1
+#undef APPEND_CH
+#undef APPEND_STR
+#undef CHECK_PREC
 
+#endif // !wxVsnprintfA
+
+#if !defined(wxSnprintf_)
+int WXDLLEXPORT wxSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...)
+{
     va_list argptr;
     va_start(argptr, format);
 
-    int ret = vwscanf( new_format, argptr );
-
-    CONVERT_FORMAT_2
+    int iLen = wxVsnprintf_(buf, len, format, argptr);
 
     va_end(argptr);
-    
-    return ret;
+
+    return iLen;
 }
+#endif // wxSnprintf_
 
-int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
-{
-    CONVERT_FORMAT_1
+// ----------------------------------------------------------------------------
+// implement the standard IO functions for wide char if libc doesn't have them
+// ----------------------------------------------------------------------------
 
-    va_list argptr;
-    va_start(argptr, format);
+#ifndef HAVE_FPUTWC
 
-    int ret = vswscanf( str, new_format, argptr );
+int wxFputs(const wchar_t *ws, FILE *stream)
+{
+    // counting the number of wide characters written isn't worth the trouble,
+    // simply distinguish between ok and error
+    return fputs(wxConvLibc.cWC2MB(ws), stream) == -1 ? -1 : 0;
+}
 
-    CONVERT_FORMAT_2
+int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
+{
+    wchar_t ws[2] = { wc, L'\0' };
 
-    va_end(argptr);
-    
-    return ret;
+    return wxFputs(ws, stream);
 }
 
-int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
+#endif // HAVE_FPUTWC
+
+// NB: we only implement va_list functions here, the ones taking ... are
+//     defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
+//     the definitions there to avoid duplicating them here
+#ifdef wxNEED_WPRINTF
+
+// TODO: implement the scanf() functions
+int vwscanf(const wchar_t *format, va_list argptr)
 {
-    CONVERT_FORMAT_1
+    wxFAIL_MSG( _T("TODO") );
 
-    va_list argptr;
-    va_start(argptr, format);
+    return -1;
+}
+
+int vswscanf(const wchar_t *ws, const wchar_t *format, va_list argptr)
+{
+    wxFAIL_MSG( _T("TODO") );
 
-    int ret = vfwscanf(stream, new_format, argptr);
+    return -1;
+}
 
-    CONVERT_FORMAT_2
+int vfwscanf(FILE *stream, const wchar_t *format, va_list argptr)
+{
+    wxFAIL_MSG( _T("TODO") );
 
-    va_end(argptr);
-    
-    return ret;
+    return -1;
 }
 
-int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap )
+#define vswprintf wxVsnprintf_
+
+int vfwprintf(FILE *stream, const wchar_t *format, va_list argptr)
 {
-    CONVERT_FORMAT_1
+    wxString s;
+    int rc = s.PrintfV(format, argptr);
 
-    int ret = vswscanf( str, new_format, ap );
-    
-    CONVERT_FORMAT_2
+    if ( rc != -1 )
+    {
+        // we can't do much better without Unicode support in libc...
+        if ( fprintf(stream, s.mb_str()) == -1 )
+            return -1;
+    }
 
-    return ret;
+    return rc;
 }
 
-int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
+int vwprintf(const wchar_t *format, va_list argptr)
 {
-    CONVERT_FORMAT_1
+    return wxVfprintf(stdout, format, argptr);
+}
 
-    va_list argptr;
-    va_start(argptr, format);
-    
-    int ret = vwprintf( new_format, argptr );
-    
-    CONVERT_FORMAT_2
+#endif // wxNEED_WPRINTF
 
-    va_end(argptr);
+#ifdef wxNEED_PRINTF_CONVERSION
 
-    return ret;
-}
+// ----------------------------------------------------------------------------
+// wxFormatConverter: class doing the "%s" -> "%ls" conversion
+// ----------------------------------------------------------------------------
 
-int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_4
+/*
+   Here are the gory details. We want to follow the Windows/MS conventions,
+   that is to have
+
+   In ANSI mode:
+
+   format specifier         results in
+   -----------------------------------
+   %c, %hc, %hC             char
+   %lc, %C, %lC             wchar_t
+
+   In Unicode mode:
+
+   format specifier         results in
+   -----------------------------------
+   %hc, %C, %hC             char
+   %c, %lc, %lC             wchar_t
+
+
+   while on POSIX systems we have %C identical to %lc and %c always means char
+   (in any mode) while %lc always means wchar_t,
+
+   So to use native functions in order to get our semantics we must do the
+   following translations in Unicode mode (nothing to do in ANSI mode):
+
+   wxWindows specifier      POSIX specifier
+   ----------------------------------------
+
+   %hc, %C, %hC             %c
+   %c                       %lc
+
+
+   And, of course, the same should be done for %s as well.
+*/
+
+class wxFormatConverter
 {
-    CONVERT_FORMAT_1
+public:
+    wxFormatConverter(const wxChar *format);
+
+    operator const wxChar *() const { return m_fmt.c_str(); }
+
+private:
+    // copy another character to the translated format: this function does the
+    // copy if we are translating but doesn't do anything at all if we don't,
+    // so we don't create the translated format string at all unless we really
+    // need to (i.e. InsertFmtChar() is called)
+    wxChar CopyFmtChar(wxChar ch)
+    {
+        if ( !m_fmtOrig )
+        {
+            // we're translating, d copy
+            m_fmt += ch;
+        }
+        else
+        {
+            // simply increase the count which should be copied by
+            // CopyAllBefore() later if needed
+            m_nCopied++;
+        }
+
+        return ch;
+    }
+
+    // insert an extra character
+    void InsertFmtChar(wxChar ch)
+    {
+        if ( m_fmtOrig )
+        {
+            // so far we haven't translated anything yet
+            CopyAllBefore();
+        }
+
+        m_fmt += ch;
+    }
+
+    void CopyAllBefore()
+    {
+        wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
+
+        m_fmt = wxString(m_fmtOrig, m_nCopied);
+
+        // we won't need it any longer
+        m_fmtOrig = NULL;
+    }
 
+    static bool IsFlagChar(wxChar ch)
+    {
+        return ch == _T('-') || ch == _T('+') ||
+               ch == _T('0') || ch == _T(' ') || ch == _T('#');
+    }
+
+    void SkipDigits(const wxChar **ppc)
+    {
+        while ( **ppc >= _T('0') && **ppc <= _T('9') )
+            CopyFmtChar(*(*ppc)++);
+    }
+
+    // the translated format
+    wxString m_fmt;
+
+    // the original format
+    const wxChar *m_fmtOrig;
+
+    // the number of characters already copied
+    size_t m_nCopied;
+};
+
+wxFormatConverter::wxFormatConverter(const wxChar *format)
+{
+    m_fmtOrig = format;
+    m_nCopied = 0;
+
+    while ( *format )
+    {
+        if ( CopyFmtChar(*format++) == _T('%') )
+        {
+            // skip any flags
+            while ( IsFlagChar(*format) )
+                CopyFmtChar(*format++);
+
+            // and possible width
+            if ( *format == _T('*') )
+                CopyFmtChar(*format++);
+            else
+                SkipDigits(&format);
+
+            // precision?
+            if ( *format == _T('.') )
+            {
+                SkipDigits(&format);
+            }
+
+            // next we can have a size modifier
+            enum
+            {
+                Default,
+                Short,
+                Long
+            } size;
+
+            switch ( *format )
+            {
+                case _T('h'):
+                    size = Short;
+                    format++;
+                    break;
+
+                case _T('l'):
+                    // "ll" has a different meaning!
+                    if ( format[1] != _T('l') )
+                    {
+                        size = Long;
+                        format++;
+                        break;
+                    }
+                    //else: fall through
+
+                default:
+                    size = Default;
+            }
+
+            // and finally we should have the type
+            switch ( *format )
+            {
+                case _T('C'):
+                case _T('S'):
+                    // %C and %hC -> %c and %lC -> %lc
+                    if ( size == Long )
+                        CopyFmtChar(_T('l'));
+
+                    InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
+                    break;
+
+                case _T('c'):
+                case _T('s'):
+                    // %c -> %lc but %hc stays %hc and %lc is still %lc
+                    switch ( size )
+                    {
+                        case Default:
+                            InsertFmtChar(_T('l'));
+                            break;
+
+                        case Short:
+                            CopyFmtChar(_T('h'));
+                            break;
+
+                        case Long:
+                            ;
+                    }
+                    // fall through
+
+                default:
+                    // nothing special to do
+                    CopyFmtChar(*format++);
+            }
+        }
+    }
+}
+
+#else // !wxNEED_PRINTF_CONVERSION
+    // no conversion necessary
+    #define wxFormatConverter(x) (x)
+#endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION
+
+// ----------------------------------------------------------------------------
+// wxPrintf(), wxScanf() and relatives
+// ----------------------------------------------------------------------------
+
+#if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
+
+int wxScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
+{
     va_list argptr;
     va_start(argptr, format);
 
-    int ret = vswprintf( str, size, new_format, argptr );
-
-    CONVERT_FORMAT_2
+    int ret = vwscanf(wxFormatConverter(format), argptr );
 
     va_end(argptr);
 
     return ret;
 }
 
-int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
+int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
 {
-    CONVERT_FORMAT_1
-
     va_list argptr;
     va_start(argptr, format);
 
-    // Ugly
-    int ret = vswprintf( str, 10000, new_format, argptr );
-
-    CONVERT_FORMAT_2
+    int ret = vswscanf( str, wxFormatConverter(format), argptr );
 
     va_end(argptr);
 
     return ret;
 }
 
-int wxFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
+int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
 {
-    CONVERT_FORMAT_1
-
     va_list argptr;
-    va_start( argptr, format );
-
-    int ret = vfwprintf( stream, new_format, argptr );
+    va_start(argptr, format);
 
-    CONVERT_FORMAT_2
+    int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
 
     va_end(argptr);
 
     return ret;
 }
 
-int wxVfprint( FILE *stream, const wxChar *format, va_list ap )
+int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
 {
-    CONVERT_FORMAT_1
+    va_list argptr;
+    va_start(argptr, format);
 
-    int ret = vfwprintf( stream, new_format, ap );
+    int ret = vwprintf( wxFormatConverter(format), argptr );
 
-    CONVERT_FORMAT_2
+    va_end(argptr);
 
     return ret;
 }
 
-int wxVprintf( const wxChar *format, va_list ap )
+#ifndef wxSnprintf
+int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_4
 {
-    CONVERT_FORMAT_1
+    va_list argptr;
+    va_start(argptr, format);
 
-    int ret = vwprintf( new_format, ap );
+    int ret = vswprintf( str, size, wxFormatConverter(format), argptr );
 
-    CONVERT_FORMAT_2
+    va_end(argptr);
 
     return ret;
 }
+#endif // wxSnprintf
 
-int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap )
+int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
 {
-    CONVERT_FORMAT_1
+    va_list argptr;
+    va_start(argptr, format);
 
-    int ret = vswprintf( str, size, new_format, ap );
+    // callers of wxSprintf() deserve what they get
+    int ret = vswprintf( str, UINT_MAX, wxFormatConverter(format), argptr );
 
-    CONVERT_FORMAT_2
+    va_end(argptr);
 
     return ret;
 }
 
-int wxVsprintf( wxChar *str, const wxChar *format, va_list ap )
+int wxFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
 {
-    CONVERT_FORMAT_1
+    va_list argptr;
+    va_start( argptr, format );
 
-    // This is so ugly
-    int ret = vswprintf(str, 10000, new_format, ap);
+    int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
 
-    CONVERT_FORMAT_2
+    va_end(argptr);
 
     return ret;
 }
-#endif
-
-// we want to find out if the current platform supports vsnprintf()-like
-// function: for Unix this is done with configure, for Windows we test the
-// compiler explicitly.
-//
-// FIXME currently, this is only for ANSI (!Unicode) strings, so we call this
-//       function wxVsnprintfA (A for ANSI), should also find one for Unicode
-//       strings in Unicode build
-#ifdef __WXMSW__
-    #if defined(__VISUALC__) || (defined(__MINGW32__) && wxUSE_NORLANDER_HEADERS)
-        #define wxVsnprintfA     _vsnprintf
-    #endif
-#elif defined(__WXMAC__)
-    #define wxVsnprintfA       vsnprintf
-#else   // !Windows
-    #ifdef HAVE_VSNPRINTF
-        #define wxVsnprintfA       vsnprintf
-    #endif
-#endif  // Windows/!Windows
-
-#ifndef wxVsnprintfA
-    // in this case we'll use vsprintf() (which is ANSI and thus should be
-    // always available), but it's unsafe because it doesn't check for buffer
-    // size - so give a warning
-    #define wxVsnprintfA(buf, len, format, arg) vsprintf(buf, format, arg)
-
-    #if defined(__VISUALC__)
-        #pragma message("Using sprintf() because no snprintf()-like function defined")
-    #elif defined(__GNUG__)
-        #warning "Using sprintf() because no snprintf()-like function defined"
-    #endif //compiler
-#endif // no vsnprintf
-
-#if defined(_AIX)
-  // AIX has vsnprintf, but there's no prototype in the system headers.
-  extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap);
-#endif
 
-#if !defined(wxVsnprintf) && !defined(wxHAS_VSNPRINTF)
-int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len,
-                            const wxChar *format, va_list argptr)
+int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr )
 {
-#if wxUSE_UNICODE
-    wxString s;
-    int iLen = s.PrintfV(format, argptr);
-    if ( iLen != -1 )
-    {
-        wxStrncpy(buf, s.c_str(), len);
-        buf[len-1] = wxT('\0');
-    }
+    return vswscanf( str, wxFormatConverter(format), argptr );
+}
 
-    return iLen;
-#else // ANSI
-    // vsnprintf() will not terminate the string with '\0' if there is not
-    // enough place, but we want the string to always be NUL terminated
-    int rc = wxVsnprintfA(buf, len - 1, format, argptr);
-    if ( rc == -1 )
-    {
-        buf[len] = 0;
-    }
+int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr )
+{
+    return vfwprintf( stream, wxFormatConverter(format), argptr );
+}
 
-    return rc;
-#endif // Unicode/ANSI
+int wxVprintf( const wxChar *format, va_list argptr )
+{
+    return vwprintf( wxFormatConverter(format), argptr );
 }
-#endif
 
-#if !defined(wxSnprintf) && !defined(wxHAS_SNPRINTF)
-int WXDLLEXPORT wxSnprintf(wxChar *buf, size_t len,
-                           const wxChar *format, ...)
+#ifndef wxVsnprintf
+int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
 {
-    va_list argptr;
-    va_start(argptr, format);
+    return vswprintf( str, size, wxFormatConverter(format), argptr );
+}
+#endif // wxVsnprintf
 
-    int iLen = wxVsnprintf(buf, len, format, argptr);
+int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr )
+{
+    // same as for wxSprintf()
+    return vswprintf(str, UINT_MAX, wxFormatConverter(format), argptr);
+}
 
-    va_end(argptr);
+#endif // wxNEED_PRINTF_CONVERSION
 
-    return iLen;
-}
-#endif
+// ----------------------------------------------------------------------------
+// ctype.h stuff (currently unused)
+// ----------------------------------------------------------------------------
 
 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
 inline WORD wxMSW_ctype(wxChar ch)
@@ -500,6 +945,10 @@ WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
 }
 #endif
 
+// ----------------------------------------------------------------------------
+// string.h functions
+// ----------------------------------------------------------------------------
+
 #ifdef wxNEED_WX_STRING_H
 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
 {
@@ -665,7 +1114,7 @@ WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
 
   return ret;
 }
-#endif
+#endif // wxNEED_WX_STRING_H
 
 #ifdef wxNEED_WX_STDIO_H
 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
@@ -673,7 +1122,7 @@ WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
     char mode_buffer[10];
     for (size_t i = 0; i < wxStrlen(mode)+1; i++)
        mode_buffer[i] = (char) mode[i];
-    
+
     return fopen( wxConvFile.cWX2MB(path), mode_buffer );
 }
 
@@ -682,7 +1131,7 @@ WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *strea
     char mode_buffer[10];
     for (size_t i = 0; i < wxStrlen(mode)+1; i++)
        mode_buffer[i] = (char) mode[i];
-    
+
     return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
 }
 
@@ -718,7 +1167,7 @@ long     WXDLLEXPORT wxAtol(const wxChar *psz)
 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
 {
   static wxHashTable env;
-  
+
   // check if we already have stored the converted env var
   wxObject *data = env.Get(name);
   if (!data)
@@ -734,7 +1183,7 @@ wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
 
     if (!val) return (wxChar *)NULL;
     // printf( "home %s\n", val );
-    
+
     // convert it,
 #ifdef wxUSE_UNICODE
     data = (wxObject *)new wxString(val, wxConvLocal);
@@ -760,7 +1209,7 @@ int WXDLLEXPORT wxSystem(const wxChar *psz)
 WXDLLEXPORT size_t   wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const struct tm *tm)
 {
     if (!max) return 0;
-    
+
     char *buf = (char *)malloc(max);
     size_t ret = strftime(buf, max, wxConvLocal.cWX2MB(fmt), tm);
     if (ret)
@@ -768,7 +1217,7 @@ WXDLLEXPORT size_t   wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const
         wxStrcpy(s, wxConvLocal.cMB2WX(buf));
         free(buf);
         return wxStrlen(s);
-    } 
+    }
     else
     {
         free(buf);