1297 lines
33 KiB
C++
1297 lines
33 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/wxcrt.cpp
|
|
// Purpose: wxChar CRT wrappers implementation
|
|
// Author: Ove Kaven
|
|
// Modified by: Ron Lee, Francesco Montorsi
|
|
// Created: 09/04/99
|
|
// Copyright: (c) wxWidgets copyright
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ===========================================================================
|
|
// headers, declarations, constants
|
|
// ===========================================================================
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include "wx/crt.h"
|
|
#include "wx/strconv.h" // wxMBConv::cWC2MB()
|
|
|
|
#define _ISOC9X_SOURCE 1 // to get vsscanf()
|
|
#define _BSD_SOURCE 1 // to still get strdup()
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
|
|
#ifdef __SGI__
|
|
// wide character functions are declared in std namespace under IRIX
|
|
using namespace std;
|
|
|
|
// and this one is only declared if __c99 is defined which is not the case
|
|
// for C++ builds, so declare it ourselves
|
|
extern "C" int vswscanf(const wchar_t *, const wchar_t *, va_list);
|
|
#endif
|
|
|
|
#ifndef __WXWINCE__
|
|
#include <time.h>
|
|
#include <locale.h>
|
|
#else
|
|
#include "wx/msw/wince/time.h"
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/string.h"
|
|
#include "wx/hash.h"
|
|
#include "wx/utils.h" // for wxMin and wxMax
|
|
#include "wx/log.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_LANGINFO_H
|
|
#include <langinfo.h>
|
|
#endif
|
|
|
|
#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
|
|
|
|
#if defined(__DARWIN__)
|
|
#include "wx/osx/core/cfref.h"
|
|
#include <CoreFoundation/CFLocale.h>
|
|
#include "wx/osx/core/cfstring.h"
|
|
#include <xlocale.h>
|
|
#endif
|
|
|
|
WXDLLIMPEXP_BASE size_t wxMB2WC(wchar_t *buf, const char *psz, size_t n)
|
|
{
|
|
// assume that we have mbsrtowcs() too if we have wcsrtombs()
|
|
#ifdef HAVE_WCSRTOMBS
|
|
mbstate_t mbstate;
|
|
memset(&mbstate, 0, sizeof(mbstate_t));
|
|
#endif
|
|
|
|
if (buf) {
|
|
if (!n || !*psz) {
|
|
if (n) *buf = wxT('\0');
|
|
return 0;
|
|
}
|
|
#ifdef HAVE_WCSRTOMBS
|
|
return mbsrtowcs(buf, &psz, n, &mbstate);
|
|
#else
|
|
return mbstowcs(buf, psz, n);
|
|
#endif
|
|
}
|
|
|
|
// Note that we rely on common (and required by Unix98 but unfortunately not
|
|
// C99) extension which allows to call mbs(r)towcs() with NULL output pointer
|
|
// to just get the size of the needed buffer -- this is needed as otherwise
|
|
// we have no idea about how much space we need. Currently all supported
|
|
// compilers do provide it and if they don't, HAVE_WCSRTOMBS shouldn't be
|
|
// defined at all.
|
|
#ifdef HAVE_WCSRTOMBS
|
|
return mbsrtowcs(NULL, &psz, 0, &mbstate);
|
|
#else
|
|
return mbstowcs(NULL, psz, 0);
|
|
#endif
|
|
}
|
|
|
|
WXDLLIMPEXP_BASE size_t wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
|
|
{
|
|
#ifdef HAVE_WCSRTOMBS
|
|
mbstate_t mbstate;
|
|
memset(&mbstate, 0, sizeof(mbstate_t));
|
|
#endif
|
|
|
|
if (buf) {
|
|
if (!n || !*pwz) {
|
|
// glibc2.1 chokes on null input
|
|
if (n) *buf = '\0';
|
|
return 0;
|
|
}
|
|
#ifdef HAVE_WCSRTOMBS
|
|
return wcsrtombs(buf, &pwz, n, &mbstate);
|
|
#else
|
|
return wcstombs(buf, pwz, n);
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_WCSRTOMBS
|
|
return wcsrtombs(NULL, &pwz, 0, &mbstate);
|
|
#else
|
|
return wcstombs(NULL, pwz, 0);
|
|
#endif
|
|
}
|
|
|
|
char* wxSetlocale(int category, const char *locale)
|
|
{
|
|
#ifdef __WXWINCE__
|
|
// FIXME-CE: there is no setlocale() in CE CRT, use SetThreadLocale()?
|
|
wxUnusedVar(category);
|
|
wxUnusedVar(locale);
|
|
|
|
return NULL;
|
|
#else // !__WXWINCE__
|
|
#ifdef __WXMAC__
|
|
char *rv = NULL ;
|
|
if ( locale != NULL && locale[0] == 0 )
|
|
{
|
|
// the attempt to use newlocale(LC_ALL_MASK, "", NULL);
|
|
// here in order to deduce the language along the environment vars rules
|
|
// lead to strange crashes later...
|
|
|
|
// we have to emulate the behaviour under OS X
|
|
wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
|
|
wxCFStringRef str(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode)));
|
|
wxString langFull = str.AsString()+"_";
|
|
str.reset(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode)));
|
|
langFull += str.AsString();
|
|
rv = setlocale(category, langFull.c_str());
|
|
}
|
|
else
|
|
rv = setlocale(category, locale);
|
|
#else
|
|
char *rv = setlocale(category, locale);
|
|
#endif
|
|
if ( locale != NULL /* setting locale, not querying */ &&
|
|
rv /* call was successful */ )
|
|
{
|
|
wxUpdateLocaleIsUtf8();
|
|
}
|
|
return rv;
|
|
#endif // __WXWINCE__/!__WXWINCE__
|
|
}
|
|
|
|
// ============================================================================
|
|
// printf() functions business
|
|
// ============================================================================
|
|
|
|
// special test mode: define all functions below even if we don't really need
|
|
// them to be able to test them
|
|
#ifdef wxTEST_PRINTF
|
|
#undef wxFprintf
|
|
#undef wxPrintf
|
|
#undef wxSprintf
|
|
#undef wxVfprintf
|
|
#undef wxVsprintf
|
|
#undef wxVprintf
|
|
#undef wxVsnprintf_
|
|
|
|
#define wxNEED_WPRINTF
|
|
|
|
int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list argptr );
|
|
#endif
|
|
|
|
#if defined(__DMC__)
|
|
/* Digital Mars adds count to _stprintf (C99) so convert */
|
|
int wxCRT_SprintfW (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
|
|
{
|
|
va_list arglist;
|
|
|
|
va_start( arglist, format );
|
|
int iLen = swprintf ( s, -1, format, arglist );
|
|
va_end( arglist );
|
|
return iLen ;
|
|
}
|
|
#endif //__DMC__
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// implement the standard IO functions for wide char if libc doesn't have them
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifndef wxCRT_FputsW
|
|
int wxCRT_FputsW(const wchar_t *ws, FILE *stream)
|
|
{
|
|
wxCharBuffer buf(wxConvLibc.cWC2MB(ws));
|
|
if ( !buf )
|
|
return -1;
|
|
|
|
// counting the number of wide characters written isn't worth the trouble,
|
|
// simply distinguish between ok and error
|
|
return wxCRT_FputsA(buf, stream) == -1 ? -1 : 0;
|
|
}
|
|
#endif // !wxCRT_FputsW
|
|
|
|
#ifndef wxCRT_PutsW
|
|
int wxCRT_PutsW(const wchar_t *ws)
|
|
{
|
|
int rc = wxCRT_FputsW(ws, stdout);
|
|
if ( rc != -1 )
|
|
{
|
|
if ( wxCRT_FputsW(L"\n", stdout) == -1 )
|
|
return -1;
|
|
|
|
rc++;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
#endif // !wxCRT_PutsW
|
|
|
|
#ifndef wxCRT_FputcW
|
|
int /* not wint_t */ wxCRT_FputcW(wchar_t wc, FILE *stream)
|
|
{
|
|
wchar_t ws[2] = { wc, L'\0' };
|
|
|
|
return wxCRT_FputsW(ws, stream);
|
|
}
|
|
#endif // !wxCRT_FputcW
|
|
|
|
// 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
|
|
static int vwscanf(const wchar_t *format, va_list argptr)
|
|
{
|
|
wxFAIL_MSG( wxT("TODO") );
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int vfwscanf(FILE *stream, const wchar_t *format, va_list argptr)
|
|
{
|
|
wxFAIL_MSG( wxT("TODO") );
|
|
|
|
return -1;
|
|
}
|
|
|
|
#define vswprintf wxCRT_VsnprintfW
|
|
|
|
static 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", (const char*)s.mb_str() ) == -1 )
|
|
return -1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int vwprintf(const wchar_t *format, va_list argptr)
|
|
{
|
|
return wxCRT_VfprintfW(stdout, format, argptr);
|
|
}
|
|
|
|
#endif // wxNEED_WPRINTF
|
|
|
|
#ifdef wxNEED_VSWSCANF
|
|
static int vswscanf(const wchar_t *ws, const wchar_t *format, va_list argptr)
|
|
{
|
|
// The best we can do without proper Unicode support in glibc is to
|
|
// convert the strings into MB representation and run ANSI version
|
|
// of the function. This doesn't work with %c and %s because of difference
|
|
// in size of char and wchar_t, though.
|
|
|
|
wxCHECK_MSG( wxStrstr(format, wxT("%s")) == NULL, -1,
|
|
wxT("incomplete vswscanf implementation doesn't allow %s") );
|
|
wxCHECK_MSG( wxStrstr(format, wxT("%c")) == NULL, -1,
|
|
wxT("incomplete vswscanf implementation doesn't allow %c") );
|
|
|
|
return vsscanf(static_cast<const char*>(wxConvLibc.cWX2MB(ws)),
|
|
wxConvLibc.cWX2MB(format), argptr);
|
|
}
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxPrintf(), wxScanf() and relatives
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// FIXME-UTF8: do format conversion using (modified) wxFormatConverter in
|
|
// template wrappers, not here; note that it will needed to
|
|
// translate all forms of string specifiers to %(l)s for wxPrintf(),
|
|
// but it only should do what it did in 2.8 for wxScanf()!
|
|
|
|
#ifndef wxCRT_PrintfW
|
|
int wxCRT_PrintfW( const wchar_t *format, ... )
|
|
{
|
|
va_list argptr;
|
|
va_start(argptr, format);
|
|
|
|
int ret = vwprintf( format, argptr );
|
|
|
|
va_end(argptr);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_FprintfW
|
|
int wxCRT_FprintfW( FILE *stream, const wchar_t *format, ... )
|
|
{
|
|
va_list argptr;
|
|
va_start( argptr, format );
|
|
|
|
int ret = vfwprintf( stream, format, argptr );
|
|
|
|
va_end(argptr);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_VfprintfW
|
|
int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list argptr )
|
|
{
|
|
return vfwprintf( stream, format, argptr );
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_VprintfW
|
|
int wxCRT_VprintfW( const wchar_t *format, va_list argptr )
|
|
{
|
|
return vwprintf( format, argptr );
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_VsprintfW
|
|
int wxCRT_VsprintfW( wchar_t *str, const wchar_t *format, va_list argptr )
|
|
{
|
|
// same as for wxSprintf()
|
|
return vswprintf(str, INT_MAX / 4, format, argptr);
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_ScanfW
|
|
int wxCRT_ScanfW(const wchar_t *format, ...)
|
|
{
|
|
va_list argptr;
|
|
va_start(argptr, format);
|
|
|
|
#ifdef __VMS
|
|
#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
|
|
int ret = std::vwscanf(format, argptr);
|
|
#else
|
|
int ret = vwscanf(format, argptr);
|
|
#endif
|
|
#else
|
|
int ret = vwscanf(format, argptr);
|
|
#endif
|
|
|
|
va_end(argptr);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_SscanfW
|
|
int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...)
|
|
{
|
|
va_list argptr;
|
|
va_start(argptr, format);
|
|
|
|
#ifdef __VMS
|
|
#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
|
|
int ret = std::vswscanf(str, format, argptr);
|
|
#else
|
|
int ret = vswscanf(str, format, argptr);
|
|
#endif
|
|
#else
|
|
int ret = vswscanf(str, format, argptr);
|
|
#endif
|
|
|
|
va_end(argptr);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_FscanfW
|
|
int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...)
|
|
{
|
|
va_list argptr;
|
|
va_start(argptr, format);
|
|
#ifdef __VMS
|
|
#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
|
|
int ret = std::vfwscanf(stream, format, argptr);
|
|
#else
|
|
int ret = vfwscanf(stream, format, argptr);
|
|
#endif
|
|
#else
|
|
int ret = vfwscanf(stream, format, argptr);
|
|
#endif
|
|
|
|
va_end(argptr);
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_VsscanfW
|
|
int wxCRT_VsscanfW(const wchar_t *str, const wchar_t *format, va_list argptr)
|
|
{
|
|
#ifdef __VMS
|
|
#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
|
|
return std::vswscanf(str, format, argptr);
|
|
#else
|
|
return vswscanf(str, format, argptr);
|
|
#endif
|
|
#else
|
|
return vswscanf(str, format, argptr);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// 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 rv = wxVsprintf(str, format, argptr);
|
|
|
|
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
|
|
|
|
#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 // !wxUSE_UTF8_LOCALE_ONLY
|
|
|
|
#if wxUSE_UNICODE_UTF8
|
|
int wxDoSprintfUtf8(wchar_t *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
|
|
|
|
#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
|
|
|
|
#if wxUSE_UNICODE_UTF8
|
|
int wxDoSnprintfUtf8(char *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
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
|
|
#ifdef HAVE_BROKEN_VSNPRINTF_DECL
|
|
#define vsnprintf wx_fixed_vsnprintf
|
|
#endif
|
|
|
|
#if wxUSE_UNICODE
|
|
|
|
namespace
|
|
{
|
|
|
|
#if !wxUSE_UTF8_LOCALE_ONLY
|
|
int ConvertStringToBuf(const wxString& s, char *out, size_t outsize)
|
|
{
|
|
const wxCharBuffer buf(s.mb_str());
|
|
|
|
const size_t len = buf.length();
|
|
if ( outsize > len )
|
|
{
|
|
memcpy(out, buf, len+1);
|
|
}
|
|
else // not enough space
|
|
{
|
|
memcpy(out, buf, outsize-1);
|
|
out[outsize-1] = '\0';
|
|
}
|
|
|
|
return len;
|
|
}
|
|
#endif // !wxUSE_UTF8_LOCALE_ONLY
|
|
|
|
#if wxUSE_UNICODE_UTF8
|
|
int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize)
|
|
{
|
|
const wxWX2WCbuf buf(s.wc_str());
|
|
size_t len = s.length(); // same as buf length for wchar_t*
|
|
if ( outsize > len )
|
|
{
|
|
memcpy(out, buf, (len+1) * sizeof(wchar_t));
|
|
}
|
|
else // not enough space
|
|
{
|
|
memcpy(out, buf, (outsize-1) * sizeof(wchar_t));
|
|
out[outsize-1] = 0;
|
|
}
|
|
return len;
|
|
}
|
|
#endif // wxUSE_UNICODE_UTF8
|
|
|
|
} // anonymous namespace
|
|
|
|
template<typename T>
|
|
static size_t PrintfViaString(T *out, size_t outsize,
|
|
const wxString& format, va_list argptr)
|
|
{
|
|
wxString s;
|
|
s.PrintfV(format, argptr);
|
|
|
|
return ConvertStringToBuf(s, out, outsize);
|
|
}
|
|
#endif // wxUSE_UNICODE
|
|
|
|
int wxVsprintf(char *str, const wxString& format, va_list argptr)
|
|
{
|
|
#if wxUSE_UTF8_LOCALE_ONLY
|
|
return wxCRT_VsprintfA(str, format.wx_str(), argptr);
|
|
#else
|
|
#if wxUSE_UNICODE_UTF8
|
|
if ( wxLocaleIsUtf8 )
|
|
return wxCRT_VsprintfA(str, format.wx_str(), argptr);
|
|
else
|
|
#endif
|
|
#if wxUSE_UNICODE
|
|
return PrintfViaString(str, wxNO_LEN, format, argptr);
|
|
#else
|
|
return wxCRT_VsprintfA(str, format.mb_str(), argptr);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#if wxUSE_UNICODE
|
|
int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr)
|
|
{
|
|
#if wxUSE_UNICODE_WCHAR
|
|
#ifdef __DMC__
|
|
/*
|
|
This fails with a bug similar to
|
|
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=c++.beta&artnum=680
|
|
in DMC 8.49 and 8.50
|
|
I don't see it being used in the wxWidgets sources at present (oct 2007) CE
|
|
*/
|
|
#pragma message ( "warning ::::: wxVsprintf(wchar_t *str, const wxString& format, va_list argptr) not yet implemented" )
|
|
wxFAIL_MSG( wxT("TODO") );
|
|
|
|
return -1;
|
|
#else
|
|
return wxCRT_VsprintfW(str, format.wc_str(), argptr);
|
|
#endif //DMC
|
|
#else // wxUSE_UNICODE_UTF8
|
|
#if !wxUSE_UTF8_LOCALE_ONLY
|
|
if ( !wxLocaleIsUtf8 )
|
|
return wxCRT_VsprintfW(str, format.wc_str(), 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 = wxCRT_VsnprintfA(str, size, format.wx_str(), argptr);
|
|
#else
|
|
#if wxUSE_UNICODE_UTF8
|
|
if ( wxLocaleIsUtf8 )
|
|
rv = wxCRT_VsnprintfA(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_VsnprintfA(str, size, format.mb_str(), 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_VsnprintfW(str, size, format.wc_str(), argptr);
|
|
#else // wxUSE_UNICODE_UTF8
|
|
#if !wxUSE_UTF8_LOCALE_ONLY
|
|
if ( !wxLocaleIsUtf8 )
|
|
rv = wxCRT_VsnprintfW(str, size, format.wc_str(), 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
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ctype.h stuff (currently unused)
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifndef wxCRT_StrdupA
|
|
WXDLLIMPEXP_BASE char *wxCRT_StrdupA(const char *s)
|
|
{
|
|
return strcpy((char *)malloc(strlen(s) + 1), s);
|
|
}
|
|
#endif // wxCRT_StrdupA
|
|
|
|
#ifndef wxCRT_StrdupW
|
|
WXDLLIMPEXP_BASE wchar_t * wxCRT_StrdupW(const wchar_t *pwz)
|
|
{
|
|
size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
|
|
wchar_t *ret = (wchar_t *) malloc(size);
|
|
memcpy(ret, pwz, size);
|
|
return ret;
|
|
}
|
|
#endif // wxCRT_StrdupW
|
|
|
|
#ifndef wxWCHAR_T_IS_WXCHAR16
|
|
size_t wxStrlen(const wxChar16 *s )
|
|
{
|
|
if (!s) return 0;
|
|
size_t i=0;
|
|
while (*s!=0) { ++i; ++s; };
|
|
return i;
|
|
}
|
|
|
|
wxChar16* wxStrdup(const wxChar16* s)
|
|
{
|
|
size_t size = (wxStrlen(s) + 1) * sizeof(wxChar16);
|
|
wxChar16 *ret = (wxChar16*) malloc(size);
|
|
memcpy(ret, s, size);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxWCHAR_T_IS_WXCHAR32
|
|
size_t wxStrlen(const wxChar32 *s )
|
|
{
|
|
if (!s) return 0;
|
|
size_t i=0;
|
|
while (*s!=0) { ++i; ++s; };
|
|
return i;
|
|
}
|
|
|
|
wxChar32* wxStrdup(const wxChar32* s)
|
|
{
|
|
size_t size = (wxStrlen(s) + 1) * sizeof(wxChar32);
|
|
wxChar32 *ret = (wxChar32*) malloc(size);
|
|
if ( ret )
|
|
memcpy(ret, s, size);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifndef wxCRT_StricmpA
|
|
WXDLLIMPEXP_BASE int wxCRT_StricmpA(const char *psz1, const char *psz2)
|
|
{
|
|
register char c1, c2;
|
|
do {
|
|
c1 = wxTolower(*psz1++);
|
|
c2 = wxTolower(*psz2++);
|
|
} while ( c1 && (c1 == c2) );
|
|
return c1 - c2;
|
|
}
|
|
#endif // !defined(wxCRT_StricmpA)
|
|
|
|
#ifndef wxCRT_StricmpW
|
|
WXDLLIMPEXP_BASE int wxCRT_StricmpW(const wchar_t *psz1, const wchar_t *psz2)
|
|
{
|
|
register wchar_t c1, c2;
|
|
do {
|
|
c1 = wxTolower(*psz1++);
|
|
c2 = wxTolower(*psz2++);
|
|
} while ( c1 && (c1 == c2) );
|
|
return c1 - c2;
|
|
}
|
|
#endif // !defined(wxCRT_StricmpW)
|
|
|
|
#ifndef wxCRT_StrnicmpA
|
|
WXDLLIMPEXP_BASE int wxCRT_StrnicmpA(const char *s1, const char *s2, size_t n)
|
|
{
|
|
// initialize the variables just to suppress stupid gcc warning
|
|
register char c1 = 0, c2 = 0;
|
|
while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
|
|
if (n) {
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // !defined(wxCRT_StrnicmpA)
|
|
|
|
#ifndef wxCRT_StrnicmpW
|
|
WXDLLIMPEXP_BASE int wxCRT_StrnicmpW(const wchar_t *s1, const wchar_t *s2, size_t n)
|
|
{
|
|
// initialize the variables just to suppress stupid gcc warning
|
|
register wchar_t c1 = 0, c2 = 0;
|
|
while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
|
|
if (n) {
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // !defined(wxCRT_StrnicmpW)
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// string.h functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// this (and wxCRT_StrncmpW below) are extern "C" because they are needed
|
|
// by regex code, the rest isn't needed, so it's not declared as extern "C"
|
|
#ifndef wxCRT_StrlenW
|
|
extern "C" WXDLLIMPEXP_BASE size_t wxCRT_StrlenW(const wchar_t *s)
|
|
{
|
|
size_t n = 0;
|
|
while ( *s++ )
|
|
n++;
|
|
|
|
return n;
|
|
}
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// stdlib.h functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifndef wxCRT_GetenvW
|
|
WXDLLIMPEXP_BASE wchar_t* wxCRT_GetenvW(const wchar_t *name)
|
|
{
|
|
// NB: buffer returned by getenv() is allowed to be overwritten next
|
|
// time getenv() is called, so it is OK to use static string
|
|
// buffer to hold the data.
|
|
static wxWCharBuffer value;
|
|
value = wxConvLibc.cMB2WC(getenv(wxConvLibc.cWC2MB(name)));
|
|
return value.data();
|
|
}
|
|
#endif // !wxCRT_GetenvW
|
|
|
|
#ifndef wxCRT_StrftimeW
|
|
WXDLLIMPEXP_BASE size_t
|
|
wxCRT_StrftimeW(wchar_t *s, size_t maxsize, const wchar_t *fmt, const struct tm *tm)
|
|
{
|
|
if ( !maxsize )
|
|
return 0;
|
|
|
|
wxCharBuffer buf(maxsize);
|
|
|
|
wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
|
|
if ( !bufFmt )
|
|
return 0;
|
|
|
|
size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
|
|
if ( !ret )
|
|
return 0;
|
|
|
|
wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
|
|
if ( !wbuf )
|
|
return 0;
|
|
|
|
wxCRT_StrncpyW(s, wbuf, maxsize);
|
|
return wxCRT_StrlenW(s);
|
|
}
|
|
#endif // !wxCRT_StrftimeW
|
|
|
|
#ifdef wxLongLong_t
|
|
template<typename T>
|
|
static wxULongLong_t
|
|
wxCRT_StrtoullBase(const T* nptr, T** endptr, int base, T* 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 )
|
|
{
|
|
T c = *i;
|
|
if ( c == wxT('+') || c == wxT('-') )
|
|
{
|
|
*sign = c;
|
|
++i;
|
|
}
|
|
}
|
|
|
|
// Starts with octal or hexadecimal prefix?
|
|
if ( i != end && *i == wxT('0') )
|
|
{
|
|
++i;
|
|
if ( i != end )
|
|
{
|
|
if ( (*i == wxT('x')) || (*i == wxT('X')) )
|
|
{
|
|
// Hexadecimal prefix: use base 16 if auto-detecting.
|
|
if ( base == 0 )
|
|
base = 16;
|
|
|
|
// If we do use base 16, just skip "x" as well.
|
|
if ( base == 16 )
|
|
{
|
|
++i;
|
|
}
|
|
else // Not using base 16
|
|
{
|
|
// Then it's an error.
|
|
if ( endptr )
|
|
*endptr = (T*) nptr;
|
|
wxSET_ERRNO(EINVAL);
|
|
return sum;
|
|
}
|
|
}
|
|
else if ( base == 0 )
|
|
{
|
|
base = 8;
|
|
}
|
|
}
|
|
else
|
|
--i;
|
|
}
|
|
|
|
if ( base == 0 )
|
|
base = 10;
|
|
|
|
for ( ; i != end; ++i )
|
|
{
|
|
unsigned int n;
|
|
|
|
T c = *i;
|
|
if ( c >= '0' )
|
|
{
|
|
if ( c <= '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 = (T*)(nptr + (i - wxstr.begin()));
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
template<typename T>
|
|
static wxULongLong_t wxCRT_DoStrtoull(const T* nptr, T** endptr, int base)
|
|
{
|
|
T sign;
|
|
wxULongLong_t uval = ::wxCRT_StrtoullBase(nptr, endptr, base, &sign);
|
|
|
|
if ( sign == wxT('-') )
|
|
{
|
|
wxSET_ERRNO(ERANGE);
|
|
uval = 0;
|
|
}
|
|
|
|
return uval;
|
|
}
|
|
|
|
template<typename T>
|
|
static wxLongLong_t wxCRT_DoStrtoll(const T* nptr, T** endptr, int base)
|
|
{
|
|
T sign;
|
|
wxULongLong_t uval = ::wxCRT_StrtoullBase(nptr, endptr, base, &sign);
|
|
wxLongLong_t val = 0;
|
|
|
|
if ( sign == wxT('-') )
|
|
{
|
|
if (uval <= (wxULongLong_t)wxINT64_MAX + 1)
|
|
{
|
|
val = -(wxLongLong_t)uval;
|
|
}
|
|
else
|
|
{
|
|
wxSET_ERRNO(ERANGE);
|
|
}
|
|
}
|
|
else if ( uval <= wxINT64_MAX )
|
|
{
|
|
val = uval;
|
|
}
|
|
else
|
|
{
|
|
wxSET_ERRNO(ERANGE);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
#ifndef wxCRT_StrtollA
|
|
wxLongLong_t wxCRT_StrtollA(const char* nptr, char** endptr, int base)
|
|
{ return wxCRT_DoStrtoll(nptr, endptr, base); }
|
|
#endif
|
|
#ifndef wxCRT_StrtollW
|
|
wxLongLong_t wxCRT_StrtollW(const wchar_t* nptr, wchar_t** endptr, int base)
|
|
{ return wxCRT_DoStrtoll(nptr, endptr, base); }
|
|
#endif
|
|
|
|
#ifndef wxCRT_StrtoullA
|
|
wxULongLong_t wxCRT_StrtoullA(const char* nptr, char** endptr, int base)
|
|
{ return wxCRT_DoStrtoull(nptr, endptr, base); }
|
|
#endif
|
|
#ifndef wxCRT_StrtoullW
|
|
wxULongLong_t wxCRT_StrtoullW(const wchar_t* nptr, wchar_t** endptr, int base)
|
|
{ return wxCRT_DoStrtoull(nptr, endptr, base); }
|
|
#endif
|
|
|
|
#endif // wxLongLong_t
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// strtok() functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
template<typename T>
|
|
static T *wxCRT_DoStrtok(T *psz, const T *delim, T **save_ptr)
|
|
{
|
|
if (!psz)
|
|
{
|
|
psz = *save_ptr;
|
|
if ( !psz )
|
|
return NULL;
|
|
}
|
|
|
|
psz += wxStrspn(psz, delim);
|
|
if (!*psz)
|
|
{
|
|
*save_ptr = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
T *ret = psz;
|
|
psz = wxStrpbrk(psz, delim);
|
|
if (!psz)
|
|
{
|
|
*save_ptr = NULL;
|
|
}
|
|
else
|
|
{
|
|
*psz = wxT('\0');
|
|
*save_ptr = psz + 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifndef wxCRT_StrtokA
|
|
char *wxCRT_StrtokA(char *psz, const char *delim, char **save_ptr)
|
|
{ return wxCRT_DoStrtok(psz, delim, save_ptr); }
|
|
#endif
|
|
#ifndef wxCRT_StrtokW
|
|
wchar_t *wxCRT_StrtokW(wchar_t *psz, const wchar_t *delim, wchar_t **save_ptr)
|
|
{ return wxCRT_DoStrtok(psz, delim, save_ptr); }
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// missing C RTL functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef wxNEED_STRDUP
|
|
|
|
char *strdup(const char *s)
|
|
{
|
|
char *dest = (char*) malloc( strlen( s ) + 1 ) ;
|
|
if ( dest )
|
|
strcpy( dest , s ) ;
|
|
return dest ;
|
|
}
|
|
#endif // wxNEED_STRDUP
|
|
|
|
#if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
|
|
|
|
void *calloc( size_t num, size_t size )
|
|
{
|
|
void** ptr = (void **)malloc(num * size);
|
|
memset( ptr, 0, num * size);
|
|
return ptr;
|
|
}
|
|
|
|
#endif // __WXWINCE__ <= 211
|
|
|
|
// ============================================================================
|
|
// 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 // HAVE_LANGINFO_H
|
|
|
|
// 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(wxT("This program requires UTF-8 locale to run."));
|
|
}
|
|
#else // !wxUSE_UTF8_LOCALE_ONLY
|
|
wxLocaleIsUtf8 = wxIsLocaleUtf8();
|
|
#endif
|
|
}
|
|
|
|
#endif // wxUSE_UNICODE_UTF8
|
|
|
|
// ============================================================================
|
|
// wx wrappers for CRT functions
|
|
// ============================================================================
|
|
|
|
#if wxUSE_UNICODE_WCHAR
|
|
#define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callW
|
|
#elif wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
|
|
#define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) \
|
|
return_kw wxLocaleIsUtf8 ? callA : callW
|
|
#else // ANSI or UTF8 only
|
|
#define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callA
|
|
#endif
|
|
|
|
int wxPuts(const wxString& s)
|
|
{
|
|
// under IRIX putws() takes a non-const argument so use wchar_str() instead
|
|
// of wc_str()
|
|
CALL_ANSI_OR_UNICODE(return,
|
|
wxCRT_PutsA(s.mb_str()),
|
|
wxCRT_PutsW(s.wchar_str()));
|
|
}
|
|
|
|
int wxFputs(const wxString& s, FILE *stream)
|
|
{
|
|
CALL_ANSI_OR_UNICODE(return,
|
|
wxCRT_FputsA(s.mb_str(), stream),
|
|
wxCRT_FputsW(s.wc_str(), stream));
|
|
}
|
|
|
|
int wxFputc(const wxUniChar& c, FILE *stream)
|
|
{
|
|
#if !wxUSE_UNICODE // FIXME-UTF8: temporary, remove this with ANSI build
|
|
return wxCRT_FputcA((char)c, stream);
|
|
#else
|
|
CALL_ANSI_OR_UNICODE(return,
|
|
wxCRT_FputsA(c.AsUTF8(), stream),
|
|
wxCRT_FputcW((wchar_t)c, stream));
|
|
#endif
|
|
}
|
|
|
|
#ifdef wxCRT_PerrorA
|
|
|
|
void wxPerror(const wxString& s)
|
|
{
|
|
#ifdef wxCRT_PerrorW
|
|
CALL_ANSI_OR_UNICODE(wxEMPTY_PARAMETER_VALUE,
|
|
wxCRT_PerrorA(s.mb_str()),
|
|
wxCRT_PerrorW(s.wc_str()));
|
|
#else
|
|
wxCRT_PerrorA(s.mb_str());
|
|
#endif
|
|
}
|
|
|
|
#endif // wxCRT_PerrorA
|
|
|
|
wchar_t *wxFgets(wchar_t *s, int size, FILE *stream)
|
|
{
|
|
wxCHECK_MSG( s, NULL, "empty buffer passed to wxFgets()" );
|
|
|
|
wxCharBuffer buf(size - 1);
|
|
// FIXME: this reads too little data if wxConvLibc uses UTF-8 ('size' wide
|
|
// characters may be encoded by up to 'size'*4 bytes), but what
|
|
// else can we do?
|
|
if ( wxFgets(buf.data(), size, stream) == NULL )
|
|
return NULL;
|
|
|
|
if ( wxConvLibc.ToWChar(s, size, buf, wxNO_LEN) == wxCONV_FAILED )
|
|
return NULL;
|
|
|
|
return s;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxScanf() and friends
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef HAVE_VSSCANF // __VISUALC__ and __DMC__ see wx/crt.h
|
|
int wxVsscanf(const char *str, const char *format, va_list ap)
|
|
{ return wxCRT_VsscanfA(str, format, ap); }
|
|
int wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap)
|
|
{ return wxCRT_VsscanfW(str, format, ap); }
|
|
int wxVsscanf(const wxCharBuffer& str, const char *format, va_list ap)
|
|
{ return wxCRT_VsscanfA(static_cast<const char*>(str), format, ap); }
|
|
int wxVsscanf(const wxWCharBuffer& str, const wchar_t *format, va_list ap)
|
|
{ return wxCRT_VsscanfW(str, format, ap); }
|
|
int wxVsscanf(const wxString& str, const char *format, va_list ap)
|
|
{ return wxCRT_VsscanfA(static_cast<const char*>(str.mb_str()), format, ap); }
|
|
int wxVsscanf(const wxString& str, const wchar_t *format, va_list ap)
|
|
{ return wxCRT_VsscanfW(str.wc_str(), format, ap); }
|
|
int wxVsscanf(const wxCStrData& str, const char *format, va_list ap)
|
|
{ return wxCRT_VsscanfA(static_cast<const char*>(str.AsCharBuf()), format, ap); }
|
|
int wxVsscanf(const wxCStrData& str, const wchar_t *format, va_list ap)
|
|
{ return wxCRT_VsscanfW(str.AsWCharBuf(), format, ap); }
|
|
#endif // HAVE_NO_VSSCANF
|