X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cb352236d9c7228e336a98c2c1a22e933c67e449..0a7ce61e65c6fffcc8ab1649ab29c08d90e13fdb:/src/common/wxcrt.cpp diff --git a/src/common/wxcrt.cpp b/src/common/wxcrt.cpp index 3d12a3bee7..a3abc326bf 100644 --- a/src/common/wxcrt.cpp +++ b/src/common/wxcrt.cpp @@ -163,31 +163,16 @@ bool WXDLLEXPORT wxOKlibc() #undef wxVsprintf #undef wxVprintf #undef wxVsnprintf_ - #undef wxSnprintf_ #define wxNEED_WPRINTF int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr ); #endif -#if !defined(wxSnprintf_) -int WXDLLEXPORT wxDoSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...) -{ - va_list argptr; - va_start(argptr, format); - - int iLen = wxVsnprintf_(buf, len, format, argptr); - - va_end(argptr); - - return iLen; -} -#endif // wxSnprintf_ - #if defined(__DMC__) /* Digital Mars adds count to _stprintf (C99) so convert */ #if wxUSE_UNICODE - int wxDoSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... ) + int wxSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... ) { va_list arglist; @@ -268,9 +253,7 @@ int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr) wxCHECK_MSG( wxStrstr(format, _T("%c")) == NULL, -1, _T("incomplete vswscanf implementation doesn't allow %c") ); - va_list argcopy; - wxVaCopy(argcopy, argptr); - return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argcopy); + return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argptr); } int vfwscanf(FILE *stream, const wxChar *format, va_list argptr) @@ -527,7 +510,7 @@ wxString wxConvertFormat(const wxChar *format) #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF) -int wxDoScanf( const wxChar *format, ... ) +int wxCRT_Scanf( const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -539,7 +522,7 @@ int wxDoScanf( const wxChar *format, ... ) return ret; } -int wxDoSscanf( const wxChar *str, const wxChar *format, ... ) +int wxCRT_Sscanf( const wxChar *str, const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -551,7 +534,7 @@ int wxDoSscanf( const wxChar *str, const wxChar *format, ... ) return ret; } -int wxDoFscanf( FILE *stream, const wxChar *format, ... ) +int wxCRT_Fscanf( FILE *stream, const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -562,7 +545,7 @@ int wxDoFscanf( FILE *stream, const wxChar *format, ... ) return ret; } -int wxDoPrintf( const wxChar *format, ... ) +int wxCRT_Printf( const wxChar *format, ... ) { va_list argptr; va_start(argptr, format); @@ -574,80 +557,300 @@ int wxDoPrintf( const wxChar *format, ... ) return ret; } -#ifndef wxSnprintf -int wxDoSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) +int wxCRT_Fprintf( FILE *stream, const wxChar *format, ... ) +{ + va_list argptr; + va_start( argptr, format ); + + int ret = vfwprintf( stream, wxFormatConverter(format), argptr ); + + va_end(argptr); + + return ret; +} + +int wxCRT_Vsscanf( const wxChar *str, const wxChar *format, va_list argptr ) +{ + return vswscanf( str, wxFormatConverter(format), argptr ); +} + +int wxCRT_Vfprintf( FILE *stream, const wxChar *format, va_list argptr ) +{ + return vfwprintf( stream, wxFormatConverter(format), argptr ); +} + +int wxCRT_Vprintf( const wxChar *format, va_list argptr ) +{ + return vwprintf( wxFormatConverter(format), argptr ); +} + +#ifndef wxCRT_Vsnprintf +int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr ) +{ + return vswprintf( str, size, wxFormatConverter(format), argptr ); +} +#endif // wxCRT_Vsnprintf + +int wxCRT_Vsprintf( wxChar *str, const wxChar *format, va_list argptr ) +{ + // same as for wxSprintf() + return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr); +} + +#endif // wxNEED_PRINTF_CONVERSION + + +// ---------------------------------------------------------------------------- +// wrappers to printf and scanf function families +// ---------------------------------------------------------------------------- + +#if !wxUSE_UTF8_LOCALE_ONLY +int wxDoSprintfWchar(char *str, const wxChar *format, ...) { va_list argptr; va_start(argptr, format); - int ret = vswprintf( str, size, wxFormatConverter(format), argptr ); + int rv = wxVsprintf(str, format, argptr); - // VsnprintfTestCase reveals that glibc's implementation of vswprintf - // doesn't nul terminate on truncation. - str[size - 1] = 0; + va_end(argptr); + return rv; +} +#endif // !wxUSE_UTF8_LOCALE_ONLY + +#if wxUSE_UNICODE_UTF8 +int wxDoSprintfUtf8(char *str, const char *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsprintf(str, format, argptr); va_end(argptr); + return rv; +} +#endif // wxUSE_UNICODE_UTF8 - return ret; +#if wxUSE_UNICODE + +#if !wxUSE_UTF8_LOCALE_ONLY +int wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsprintf(str, format, argptr); + + va_end(argptr); + return rv; } -#endif // wxSnprintf +#endif // !wxUSE_UTF8_LOCALE_ONLY -int wxDoSprintf( wxChar *str, const wxChar *format, ... ) +#if wxUSE_UNICODE_UTF8 +int wxDoSprintfUtf8(wchar_t *str, const char *format, ...) { va_list argptr; va_start(argptr, format); - // note that wxString::FormatV() uses wxVsnprintf(), not wxSprintf(), so - // it's safe to implement this one in terms of it - wxString s(wxString::FormatV(format, argptr)); - wxStrcpy(str, s); + int rv = wxVsprintf(str, format, argptr); va_end(argptr); + return rv; +} +#endif // wxUSE_UNICODE_UTF8 + +#endif // wxUSE_UNICODE + +#if !wxUSE_UTF8_LOCALE_ONLY +int wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsnprintf(str, size, format, argptr); - return s.length(); + va_end(argptr); + return rv; } +#endif // !wxUSE_UTF8_LOCALE_ONLY -int wxDoFprintf( FILE *stream, const wxChar *format, ... ) +#if wxUSE_UNICODE_UTF8 +int wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...) { va_list argptr; - va_start( argptr, format ); + va_start(argptr, format); - int ret = vfwprintf( stream, wxFormatConverter(format), argptr ); + int rv = wxVsnprintf(str, size, format, argptr); + + va_end(argptr); + return rv; +} +#endif // wxUSE_UNICODE_UTF8 + +#if wxUSE_UNICODE + +#if !wxUSE_UTF8_LOCALE_ONLY +int wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsnprintf(str, size, format, argptr); va_end(argptr); + return rv; +} +#endif // !wxUSE_UTF8_LOCALE_ONLY - return ret; +#if wxUSE_UNICODE_UTF8 +int wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int rv = wxVsnprintf(str, size, format, argptr); + + va_end(argptr); + return rv; } +#endif // wxUSE_UNICODE_UTF8 + +#endif // wxUSE_UNICODE + -int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr ) +#ifdef HAVE_BROKEN_VSNPRINTF_DECL + #define vsnprintf wx_fixed_vsnprintf +#endif + +#if wxUSE_UNICODE + +#if !wxUSE_UTF8_LOCALE_ONLY +static int ConvertStringToBuf(const wxString& s, char *out, size_t outsize) { - return vswscanf( str, wxFormatConverter(format), argptr ); + const wxWX2WCbuf buf = s.wc_str(); + + size_t len = wxConvLibc.FromWChar(out, outsize, buf); + if ( len != wxCONV_FAILED ) + return len-1; + else + return wxConvLibc.FromWChar(NULL, 0, buf); } +#endif // !wxUSE_UTF8_LOCALE_ONLY -int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr ) +#if wxUSE_UNICODE_UTF8 +static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize) { - return vfwprintf( stream, wxFormatConverter(format), argptr ); + const wxWX2WCbuf buf(s.wc_str()); + size_t len = wxWcslen(buf); + if ( outsize > len ) + memcpy(out, buf, (len+1) * sizeof(wchar_t)); + // else: not enough space + return len; } +#endif // wxUSE_UNICODE_UTF8 -int wxVprintf( const wxChar *format, va_list argptr ) +template +static size_t PrintfViaString(T *out, size_t outsize, + const wxString& format, va_list argptr) { - return vwprintf( wxFormatConverter(format), argptr ); + wxString s; + s.PrintfV(format, argptr); + + return ConvertStringToBuf(s, out, outsize); } +#endif // wxUSE_UNICODE -#ifndef wxVsnprintf -int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr ) +int wxVsprintf(char *str, const wxString& format, va_list argptr) { - return vswprintf( str, size, wxFormatConverter(format), argptr ); +#if wxUSE_UTF8_LOCALE_ONLY + return vsprintf(str, format.wx_str(), argptr); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + return vsprintf(str, format.wx_str(), argptr); + else + #endif + #if wxUSE_UNICODE + return PrintfViaString(str, wxNO_LEN, format, argptr); + #else + return wxCRT_Vsprintf(str, format, argptr); + #endif +#endif } -#endif // wxVsnprintf -int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr ) +#if wxUSE_UNICODE +int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr) +{ +#if wxUSE_UNICODE_WCHAR + return wxCRT_Vsprintf(str, format, argptr); +#else // wxUSE_UNICODE_UTF8 + #if !wxUSE_UTF8_LOCALE_ONLY + if ( !wxLocaleIsUtf8 ) + return wxCRT_Vsprintf(str, format, argptr); + else + #endif + return PrintfViaString(str, wxNO_LEN, format, argptr); +#endif // wxUSE_UNICODE_UTF8 +} +#endif // wxUSE_UNICODE + +int wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr) { - // same as for wxSprintf() - return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr); + int rv; +#if wxUSE_UTF8_LOCALE_ONLY + rv = vsnprintf(str, size, format.wx_str(), argptr); +#else + #if wxUSE_UNICODE_UTF8 + if ( wxLocaleIsUtf8 ) + rv = vsnprintf(str, size, format.wx_str(), argptr); + else + #endif + #if wxUSE_UNICODE + { + // NB: if this code is called, then wxString::PrintV() would use the + // wchar_t* version of wxVsnprintf(), so it's safe to use PrintV() + // from here + rv = PrintfViaString(str, size, format, argptr); + } + #else + rv = wxCRT_Vsnprintf(str, size, format, argptr); + #endif +#endif + + // VsnprintfTestCase reveals that glibc's implementation of vswprintf + // doesn't nul terminate on truncation. + str[size - 1] = 0; + + return rv; } -#endif // wxNEED_PRINTF_CONVERSION +#if wxUSE_UNICODE +int wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr) +{ + int rv; + +#if wxUSE_UNICODE_WCHAR + rv = wxCRT_Vsnprintf(str, size, format, argptr); +#else // wxUSE_UNICODE_UTF8 + #if !wxUSE_UTF8_LOCALE_ONLY + if ( !wxLocaleIsUtf8 ) + rv = wxCRT_Vsnprintf(str, size, format, argptr); + else + #endif + { + // NB: if this code is called, then wxString::PrintV() would use the + // char* version of wxVsnprintf(), so it's safe to use PrintV() + // from here + rv = PrintfViaString(str, size, format, argptr); + } +#endif // wxUSE_UNICODE_UTF8 + + // VsnprintfTestCase reveals that glibc's implementation of vswprintf + // doesn't nul terminate on truncation. + str[size - 1] = 0; + + return rv; +} +#endif // wxUSE_UNICODE #if wxUSE_WCHAR_T @@ -820,9 +1023,9 @@ wxWCharBuffer wxSetlocale(int category, const wxChar *locale) return rv; } #else // defined(wxSetlocale_) -const wxChar *wxSetlocale(int category, const wxChar *locale) +wxChar *wxSetlocale(int category, const wxChar *locale) { - const wxChar *rv = wxSetlocale_(category, locale); + wxChar *rv = wxSetlocale_(category, locale); if ( rv ) wxUpdateLocaleIsUtf8(); return rv; @@ -1108,12 +1311,14 @@ wxChar * WXDLLEXPORT wxGetenv(const wxChar *name) #endif } +#endif // wxNEED_WX_STDLIB_H + +#ifdef wxNEED_WXSYSTEM int WXDLLEXPORT wxSystem(const wxChar *psz) { return system(wxConvLibc.cWX2MB(psz)); } - -#endif // wxNEED_WX_STDLIB_H +#endif // wxNEED_WXSYSTEM #ifdef wxNEED_WX_TIME_H WXDLLEXPORT size_t @@ -1239,8 +1444,7 @@ static wxULongLong_t wxStrtoullBase(const wxChar* nptr, wxChar** endptr, int bas if ( endptr ) { - const wxChar& endref = *i; - *endptr = &(wxChar&)endref; + *endptr = (wxChar*)(nptr + (i - wxstr.begin())); } return sum; @@ -1392,18 +1596,28 @@ static bool wxIsLocaleUtf8() { // "UTF-8" is used by modern glibc versions, but test other variants // as well, just in case: - return strcmp(charset, "UTF-8") == 0 || - strcmp(charset, "utf-8") == 0 || - strcmp(charset, "UTF8") == 0 || - strcmp(charset, "utf8") == 0; + if ( strcmp(charset, "UTF-8") == 0 || + strcmp(charset, "utf-8") == 0 || + strcmp(charset, "UTF8") == 0 || + strcmp(charset, "utf8") == 0 ) + { + return true; + } } - else // nl_langinfo() failed #endif + + // check if we're running under the "C" locale: it is 7bit subset + // of UTF-8, so it can be safely used with the UTF-8 build: + const char *lc_ctype = setlocale(LC_CTYPE, NULL); + if ( lc_ctype && + (strcmp(lc_ctype, "C") == 0 || strcmp(lc_ctype, "POSIX") == 0) ) { - // we don't know what charset libc is using, so assume the worst - // to be safe: - return false; + return true; } + + // we don't know what charset libc is using, so assume the worst + // to be safe: + return false; } void wxUpdateLocaleIsUtf8()