#include <winnt.h>
#endif
+#ifndef wxStrtoll
+ #ifdef __WXWINCE__
+ // there is no errno.h under CE apparently
+ #define wxSET_ERRNO(value)
+ #else
+ #include <errno.h>
+
+ #define wxSET_ERRNO(value) errno = value
+ #endif
+#endif
+
#if defined(__MWERKS__) && __MSL__ >= 0x6000
namespace std {}
using namespace std ;
#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;
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)
#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);
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);
return ret;
}
-int wxDoFscanf( FILE *stream, const wxChar *format, ... )
+int wxCRT_Fscanf( FILE *stream, const wxChar *format, ... )
{
va_list argptr;
va_start(argptr, format);
return ret;
}
-int wxDoPrintf( const wxChar *format, ... )
+int wxCRT_Printf( const wxChar *format, ... )
{
va_list argptr;
va_start(argptr, 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
- return s.length();
+#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);
+
+ 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
- return ret;
+#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
-int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr )
+#if wxUSE_UNICODE_UTF8
+int wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...)
{
- return vswscanf( str, wxFormatConverter(format), argptr );
+ 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 wxVfprintf( FILE *stream, 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 vfwprintf( stream, 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 wxVprintf( const wxChar *format, va_list argptr )
+#if wxUSE_UNICODE_UTF8
+static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize)
{
- return vwprintf( 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
-#ifndef wxVsnprintf
-int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
+template<typename T>
+static size_t PrintfViaString(T *out, size_t outsize,
+ const wxString& format, va_list argptr)
{
- return vswprintf( str, size, wxFormatConverter(format), argptr );
+ wxString s;
+ s.PrintfV(format, argptr);
+
+ return ConvertStringToBuf(s, out, outsize);
}
-#endif // wxVsnprintf
+#endif // wxUSE_UNICODE
-int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr )
+int wxVsprintf(char *str, const wxString& format, va_list argptr)
{
- // same as for wxSprintf()
- return vswprintf(str, INT_MAX / 4, 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 // wxNEED_PRINTF_CONVERSION
+#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)
+{
+ 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;
+}
+
+#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
}
#endif
-#ifndef wxSetlocale
-WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
+#ifndef wxSetlocale_
+wxWCharBuffer wxSetlocale_(int category, const wxChar *locale)
{
char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
}
-#endif
+
+wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
+{
+ wxWCharBuffer rv = wxSetlocale_(category, locale);
+ if ( rv )
+ wxUpdateLocaleIsUtf8();
+ return rv;
+}
+#else // defined(wxSetlocale_)
+wxChar *wxSetlocale(int category, const wxChar *locale)
+{
+ wxChar *rv = wxSetlocale_(category, locale);
+ if ( rv )
+ wxUpdateLocaleIsUtf8();
+ return rv;
+}
+#endif // wxSetlocale_ defined or not
#if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
#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
#endif // wxUSE_WCHAR_T
+#ifndef wxStrtoll
+static wxULongLong_t wxStrtoullBase(const wxChar* nptr, wxChar** endptr, int base, wxChar* sign)
+{
+ wxULongLong_t sum = 0;
+ wxString wxstr(nptr);
+ wxString::const_iterator i = wxstr.begin();
+ wxString::const_iterator end = wxstr.end();
+
+ // Skip spaces
+ while ( i != end && wxIsspace(*i) ) i++;
+
+ // Starts with sign?
+ *sign = wxT(' ');
+ if ( i != end )
+ {
+ wxChar c = *i;
+ if ( c == wxT('+') || c == wxT('-') )
+ {
+ *sign = c;
+ i++;
+ }
+ }
+
+ // Starts with 0x?
+ if ( i != end && *i == wxT('0') )
+ {
+ i++;
+ if ( i != end )
+ {
+ if ( *i == wxT('x') && (base == 16 || base == 0) )
+ {
+ base = 16;
+ i++;
+ }
+ else
+ {
+ if ( endptr )
+ *endptr = (wxChar*) nptr;
+ wxSET_ERRNO(EINVAL);
+ return sum;
+ }
+ }
+ else
+ i--;
+ }
+
+ if ( base == 0 )
+ base = 10;
+
+ for ( ; i != end; i++ )
+ {
+ unsigned int n;
+
+ wxChar c = *i;
+ if ( c >= wxT('0') )
+ {
+ if ( c <= wxT('9') )
+ n = c - wxT('0');
+ else
+ n = wxTolower(c) - wxT('a') + 10;
+ }
+ else
+ break;
+
+ if ( n >= (unsigned int)base )
+ // Invalid character (for this base)
+ break;
+
+ wxULongLong_t prevsum = sum;
+ sum = (sum * base) + n;
+
+ if ( sum < prevsum )
+ {
+ wxSET_ERRNO(ERANGE);
+ break;
+ }
+ }
+
+ if ( endptr )
+ {
+ *endptr = (wxChar*)(nptr + (i - wxstr.begin()));
+ }
+
+ return sum;
+}
+
+wxULongLong_t wxStrtoull(const wxChar* nptr, wxChar** endptr, int base)
+{
+ wxChar sign;
+ wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
+
+ if ( sign == wxT('-') )
+ {
+ wxSET_ERRNO(ERANGE);
+ uval = 0;
+ }
+
+ return uval;
+}
+
+wxLongLong_t wxStrtoll(const wxChar* nptr, wxChar** endptr, int base)
+{
+ wxChar sign;
+ wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
+ wxLongLong_t val = 0;
+
+ if ( sign == wxT('-') )
+ {
+ if ( uval <= wxULL(wxINT64_MAX+1) )
+ {
+ if ( uval == wxULL(wxINT64_MAX+1))
+ val = -((wxLongLong_t)wxINT64_MAX) - 1;
+ else
+ val = -((wxLongLong_t)uval);
+ }
+ else
+ {
+ wxSET_ERRNO(ERANGE);
+ }
+ }
+ else if ( uval <= wxINT64_MAX )
+ {
+ val = uval;
+ }
+ else
+ {
+ wxSET_ERRNO(ERANGE);
+ }
+
+ return val;
+}
+#endif // wxStrtoll
+
// ----------------------------------------------------------------------------
// functions which we may need even if !wxUSE_WCHAR_T
// ----------------------------------------------------------------------------
}
#endif
+
+
+// ----------------------------------------------------------------------------
+// wxLocaleIsUtf8
+// ----------------------------------------------------------------------------
+
+#if wxUSE_UNICODE_UTF8
+
+#if !wxUSE_UTF8_LOCALE_ONLY
+bool wxLocaleIsUtf8 = false; // the safer setting if not known
+#endif
+
+static bool wxIsLocaleUtf8()
+{
+ // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
+ // because a) it may be unavailable in some builds and b) has slightly
+ // different semantics (default locale instead of current)
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+ // GNU libc provides current character set this way (this conforms to
+ // Unix98)
+ const char *charset = nl_langinfo(CODESET);
+ if ( charset )
+ {
+ // "UTF-8" is used by modern glibc versions, but test other variants
+ // as well, just in case:
+ if ( strcmp(charset, "UTF-8") == 0 ||
+ strcmp(charset, "utf-8") == 0 ||
+ strcmp(charset, "UTF8") == 0 ||
+ strcmp(charset, "utf8") == 0 )
+ {
+ return true;
+ }
+ }
+#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) )
+ {
+ return true;
+ }
+
+ // we don't know what charset libc is using, so assume the worst
+ // to be safe:
+ return false;
+}
+
+void wxUpdateLocaleIsUtf8()
+{
+#if wxUSE_UTF8_LOCALE_ONLY
+ if ( !wxIsLocaleUtf8() )
+ {
+ wxLogFatalError(_T("This program requires UTF-8 locale to run."));
+ }
+#else // !wxUSE_UTF8_LOCALE_ONLY
+ wxLocaleIsUtf8 = wxIsLocaleUtf8();
+#endif
+}
+
+#endif // wxUSE_UTF8_LOCALE_ONLY