From f6f5941be5f080ca42cb5fed4b672f5db16c0d8e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 25 Aug 2002 17:13:44 +0000 Subject: [PATCH] reorganized, improved and hopefully simplified wxchar.h and printf() functions handling; also added wxWcslen() to fix wcslen() problems git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16767 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/wxchar.h | 1426 +++++++++++++++++++++-------------------- src/common/string.cpp | 357 +---------- src/common/wxchar.cpp | 871 +++++++++++++++++++------ 3 files changed, 1420 insertions(+), 1234 deletions(-) diff --git a/include/wx/wxchar.h b/include/wx/wxchar.h index ee7f0b225f..89bf08deea 100644 --- a/include/wx/wxchar.h +++ b/include/wx/wxchar.h @@ -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 ///////////////////////////////////////////////////////////////////////////// @@ -16,735 +16,199 @@ #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 -// ---------------------------------------------------------------------------- -// define wxHAVE_TCHAR_FUNCTIONS for the compilers which support the -// wide-character functions -// ---------------------------------------------------------------------------- - -// VC++ and BC++ starting with 5.2 have TCHAR support -#ifdef __VISUALC__ - #define wxHAVE_TCHAR_FUNCTIONS -#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x520) - #define wxHAVE_TCHAR_FUNCTIONS -#elif defined(__MINGW32__) && wxCHECK_W32API_VERSION( 1, 0 ) - #define wxHAVE_TCHAR_FUNCTIONS - #include - #include - #include -#elif defined(__CYGWIN__) +#if defined(__CYGWIN__) #ifndef HAVE_WCSLEN #define HAVE_WCSLEN #endif // !HAVE_WCSLEN #include - #include -#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 - - // 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 - #endif -#endif // compilers with (good) TCHAR support - -#ifdef wxHAVE_TCHAR_FUNCTIONS -# define HAVE_WCSLEN 1 - -# include - -# if wxUSE_UNICODE // temporary - preserve binary compatibility -#if defined(__GNUWIN32__) - #define _TCHAR TCHAR - #define _TSCHAR TCHAR - #define _TUCHAR TCHAR #endif -typedef _TCHAR wxChar; -typedef _TSCHAR wxSChar; -typedef _TUCHAR wxUChar; -# else -# define wxChar char -# define wxSChar signed char -# define wxUChar unsigned char -# 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 - // wchar_t is available +#if wxUSE_WCHAR_T + #ifdef HAVE_WCHAR_H + // include wchar.h to get wcslen() declaration used by wx/buffer.h + #include + #elif defined(HAVE_WCSTR_H) + // old compilers have wcslen() here + #include + #elif defined(__FreeBSD__) || defined(__DARWIN__) || defined(__EMX__) + // include stdlib.h for wchar_t, wcslen is provided in wxchar.cpp + #include + size_t WXDLLEXPORT wcslen(const wchar_t *s); + #endif // HAVE_WCHAR_H +#endif // wxUSE_WCHAR_T + +// ---------------------------------------------------------------------------- +// 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_SUPPORT +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x520) + #define wxHAVE_TCHAR_SUPPORT + #include +#elif defined(__MINGW32__) && wxCHECK_W32API_VERSION( 1, 0 ) + #define wxHAVE_TCHAR_SUPPORT + #include + #include + #include +#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 + + // we surely do have wchar_t if we have TCHAR #ifndef wxUSE_WCHAR_T #define wxUSE_WCHAR_T 1 #endif // !defined(wxUSE_WCHAR_T) - // ctype.h functions -#ifndef wxNO_TCHAR_CTYPE -#ifdef __BORLANDC__ -# include -#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 - -// 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 -# include -# elif defined(HAVE_WCSTR_H) - // old compilers have wcslen() here -# include -# elif defined(__FreeBSD__) || defined(__DARWIN__) || defined(__EMX__) - // include stdlib.h for wchar_t, wcslen is provided in wxchar.cpp -# include - 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 - -// 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; + // and we also do have wcslen() + #ifndef HAVE_WCSLEN + #define HAVE_WCSLEN #endif - typedef signed __WCHAR_TYPE__ wxSChar; - typedef unsigned __WCHAR_TYPE__ wxUChar; -#endif +#endif // wxHAVE_TCHAR_SUPPORT -# define _T(x) L##x +// ---------------------------------------------------------------------------- +// define wxChar 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 +// TODO: define wxCharInt to be equal to either int or wint_t? -# 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 -# include - - 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 - - // locale.h functons -# define wxSetlocale setlocale - - // string.h functions - // #define wxStricmp strcasecmp - // wxStricmp is defined below!! - - #ifdef HAVE_STRTOK_R - #define wxStrtok(str, sep, last) strtok_r(str, sep, last) - #else - #define wxStrtok(str, sep, last) strtok(str, sep) - #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 - -# endif//Unicode -#endif//TCHAR-aware compilers - -// 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 - -// 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 + 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 -# 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 - -// 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 - -#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 - -WXDLLEXPORT bool wxOKlibc(); // for internal use - -// We need conversion from %s to %ls in Unicode mode under Unix -#ifdef wxNEED_PRINTF_CONVERSION - -#include // need 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 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 ); - -#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 - -#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 - -// 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); -#endif - -#ifndef wxStrnicmp -WXDLLEXPORT int wxStrnicmp(const wxChar *psz1, const wxChar *psz2, size_t len); -#endif - -#ifndef wxStrtok -WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr); -#endif - -#ifndef wxSetlocale -class 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 - -#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 - -#ifdef wxNEED_WX_STDIO_H -# include -# include -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 - -#ifndef wxAtof -WXDLLEXPORT double wxAtof(const wxChar *psz); -#endif - -#ifdef wxNEED_WX_STDLIB_H -WXDLLEXPORT int wxAtoi(const wxChar *psz); -WXDLLEXPORT long wxAtol(const wxChar *psz); -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++ + // 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 // ---------------------------------------------------------------------------- -// common macros which are always defined +// define _T() and related macros // ---------------------------------------------------------------------------- -// although global macros with such names are really bad, we want to have +// BSD systems define _T() to be something different, override it +#if defined(__FreeBSD__) || defined(__DARWIN__) + #undef _T +#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) + +// 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) @@ -765,6 +229,576 @@ WXDLLEXPORT size_t wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const #define __TTIME__ __XTIME__(__TIME__) #endif -#endif - //_WX_WXCHAR_H_ +// ---------------------------------------------------------------------------- +// 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 _tsetlocale + + // string.h functions + #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 wxRemove _tremove + #define wxRename _trename + #endif + + // 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 + + // time.h functions + #define wxAsctime _tasctime + #define wxCtime _tctime +#else // !TCHAR-aware compilers + #if wxUSE_UNICODE + #include + + // 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 + + 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 + #include + + // 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 + +// ---------------------------------------------------------------------------- +// various special cases +// ---------------------------------------------------------------------------- + +// 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; } + +// safe version of strlen() (returns 0 if passed NULL pointer) +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 + #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 + +// ---------------------------------------------------------------------------- +// printf() family saga +// ---------------------------------------------------------------------------- + +/* + 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 + +/* + 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 // 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 + +// ---------------------------------------------------------------------------- +// various functions which might not be available in libc and for which we +// provide our own replacements in wxchar.cpp +// ---------------------------------------------------------------------------- + +// 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 + +#ifndef wxStrdup +WXDLLEXPORT wxChar * wxStrdup(const wxChar *psz); +#endif + +#ifndef wxStricmp +WXDLLEXPORT int wxStricmp(const wxChar *psz1, const wxChar *psz2); +#endif + +#ifndef wxStrnicmp +WXDLLEXPORT int wxStrnicmp(const wxChar *psz1, const wxChar *psz2, size_t len); +#endif + +#ifndef wxStrtok +WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr); +#endif + +#ifndef wxSetlocale +class WXDLLEXPORT wxWCharBuffer; +WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale); +#endif + +// stdio.h functions +#ifdef wxNEED_WX_STDIO_H + #include + 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); + + // *printf() family is handled separately +#endif // wxNEED_WX_STDIO_H + + +// stdlib.h functions +#ifndef wxAtof +WXDLLEXPORT double wxAtof(const wxChar *psz); +#endif + +#ifdef wxNEED_WX_STDLIB_H +WXDLLEXPORT int wxAtoi(const wxChar *psz); +WXDLLEXPORT long wxAtol(const wxChar *psz); +WXDLLEXPORT wxChar * wxGetenv(const wxChar *name); +WXDLLEXPORT int wxSystem(const wxChar *psz); +#endif + + +// 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 + +// ---------------------------------------------------------------------------- +// multibyte to wide char conversion functions and macros +// ---------------------------------------------------------------------------- + +#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_ diff --git a/src/common/string.cpp b/src/common/string.cpp index 77af363cb5..e2563e5c82 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -46,13 +46,6 @@ #include #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=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= 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]; + int len = wxVsnprintf(buf, size, pszFormat, argptr); - // 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; + // 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'); - UngetWriteBuf(); + UngetWriteBuf(); - if ( iLen != -1 ) { - // ok, there was enough space - break; - } + if ( len >= 0 ) + { + // ok, there was enough space + break; + } - // still not enough, double it again - size *= 2; - } + // still not enough, double it again + size *= 2; + } - if ( outOfMemory ) { - // out of memory - return -1; - } - } -#endif // wxUSE_EXPERIMENTAL_PRINTF/!wxUSE_EXPERIMENTAL_PRINTF + // we could have overshot + Shrink(); - return Len(); + return Len(); } // ---------------------------------------------------------------------------- diff --git a/src/common/wxchar.cpp b/src/common/wxchar.cpp index 2f030b8ed9..a161262499 100644 --- a/src/common/wxchar.cpp +++ b/src/common/wxchar.cpp @@ -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,154 +117,695 @@ size_t WXDLLEXPORT wcslen(const wchar_t *s) } #endif -#ifdef wxNEED_PRINTF_CONVERSION +// ============================================================================ +// printf() functions business +// ============================================================================ -#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++; \ - } \ - } \ +// ---------------------------------------------------------------------------- +// 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; + + 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= 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 +#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, ...) { - CONVERT_FORMAT_1 - 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 iLen; +} +#endif // wxSnprintf_ + +// ---------------------------------------------------------------------------- +// implement the standard IO functions for wide char if libc doesn't have them +// ---------------------------------------------------------------------------- + +#ifndef HAVE_FPUTWC + +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; +} + +int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream) +{ + wchar_t ws[2] = { wc, L'\0' }; + + return wxFputs(ws, stream); +} + +#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) +{ + wxFAIL_MSG( _T("TODO") ); + + return -1; +} + +int vswscanf(const wchar_t *ws, const wchar_t *format, va_list argptr) +{ + wxFAIL_MSG( _T("TODO") ); + + return -1; +} + +int vfwscanf(FILE *stream, const wchar_t *format, va_list argptr) +{ + wxFAIL_MSG( _T("TODO") ); + + return -1; +} + +#define vswprintf wxVsnprintf_ + +int vfwprintf(FILE *stream, const wchar_t *format, va_list argptr) +{ + wxString s; + int rc = s.PrintfV(format, argptr); + + if ( rc != -1 ) + { + // we can't do much better without Unicode support in libc... + if ( fprintf(stream, s.mb_str()) == -1 ) + return -1; + } + + return rc; +} + +int vwprintf(const wchar_t *format, va_list argptr) +{ + return wxVfprintf(stdout, format, argptr); +} + +#endif // wxNEED_WPRINTF + +#ifdef wxNEED_PRINTF_CONVERSION + +// ---------------------------------------------------------------------------- +// wxFormatConverter: class doing the "%s" -> "%ls" conversion +// ---------------------------------------------------------------------------- + +/* + 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 +{ +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 = vwscanf(wxFormatConverter(format), argptr ); + + va_end(argptr); + return ret; } int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3 { - CONVERT_FORMAT_1 - va_list argptr; va_start(argptr, format); - int ret = vswscanf( str, new_format, argptr ); - - CONVERT_FORMAT_2 + int ret = vswscanf( str, wxFormatConverter(format), argptr ); va_end(argptr); - + return ret; } int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3 { - CONVERT_FORMAT_1 - va_list argptr; va_start(argptr, format); - int ret = vfwscanf(stream, new_format, argptr); - - CONVERT_FORMAT_2 + int ret = vfwscanf(stream, wxFormatConverter(format), argptr); va_end(argptr); - - return ret; -} - -int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap ) -{ - CONVERT_FORMAT_1 - - int ret = vswscanf( str, new_format, ap ); - - CONVERT_FORMAT_2 return ret; } int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2 { - CONVERT_FORMAT_1 - va_list argptr; va_start(argptr, format); - - int ret = vwprintf( new_format, argptr ); - - CONVERT_FORMAT_2 + + int ret = vwprintf( wxFormatConverter(format), argptr ); va_end(argptr); return ret; } +#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 = vswprintf( str, size, new_format, argptr ); - - CONVERT_FORMAT_2 + int ret = vswprintf( str, size, wxFormatConverter(format), argptr ); va_end(argptr); return ret; } +#endif // wxSnprintf int wxSprintf( 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 + // callers of wxSprintf() deserve what they get + int ret = vswprintf( str, UINT_MAX, wxFormatConverter(format), argptr ); va_end(argptr); @@ -273,145 +814,49 @@ int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3 int wxFprintf( 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 ); - - CONVERT_FORMAT_2 + int ret = vfwprintf( stream, wxFormatConverter(format), argptr ); va_end(argptr); return ret; } -int wxVfprint( FILE *stream, const wxChar *format, va_list ap ) +int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr ) { - CONVERT_FORMAT_1 - - int ret = vfwprintf( stream, new_format, ap ); - - CONVERT_FORMAT_2 - - return ret; + return vswscanf( str, wxFormatConverter(format), argptr ); } -int wxVprintf( const wxChar *format, va_list ap ) +int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr ) { - CONVERT_FORMAT_1 - - int ret = vwprintf( new_format, ap ); - - CONVERT_FORMAT_2 - - return ret; + return vfwprintf( stream, wxFormatConverter(format), argptr ); } -int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap ) +int wxVprintf( const wxChar *format, va_list argptr ) { - CONVERT_FORMAT_1 - - int ret = vswprintf( str, size, new_format, ap ); - - CONVERT_FORMAT_2 - - return ret; + return vwprintf( wxFormatConverter(format), argptr ); } -int wxVsprintf( wxChar *str, const wxChar *format, va_list ap ) +#ifndef wxVsnprintf +int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr ) { - CONVERT_FORMAT_1 - - // This is so ugly - int ret = vswprintf(str, 10000, new_format, ap); - - CONVERT_FORMAT_2 - - return ret; + return vswprintf( str, size, wxFormatConverter(format), argptr ); } -#endif +#endif // wxVsnprintf -// 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 wxVsprintf( 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 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; - } - - return rc; -#endif // Unicode/ANSI + // same as for wxSprintf() + return vswprintf(str, UINT_MAX, wxFormatConverter(format), argptr); } -#endif -#if !defined(wxSnprintf) && !defined(wxHAS_SNPRINTF) -int WXDLLEXPORT wxSnprintf(wxChar *buf, size_t len, - const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); +#endif // wxNEED_PRINTF_CONVERSION - int iLen = wxVsnprintf(buf, len, format, argptr); - - va_end(argptr); - - 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);