Files
wxWidgets/src/common/wxcrt.cpp
Vadim Zeitlin bd362275b8 Remove Palm OS port.
The platform targeted by this port doesn't exist any more and the port never
achieved really working state so remove the code to avoid having to maintain
it.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70345 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2012-01-15 01:05:28 +00:00

1338 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
// RCS-ID: $Id$
// 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(__MWERKS__) && __MSL__ >= 0x6000
namespace std {}
using namespace std ;
#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 wxMbstowcs(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 and if the CRT doesn't
// support it (the only currently known example being Metrowerks, see
// wx/crt.h) we don't use its mbstowcs() at all
#ifdef HAVE_WCSRTOMBS
return mbsrtowcs(NULL, &psz, 0, &mbstate);
#else
return wxMbstowcs(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 wxWcstombs(buf, pwz, n);
#endif
}
#ifdef HAVE_WCSRTOMBS
return wcsrtombs(NULL, &pwz, 0, &mbstate);
#else
return wxWcstombs(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) * sizeof(char));
}
else // not enough space
{
memcpy(out, buf, (outsize-1) * sizeof(char));
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)
// ----------------------------------------------------------------------------
#ifdef wxNEED_WX_MBSTOWCS
WXDLLIMPEXP_BASE size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
{
if (!out)
{
size_t outsize = 0;
while(*in++)
outsize++;
return outsize;
}
const char* origin = in;
while (outlen-- && *in)
{
*out++ = (wchar_t) *in++;
}
*out = '\0';
return in - origin;
}
WXDLLIMPEXP_BASE size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
{
if (!out)
{
size_t outsize = 0;
while(*in++)
outsize++;
return outsize;
}
const wchar_t* origin = in;
while (outlen-- && *in)
{
*out++ = (char) *in++;
}
*out = '\0';
return in - origin;
}
#endif // wxNEED_WX_MBSTOWCS
#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);
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 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 = (T*) nptr;
wxSET_ERRNO(EINVAL);
return sum;
}
}
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