/////////////////////////////////////////////////////////////////////////////
-// Name: wxchar.cpp
+// Name: src/common/wxchar.cpp
// Purpose: wxChar implementation
// Author: Ove Kåven
// Modified by: Ron Lee
// Created: 09/04/99
// RCS-ID: $Id$
-// Copyright: (c) wxWindows copyright
+// Copyright: (c) wxWidgets copyright
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "wxchar.h"
-#endif
-
// ===========================================================================
// headers, declarations, constants
// ===========================================================================
#include "wx/wxprec.h"
#ifdef __BORLANDC__
- #pragma hdrstop
+ #pragma hdrstop
#endif
#define _ISOC9X_SOURCE 1 // to get vsscanf()
#include <string.h>
#ifndef __WXWINCE__
-#include <time.h>
-#include <locale.h>
+ #include <time.h>
+ #include <locale.h>
#else
-#include "wx/msw/wince/time.h"
+ #include "wx/msw/wince/time.h"
#endif
#ifndef WX_PRECOMP
- #include "wx/defs.h"
- #include "wx/wxchar.h"
- #include "wx/string.h"
- #include "wx/hash.h"
+ #include "wx/wxchar.h"
+ #include "wx/string.h"
+ #include "wx/hash.h"
#endif
#if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
#include <windef.h>
- #include <winbase.h>
- #include <winnls.h>
- #include <winnt.h>
+ #include <winbase.h>
+ #include <winnls.h>
+ #include <winnt.h>
#endif
#if defined(__MWERKS__) && __MSL__ >= 0x6000
+namespace std {}
using namespace std ;
#endif
-#ifdef __WXMAC__
- #include "wx/mac/private.h"
-#endif
-
#if wxUSE_WCHAR_T
size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
{
// assume that we have mbsrtowcs() too if we have wcsrtombs()
-#if HAVE_WCSRTOMBS
+#ifdef HAVE_WCSRTOMBS
mbstate_t mbstate;
memset(&mbstate, 0, sizeof(mbstate_t));
#endif
#ifdef HAVE_WCSRTOMBS
return mbsrtowcs(buf, &psz, n, &mbstate);
#else
- return mbstowcs(buf, psz, n);
+ 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/wxchar.h) we don't use its mbstowcs() at all
#ifdef HAVE_WCSRTOMBS
return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
#else
- return mbstowcs((wchar_t *) NULL, psz, 0);
+ return wxMbstowcs((wchar_t *) NULL, psz, 0);
#endif
}
size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
{
-#if HAVE_WCSRTOMBS
+#ifdef HAVE_WCSRTOMBS
mbstate_t mbstate;
memset(&mbstate, 0, sizeof(mbstate_t));
#endif
if (n) *buf = '\0';
return 0;
}
-#if HAVE_WCSRTOMBS
+#ifdef HAVE_WCSRTOMBS
return wcsrtombs(buf, &pwz, n, &mbstate);
#else
- return wcstombs(buf, pwz, n);
+ return wxWcstombs(buf, pwz, n);
#endif
}
-#if HAVE_WCSRTOMBS
+#ifdef HAVE_WCSRTOMBS
return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
#else
- return wcstombs((char *) NULL, pwz, 0);
+ return wxWcstombs((char *) NULL, pwz, 0);
#endif
}
#endif // wxUSE_WCHAR_T
(strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
(strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
// nope, don't use libc conversion
- return FALSE;
+ return false;
}
}
#endif
- return TRUE;
+ return true;
}
// ============================================================================
{
static char s_szFlags[256] = "%";
size_t flagofs = 1;
- bool adj_left = FALSE,
- in_prec = FALSE,
- prec_dot = FALSE,
- done = FALSE;
+ bool adj_left = false,
+ in_prec = false,
+ prec_dot = false,
+ done = false;
int ilen = 0;
size_t min_width = 0,
max_width = wxSTRING_MAXLEN;
if (in_prec && !prec_dot) \
{ \
s_szFlags[flagofs++] = '.'; \
- prec_dot = TRUE; \
+ prec_dot = true; \
}
#define APPEND_CH(ch) \
case wxT('\0'):
APPEND_CH(_T('\0'));
- done = TRUE;
+ done = true;
break;
case wxT('%'):
APPEND_CH(_T('%'));
- done = TRUE;
+ done = true;
break;
case wxT('#'):
case wxT('-'):
CHECK_PREC
- adj_left = TRUE;
+ adj_left = true;
s_szFlags[flagofs++] = ch;
break;
case wxT('.'):
CHECK_PREC
- in_prec = TRUE;
- prec_dot = FALSE;
+ in_prec = true;
+ prec_dot = false;
max_width = 0;
// dot will be auto-added to s_szFlags if non-negative
// number follows
APPEND_STR(tmp);
}
- done = TRUE;
+ done = true;
break;
case wxT('e'):
APPEND_STR(tmp);
}
- done = TRUE;
+ done = true;
break;
case wxT('p'):
wxConvLibc.cMB2WX(szScratch);
APPEND_STR(tmp);
- done = TRUE;
+ done = true;
}
break;
for (i = 1; i < min_width; i++)
APPEND_CH(_T(' '));
- done = TRUE;
+ done = true;
}
break;
}
else
{
- val = wxT("");
+ val = wxEmptyString;
len = 0;
}
for (i = len; i < min_width; i++)
APPEND_CH(_T(' '));
- done = TRUE;
+ done = true;
}
break;
long int *val = va_arg(argptr, long int *);
*val = lenCur;
}
- done = TRUE;
+ done = true;
break;
default:
// bad format, leave unchanged
APPEND_CH(_T('%'));
APPEND_CH(ch);
- done = TRUE;
+ done = true;
break;
}
}
// implement the standard IO functions for wide char if libc doesn't have them
// ----------------------------------------------------------------------------
-#ifdef wxNEED_FPUTWC
-
+#ifdef wxNEED_FPUTS
int wxFputs(const wchar_t *ws, FILE *stream)
{
// counting the number of wide characters written isn't worth the trouble,
// simply distinguish between ok and error
return fputs(wxConvLibc.cWC2MB(ws), stream) == -1 ? -1 : 0;
}
+#endif // wxNEED_FPUTS
+
+#ifdef wxNEED_PUTS
+int wxPuts(const wxChar *ws)
+{
+ int rc = wxFputs(ws, stdout);
+ if ( rc != -1 )
+ {
+ if ( wxFputs(L"\n", stdout) == -1 )
+ return -1;
+
+ rc++;
+ }
+
+ return rc;
+}
+#endif // wxNEED_PUTS
+#ifdef wxNEED_PUTC
int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
{
wchar_t ws[2] = { wc, L'\0' };
return wxFputs(ws, stream);
}
-
-#endif // wxNEED_FPUTWC
+#endif // wxNEED_PUTC
// NB: we only implement va_list functions here, the ones taking ... are
// defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr)
{
- wxFAIL_MSG( _T("TODO") );
-
- return -1;
+ // 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, _T("%s")) == NULL, -1,
+ _T("incomplete vswscanf implementation doesn't allow %s") );
+ 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);
}
int vfwscanf(FILE *stream, const wxChar *format, va_list argptr)
So to use native functions in order to get our semantics we must do the
following translations in Unicode mode (nothing to do in ANSI mode):
- wxWindows specifier POSIX specifier
+ wxWidgets specifier POSIX specifier
----------------------------------------
%hc, %C, %hC %c
WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
#endif
+#ifdef wxNEED_WX_MBSTOWCS
+
+WXDLLEXPORT 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;
+}
+
+WXDLLEXPORT 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
+
+#if defined(wxNEED_WX_CTYPE_H)
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
+#define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
+#define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
+#define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
+//CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
+#define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
+//CFCharacterSetRef cfprintset = !kCFCharacterSetControl
+#define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
+#define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
+#define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
+
+WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
+WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
+WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
+WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
+WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
+WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
+WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
+WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
+WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
+WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
+WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
+WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
+WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
+
+#endif // wxNEED_WX_CTYPE_H
+
#ifndef wxStrdupA
WXDLLEXPORT char *wxStrdupA(const char *s)
#ifndef wxSetlocale
WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
{
- char *localeOld = setlocale(category, wxConvLocal.cWX2MB(locale));
+ char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
+
+ return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
+}
+#endif
+
+#if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
+WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
+{
+ size_t n = 0;
+ while ( *s++ )
+ n++;
- return wxWCharBuffer(wxConvLocal.cMB2WC(localeOld));
+ return n;
}
#endif
// ----------------------------------------------------------------------------
#ifdef wxNEED_WX_STRING_H
+
+// RN: These need to be c externed for the regex lib
+#ifdef __cplusplus
+extern "C" {
+#endif
+
WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
{
wxChar *ret = dest;
return ret;
}
+WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
+{
+ size_t n = 0;
+ while ( *s++ )
+ n++;
+
+ return n;
+}
+
+
WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
{
wxChar *ret = dest;
WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
{
- wxCHECK_RET( needle, NULL, _T("NULL argument in wxStrstr") );
+ wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
// VZ: this is not exactly the most efficient string search algorithm...
return NULL;
}
+#ifdef __cplusplus
+}
+#endif
+
WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
{
const wxChar *start = nptr;
}
wxString data(nptr, nptr-start);
- wxWX2MBbuf dat = data.mb_str(wxConvLocal);
+ wxWX2MBbuf dat = data.mb_str(wxConvLibc);
char *rdat = wxMBSTRINGCAST dat;
double ret = strtod(dat, &rdat);
while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
(wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
- wxString data(nptr, nptr-start);
- wxWX2MBbuf dat = data.mb_str(wxConvLocal);
+ wxString data(start, nptr-start);
+ wxWX2MBbuf dat = data.mb_str(wxConvLibc);
char *rdat = wxMBSTRINGCAST dat;
long int ret = strtol(dat, &rdat, base);
return ret;
}
+
+WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
+{
+ return (unsigned long int) wxStrtol(nptr, endptr, base);
+}
+
#endif // wxNEED_WX_STRING_H
#ifdef wxNEED_WX_STDIO_H
wxString str(psz);
if (str.ToDouble(& d))
return d;
- else
- return 0.0;
+
+ return 0.0;
#else
- return atof(wxConvLocal.cWX2MB(psz));
+ return atof(wxConvLibc.cWX2MB(psz));
#endif
}
#endif
#ifdef wxNEED_WX_STDLIB_H
int WXDLLEXPORT wxAtoi(const wxChar *psz)
{
- return atoi(wxConvLocal.cWX2MB(psz));
+ return atoi(wxConvLibc.cWX2MB(psz));
}
long WXDLLEXPORT wxAtol(const wxChar *psz)
{
- return atol(wxConvLocal.cWX2MB(psz));
+ return atol(wxConvLibc.cWX2MB(psz));
}
wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
{
- static wxHashTable env;
-
- // check if we already have stored the converted env var
- wxObject *data = env.Get(name);
- if (!data)
- {
- // nope, retrieve it,
#if wxUSE_UNICODE
- wxCharBuffer buffer = wxConvLocal.cWX2MB(name);
- // printf( "buffer %s\n", (const char*) buffer );
- const char *val = getenv( (const char *)buffer );
+ // 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((wxChar*)NULL);
+ value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
+ return value.data();
#else
- const char *val = getenv( name );
+ return getenv(name);
#endif
-
- if (!val) return (wxChar *)NULL;
- // printf( "home %s\n", val );
-
- // convert it,
-#if wxUSE_UNICODE
- data = (wxObject *)new wxString(val, wxConvLocal);
-#else
- data = (wxObject *)new wxString(val);
-#endif
-
- // and store it
- env.Put(name, data);
- }
- // return converted env var
- return (wxChar *)((wxString *)data)->c_str();
}
int WXDLLEXPORT wxSystem(const wxChar *psz)
{
- return system(wxConvLocal.cWX2MB(psz));
+ return system(wxConvLibc.cWX2MB(psz));
}
#endif // wxNEED_WX_STDLIB_H
#ifdef wxNEED_WX_TIME_H
-WXDLLEXPORT size_t wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const struct tm *tm)
+WXDLLEXPORT size_t
+wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
{
- if (!max) return 0;
+ if ( !maxsize )
+ return 0;
- char *buf = (char *)malloc(max);
- size_t ret = strftime(buf, max, wxConvLocal.cWX2MB(fmt), tm);
- if (ret)
- {
- wxStrcpy(s, wxConvLocal.cMB2WX(buf));
- free(buf);
- return wxStrlen(s);
- }
- else
- {
- free(buf);
- *s = 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;
+
+ wxStrncpy(s, wbuf, maxsize);
+ return wxStrlen(s);
}
#endif // wxNEED_WX_TIME_H
#ifndef wxCtime
WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
{
- static wxChar buf[128];
+ // normally the string is 26 chars but give one more in case some broken
+ // DOS compiler decides to use "\r\n" instead of "\n" at the end
+ static wxChar buf[27];
- wxStrncpy( buf, wxConvertMB2WX( ctime( timep ) ), sizeof( buf ) );
- buf[ sizeof( buf ) - 1 ] = _T('\0');
+ // ctime() is guaranteed to return a string containing only ASCII
+ // characters, as its format is always the same for any locale
+ wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
+ buf[WXSIZEOF(buf) - 1] = _T('\0');
return buf;
}
// missing C RTL functions
// ----------------------------------------------------------------------------
-#if (defined(__MWERKS__) && !defined(__MACH__) && (__MSL__ < 0x00008000)) || \
- defined(__WXWINCE__)
+#ifdef wxNEED_STRDUP
+
char *strdup(const char *s)
{
char *dest = (char*) malloc( strlen( s ) + 1 ) ;
strcpy( dest , s ) ;
return dest ;
}
-#endif
-
-#if (defined(__MWERKS__) && !defined(__MACH__)) || (defined(__WXWINCE__) && _WIN32_WCE <= 211)
-
-int isascii( int c )
-{
- return ( c >= 0 && c < 128 );
-}
-#endif
+#endif // wxNEED_STRDUP
#if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
-#if (_WIN32_WCE < 300)
+
void *calloc( size_t num, size_t size )
{
void** ptr = (void **)malloc(num * size);
memset( ptr, 0, num * size);
return ptr;
}
-#endif
-int isspace(int c)
+#endif // __WXWINCE__ <= 211
+
+#ifdef __WXWINCE__
+
+int wxRemove(const wxChar *path)
{
- return (c == ' ');
+ return ::DeleteFile(path) == 0;
}
#endif
-