1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxChar implementation 
   5 // Modified by: Ron Lee 
   8 // Copyright:   (c) wxWindows copyright 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13   #pragma implementation "wxchar.h" 
  16 // =========================================================================== 
  17 // headers, declarations, constants 
  18 // =========================================================================== 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #define _ISOC9X_SOURCE 1 // to get vsscanf() 
  28 #define _BSD_SOURCE    1 // to still get strdup() 
  38 #include "wx/msw/wince/time.h" 
  43   #include "wx/wxchar.h" 
  44   #include "wx/string.h" 
  48 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H) 
  55 #if defined(__MWERKS__) && __MSL__ >= 0x6000 
  60     #include "wx/mac/private.h" 
  64 size_t WXDLLEXPORT 
wxMB2WC(wchar_t *buf
, const char *psz
, size_t n
) 
  66   // assume that we have mbsrtowcs() too if we have wcsrtombs() 
  69   memset(&mbstate
, 0, sizeof(mbstate_t)); 
  74       if (n
) *buf 
= wxT('\0'); 
  78     return mbsrtowcs(buf
, &psz
, n
, &mbstate
); 
  80     return mbstowcs(buf
, psz
, n
); 
  85   return mbsrtowcs((wchar_t *) NULL
, &psz
, 0, &mbstate
); 
  87   return mbstowcs((wchar_t *) NULL
, psz
, 0); 
  91 size_t WXDLLEXPORT 
wxWC2MB(char *buf
, const wchar_t *pwz
, size_t n
) 
  95   memset(&mbstate
, 0, sizeof(mbstate_t)); 
 100       // glibc2.1 chokes on null input 
 105     return wcsrtombs(buf
, &pwz
, n
, &mbstate
); 
 107     return wcstombs(buf
, pwz
, n
); 
 112   return wcsrtombs((char *) NULL
, &pwz
, 0, &mbstate
); 
 114   return wcstombs((char *) NULL
, pwz
, 0); 
 117 #endif // wxUSE_WCHAR_T 
 119 bool WXDLLEXPORT 
wxOKlibc() 
 121 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__) 
 122   // glibc 2.0 uses UTF-8 even when it shouldn't 
 124   if ((MB_CUR_MAX 
== 2) && 
 125       (wxMB2WC(&res
, "\xdd\xa5", 1) == 1) && 
 127     // this is UTF-8 allright, check whether that's what we want 
 128     char *cur_locale 
= setlocale(LC_CTYPE
, NULL
); 
 129     if ((strlen(cur_locale
) < 4) || 
 130             (strcasecmp(cur_locale 
+ strlen(cur_locale
) - 4, "utf8")) || 
 131             (strcasecmp(cur_locale 
+ strlen(cur_locale
) - 5, "utf-8"))) { 
 132       // nope, don't use libc conversion 
 140 // ============================================================================ 
 141 // printf() functions business 
 142 // ============================================================================ 
 144 // special test mode: define all functions below even if we don't really need 
 145 // them to be able to test them 
 156     #define wxNEED_WPRINTF 
 158     int wxVfprintf( FILE *stream
, const wxChar 
*format
, va_list argptr 
); 
 161 // ---------------------------------------------------------------------------- 
 162 // implement [v]snprintf() if the system doesn't provide a safe one 
 163 // ---------------------------------------------------------------------------- 
 165 #if !defined(wxVsnprintf_) 
 166 int WXDLLEXPORT 
wxVsnprintf_(wxChar 
*buf
, size_t lenMax
, 
 167                              const wxChar 
*format
, va_list argptr
) 
 169     // buffer to avoid dynamic memory allocation each time for small strings 
 170     char szScratch
[1024]; 
 172     // number of characters in the buffer so far, must be less than lenMax 
 175     for ( size_t n 
= 0; ; n
++ ) 
 177         const wxChar chCur 
= format
[n
]; 
 179         if ( chCur 
== wxT('%') ) 
 181             static char s_szFlags
[256] = "%"; 
 183             bool adj_left 
= FALSE
, 
 188             size_t min_width 
= 0, 
 189                    max_width 
= wxSTRING_MAXLEN
; 
 194                 if (in_prec && !prec_dot) \ 
 196                     s_szFlags[flagofs++] = '.'; \ 
 200 #define APPEND_CH(ch) \ 
 202                     if ( lenCur == lenMax ) \ 
 205                     buf[lenCur++] = ch; \ 
 208 #define APPEND_STR(s) \ 
 210                     for ( const wxChar *p = s; *p; p++ ) \ 
 217                 const wxChar ch 
= format
[++n
]; 
 237                         s_szFlags
[flagofs
++] = ch
; 
 243                         s_szFlags
[flagofs
++] = ch
; 
 251                         // dot will be auto-added to s_szFlags if non-negative 
 258                         s_szFlags
[flagofs
++] = ch
; 
 264                         s_szFlags
[flagofs
++] = ch
; 
 271                         s_szFlags
[flagofs
++] = ch
; 
 277                         s_szFlags
[flagofs
++] = ch
; 
 282                             int len 
= va_arg(argptr
, int); 
 293                                     adj_left 
= !adj_left
; 
 294                                     s_szFlags
[flagofs
++] = '-'; 
 299                             flagofs 
+= ::sprintf(s_szFlags
+flagofs
,"%d",len
); 
 303                     case wxT('1'): case wxT('2'): case wxT('3'): 
 304                     case wxT('4'): case wxT('5'): case wxT('6'): 
 305                     case wxT('7'): case wxT('8'): case wxT('9'): 
 309                             while ( (format
[n
] >= wxT('0')) && 
 310                                     (format
[n
] <= wxT('9')) ) 
 312                                 s_szFlags
[flagofs
++] = format
[n
]; 
 313                                 len 
= len
*10 + (format
[n
] - wxT('0')); 
 322                             n
--; // the main loop pre-increments n again 
 333                         s_szFlags
[flagofs
++] = ch
; 
 334                         s_szFlags
[flagofs
] = '\0'; 
 337                             int val 
= va_arg(argptr
, int); 
 338                             ::sprintf(szScratch
, s_szFlags
, val
); 
 342                             // NB: 'short int' value passed through '...' 
 343                             //      is promoted to 'int', so we have to get 
 344                             //      an int from stack even if we need a short 
 345                             short int val 
= (short int) va_arg(argptr
, int); 
 346                             ::sprintf(szScratch
, s_szFlags
, val
); 
 350                             long int val 
= va_arg(argptr
, long int); 
 351                             ::sprintf(szScratch
, s_szFlags
, val
); 
 356                             long long int val 
= va_arg(argptr
, long long int); 
 357                             ::sprintf(szScratch
, s_szFlags
, val
); 
 359                             long int val 
= va_arg(argptr
, long int); 
 360                             ::sprintf(szScratch
, s_szFlags
, val
); 
 361 #endif // long long/!long long 
 365                             size_t val 
= va_arg(argptr
, size_t); 
 366                             ::sprintf(szScratch
, s_szFlags
, val
); 
 370                             const wxMB2WXbuf tmp 
= 
 371                                 wxConvLibc
.cMB2WX(szScratch
); 
 384                         s_szFlags
[flagofs
++] = ch
; 
 385                         s_szFlags
[flagofs
] = '\0'; 
 388                             long double val 
= va_arg(argptr
, long double); 
 389                             ::sprintf(szScratch
, s_szFlags
, val
); 
 393                             double val 
= va_arg(argptr
, double); 
 394                             ::sprintf(szScratch
, s_szFlags
, val
); 
 398                             const wxMB2WXbuf tmp 
= 
 399                                 wxConvLibc
.cMB2WX(szScratch
); 
 408                             void *val 
= va_arg(argptr
, void *); 
 410                             s_szFlags
[flagofs
++] = ch
; 
 411                             s_szFlags
[flagofs
] = '\0'; 
 412                             ::sprintf(szScratch
, s_szFlags
, val
); 
 414                             const wxMB2WXbuf tmp 
= 
 415                                 wxConvLibc
.cMB2WX(szScratch
); 
 424                             int val 
= va_arg(argptr
, int); 
 428                                 const char buf
[2] = { val
, 0 }; 
 429                                 val 
= wxString(buf
, wxConvLibc
)[0u]; 
 434                                 const wchar_t buf
[2] = { val
, 0 }; 
 435                                 val 
= wxString(buf
, wxConvLibc
)[0u]; 
 441                                 for (i 
= 1; i 
< min_width
; i
++) 
 447                                 for (i 
= 1; i 
< min_width
; i
++) 
 456                             const wxChar 
*val 
= NULL
; 
 462                                 // wx extension: we'll let %hs mean non-Unicode 
 464                                 char *v 
= va_arg(argptr
, char *); 
 467                                     val 
= s 
= wxString(v
, wxConvLibc
); 
 475                                 // %ls means Unicode strings 
 476                                 wchar_t *v 
= va_arg(argptr
, wchar_t *); 
 479                                     val 
= s 
= wxString(v
, wxConvLibc
); 
 484                                 val 
= va_arg(argptr
, wxChar 
*); 
 492                                       val
[len
] && (len 
< max_width
); 
 496                             else if (max_width 
>= 6) 
 510                                 for (i 
= len
; i 
< min_width
; i
++) 
 513                             for (i 
= 0; i 
< len
; i
++) 
 517                                 for (i 
= len
; i 
< min_width
; i
++) 
 527                             int *val 
= va_arg(argptr
, int *); 
 532                             short int *val 
= va_arg(argptr
, short int *); 
 537                             long int *val 
= va_arg(argptr
, long int *); 
 544                         // bad format, leave unchanged 
 570 #endif // !wxVsnprintfA 
 572 #if !defined(wxSnprintf_) 
 573 int WXDLLEXPORT 
wxSnprintf_(wxChar 
*buf
, size_t len
, const wxChar 
*format
, ...) 
 576     va_start(argptr
, format
); 
 578     int iLen 
= wxVsnprintf_(buf
, len
, format
, argptr
); 
 584 #endif // wxSnprintf_ 
 587     /* Digital Mars adds count to _stprintf (C99) so convert */ 
 589         int wxSprintf (wchar_t * __RESTRICT s
, const wchar_t * __RESTRICT format
, ... ) 
 593             va_start( arglist
, format 
); 
 594             int iLen 
= swprintf ( s
, -1, format
, arglist 
); 
 599     #endif // wxUSE_UNICODE 
 603 // ---------------------------------------------------------------------------- 
 604 // implement the standard IO functions for wide char if libc doesn't have them 
 605 // ---------------------------------------------------------------------------- 
 609 int wxFputs(const wchar_t *ws
, FILE *stream
) 
 611     // counting the number of wide characters written isn't worth the trouble, 
 612     // simply distinguish between ok and error 
 613     return fputs(wxConvLibc
.cWC2MB(ws
), stream
) == -1 ? -1 : 0; 
 616 int /* not wint_t */ wxPutc(wchar_t wc
, FILE *stream
) 
 618     wchar_t ws
[2] = { wc
, L
'\0' }; 
 620     return wxFputs(ws
, stream
); 
 623 #endif // wxNEED_FPUTWC 
 625 // NB: we only implement va_list functions here, the ones taking ... are 
 626 //     defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse 
 627 //     the definitions there to avoid duplicating them here 
 628 #ifdef wxNEED_WPRINTF 
 630 // TODO: implement the scanf() functions 
 631 int vwscanf(const wxChar 
*format
, va_list argptr
) 
 633     wxFAIL_MSG( _T("TODO") ); 
 638 int vswscanf(const wxChar 
*ws
, const wxChar 
*format
, va_list argptr
) 
 640     wxFAIL_MSG( _T("TODO") ); 
 645 int vfwscanf(FILE *stream
, const wxChar 
*format
, va_list argptr
) 
 647     wxFAIL_MSG( _T("TODO") ); 
 652 #define vswprintf wxVsnprintf_ 
 654 int vfwprintf(FILE *stream
, const wxChar 
*format
, va_list argptr
) 
 657     int rc 
= s
.PrintfV(format
, argptr
); 
 661         // we can't do much better without Unicode support in libc... 
 662         if ( fprintf(stream
, "%s", (const char*)s
.mb_str() ) == -1 ) 
 669 int vwprintf(const wxChar 
*format
, va_list argptr
) 
 671     return wxVfprintf(stdout
, format
, argptr
); 
 674 #endif // wxNEED_WPRINTF 
 676 #ifdef wxNEED_PRINTF_CONVERSION 
 678 // ---------------------------------------------------------------------------- 
 679 // wxFormatConverter: class doing the "%s" -> "%ls" conversion 
 680 // ---------------------------------------------------------------------------- 
 683    Here are the gory details. We want to follow the Windows/MS conventions, 
 688    format specifier         results in 
 689    ----------------------------------- 
 695    format specifier         results in 
 696    ----------------------------------- 
 701    while on POSIX systems we have %C identical to %lc and %c always means char 
 702    (in any mode) while %lc always means wchar_t, 
 704    So to use native functions in order to get our semantics we must do the 
 705    following translations in Unicode mode (nothing to do in ANSI mode): 
 707    wxWindows specifier      POSIX specifier 
 708    ---------------------------------------- 
 714    And, of course, the same should be done for %s as well. 
 717 class wxFormatConverter
 
 720     wxFormatConverter(const wxChar 
*format
); 
 722     // notice that we only translated the string if m_fmtOrig == NULL (as set 
 723     // by CopyAllBefore()), otherwise we should simply use the original format 
 724     operator const wxChar 
*() const 
 725         { return m_fmtOrig 
? m_fmtOrig 
: m_fmt
.c_str(); } 
 728     // copy another character to the translated format: this function does the 
 729     // copy if we are translating but doesn't do anything at all if we don't, 
 730     // so we don't create the translated format string at all unless we really 
 731     // need to (i.e. InsertFmtChar() is called) 
 732     wxChar 
CopyFmtChar(wxChar ch
) 
 736             // we're translating, do copy 
 741             // simply increase the count which should be copied by 
 742             // CopyAllBefore() later if needed 
 749     // insert an extra character 
 750     void InsertFmtChar(wxChar ch
) 
 754             // so far we haven't translated anything yet 
 763         wxASSERT_MSG( m_fmtOrig 
&& m_fmt
.empty(), _T("logic error") ); 
 765         m_fmt 
= wxString(m_fmtOrig
, m_nCopied
); 
 767         // we won't need it any longer 
 771     static bool IsFlagChar(wxChar ch
) 
 773         return ch 
== _T('-') || ch 
== _T('+') || 
 774                ch 
== _T('0') || ch 
== _T(' ') || ch 
== _T('#'); 
 777     void SkipDigits(const wxChar 
**ppc
) 
 779         while ( **ppc 
>= _T('0') && **ppc 
<= _T('9') ) 
 780             CopyFmtChar(*(*ppc
)++); 
 783     // the translated format 
 786     // the original format 
 787     const wxChar 
*m_fmtOrig
; 
 789     // the number of characters already copied 
 793 wxFormatConverter::wxFormatConverter(const wxChar 
*format
) 
 800         if ( CopyFmtChar(*format
++) == _T('%') ) 
 803             while ( IsFlagChar(*format
) ) 
 804                 CopyFmtChar(*format
++); 
 806             // and possible width 
 807             if ( *format 
== _T('*') ) 
 808                 CopyFmtChar(*format
++); 
 813             if ( *format 
== _T('.') ) 
 815                 CopyFmtChar(*format
++); 
 816                 if ( *format 
== _T('*') ) 
 817                     CopyFmtChar(*format
++); 
 822             // next we can have a size modifier 
 838                     // "ll" has a different meaning! 
 839                     if ( format
[1] != _T('l') ) 
 851             // and finally we should have the type 
 856                     // %C and %hC -> %c and %lC -> %lc 
 858                         CopyFmtChar(_T('l')); 
 860                     InsertFmtChar(*format
++ == _T('C') ? _T('c') : _T('s')); 
 865                     // %c -> %lc but %hc stays %hc and %lc is still %lc 
 866                     if ( size 
== Default
) 
 867                         InsertFmtChar(_T('l')); 
 871                     // nothing special to do 
 872                     if ( size 
!= Default 
) 
 873                         CopyFmtChar(*(format 
- 1)); 
 874                     CopyFmtChar(*format
++); 
 880 #else // !wxNEED_PRINTF_CONVERSION 
 881     // no conversion necessary 
 882     #define wxFormatConverter(x) (x) 
 883 #endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION 
 886 // For testing the format converter 
 887 wxString 
wxConvertFormat(const wxChar 
*format
) 
 889     return wxString(wxFormatConverter(format
)); 
 893 // ---------------------------------------------------------------------------- 
 894 // wxPrintf(), wxScanf() and relatives 
 895 // ---------------------------------------------------------------------------- 
 897 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF) 
 899 int wxScanf( const wxChar 
*format
, ... ) 
 902     va_start(argptr
, format
); 
 904     int ret 
= vwscanf(wxFormatConverter(format
), argptr 
); 
 911 int wxSscanf( const wxChar 
*str
, const wxChar 
*format
, ... ) 
 914     va_start(argptr
, format
); 
 916     int ret 
= vswscanf( str
, wxFormatConverter(format
), argptr 
); 
 923 int wxFscanf( FILE *stream
, const wxChar 
*format
, ... ) 
 926     va_start(argptr
, format
); 
 927     int ret 
= vfwscanf(stream
, wxFormatConverter(format
), argptr
); 
 934 int wxPrintf( const wxChar 
*format
, ... ) 
 937     va_start(argptr
, format
); 
 939     int ret 
= vwprintf( wxFormatConverter(format
), argptr 
); 
 947 int wxSnprintf( wxChar 
*str
, size_t size
, const wxChar 
*format
, ... ) 
 950     va_start(argptr
, format
); 
 952     int ret 
= vswprintf( str
, size
, wxFormatConverter(format
), argptr 
); 
 960 int wxSprintf( wxChar 
*str
, const wxChar 
*format
, ... ) 
 963     va_start(argptr
, format
); 
 965     // note that wxString::Format() uses wxVsnprintf(), not wxSprintf(), so 
 966     // it's safe to implement this one in terms of it 
 967     wxString 
s(wxString::Format(format
, argptr
)); 
 975 int wxFprintf( FILE *stream
, const wxChar 
*format
, ... ) 
 978     va_start( argptr
, format 
); 
 980     int ret 
= vfwprintf( stream
, wxFormatConverter(format
), argptr 
); 
 987 int wxVsscanf( const wxChar 
*str
, const wxChar 
*format
, va_list argptr 
) 
 989     return vswscanf( str
, wxFormatConverter(format
), argptr 
); 
 992 int wxVfprintf( FILE *stream
, const wxChar 
*format
, va_list argptr 
) 
 994     return vfwprintf( stream
, wxFormatConverter(format
), argptr 
); 
 997 int wxVprintf( const wxChar 
*format
, va_list argptr 
) 
 999     return vwprintf( wxFormatConverter(format
), argptr 
); 
1003 int wxVsnprintf( wxChar 
*str
, size_t size
, const wxChar 
*format
, va_list argptr 
) 
1005     return vswprintf( str
, size
, wxFormatConverter(format
), argptr 
); 
1007 #endif // wxVsnprintf 
1009 int wxVsprintf( wxChar 
*str
, const wxChar 
*format
, va_list argptr 
) 
1011     // same as for wxSprintf() 
1012     return vswprintf(str
, INT_MAX 
/ 4, wxFormatConverter(format
), argptr
); 
1015 #endif // wxNEED_PRINTF_CONVERSION 
1019 // ---------------------------------------------------------------------------- 
1020 // ctype.h stuff (currently unused) 
1021 // ---------------------------------------------------------------------------- 
1023 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H) 
1024 inline WORD 
wxMSW_ctype(wxChar ch
) 
1027   GetStringTypeEx(LOCALE_USER_DEFAULT
, CT_CTYPE1
, &ch
, 1, &ret
); 
1031 WXDLLEXPORT 
int wxIsalnum(wxChar ch
) { return IsCharAlphaNumeric(ch
); } 
1032 WXDLLEXPORT 
int wxIsalpha(wxChar ch
) { return IsCharAlpha(ch
); } 
1033 WXDLLEXPORT 
int wxIscntrl(wxChar ch
) { return wxMSW_ctype(ch
) & C1_CNTRL
; } 
1034 WXDLLEXPORT 
int wxIsdigit(wxChar ch
) { return wxMSW_ctype(ch
) & C1_DIGIT
; } 
1035 WXDLLEXPORT 
int wxIsgraph(wxChar ch
) { return wxMSW_ctype(ch
) & (C1_DIGIT
|C1_PUNCT
|C1_ALPHA
); } 
1036 WXDLLEXPORT 
int wxIslower(wxChar ch
) { return IsCharLower(ch
); } 
1037 WXDLLEXPORT 
int wxIsprint(wxChar ch
) { return wxMSW_ctype(ch
) & (C1_DIGIT
|C1_SPACE
|C1_PUNCT
|C1_ALPHA
); } 
1038 WXDLLEXPORT 
int wxIspunct(wxChar ch
) { return wxMSW_ctype(ch
) & C1_PUNCT
; } 
1039 WXDLLEXPORT 
int wxIsspace(wxChar ch
) { return wxMSW_ctype(ch
) & C1_SPACE
; } 
1040 WXDLLEXPORT 
int wxIsupper(wxChar ch
) { return IsCharUpper(ch
); } 
1041 WXDLLEXPORT 
int wxIsxdigit(wxChar ch
) { return wxMSW_ctype(ch
) & C1_XDIGIT
; } 
1042 WXDLLEXPORT 
int wxTolower(wxChar ch
) { return (wxChar
)CharLower((LPTSTR
)(ch
)); } 
1043 WXDLLEXPORT 
int wxToupper(wxChar ch
) { return (wxChar
)CharUpper((LPTSTR
)(ch
)); } 
1048 WXDLLEXPORT 
char *wxStrdupA(const char *s
) 
1050     return strcpy((char *)malloc(strlen(s
) + 1), s
); 
1057 WXDLLEXPORT 
wchar_t * wxStrdupW(const wchar_t *pwz
) 
1059   size_t size 
= (wxWcslen(pwz
) + 1) * sizeof(wchar_t); 
1060   wchar_t *ret 
= (wchar_t *) malloc(size
); 
1061   memcpy(ret
, pwz
, size
); 
1068 int WXDLLEXPORT 
wxStricmp(const wxChar 
*psz1
, const wxChar 
*psz2
) 
1070   register wxChar c1
, c2
; 
1072     c1 
= wxTolower(*psz1
++); 
1073     c2 
= wxTolower(*psz2
++); 
1074   } while ( c1 
&& (c1 
== c2
) ); 
1080 int WXDLLEXPORT 
wxStrnicmp(const wxChar 
*s1
, const wxChar 
*s2
, size_t n
) 
1082   // initialize the variables just to suppress stupid gcc warning 
1083   register wxChar c1 
= 0, c2 
= 0; 
1084   while (n 
&& ((c1 
= wxTolower(*s1
)) == (c2 
= wxTolower(*s2
)) ) && c1
) n
--, s1
++, s2
++; 
1086     if (c1 
< c2
) return -1; 
1087     if (c1 
> c2
) return 1; 
1094 WXDLLEXPORT wxWCharBuffer 
wxSetlocale(int category
, const wxChar 
*locale
) 
1096     char *localeOld 
= setlocale(category
, wxConvLocal
.cWX2MB(locale
)); 
1098     return wxWCharBuffer(wxConvLocal
.cMB2WC(localeOld
)); 
1102 // ---------------------------------------------------------------------------- 
1103 // string.h functions 
1104 // ---------------------------------------------------------------------------- 
1106 #ifdef wxNEED_WX_STRING_H 
1107 WXDLLEXPORT wxChar 
* wxStrcat(wxChar 
*dest
, const wxChar 
*src
) 
1110   while (*dest
) dest
++; 
1111   while ((*dest
++ = *src
++)); 
1115 WXDLLEXPORT 
const wxChar 
* wxStrchr(const wxChar 
*s
, wxChar c
) 
1117     // be careful here as the terminating NUL makes part of the string 
1127 WXDLLEXPORT 
int wxStrcmp(const wxChar 
*s1
, const wxChar 
*s2
) 
1129   while ((*s1 
== *s2
) && *s1
) s1
++, s2
++; 
1130   if ((wxUChar
)*s1 
< (wxUChar
)*s2
) return -1; 
1131   if ((wxUChar
)*s1 
> (wxUChar
)*s2
) return 1; 
1135 WXDLLEXPORT wxChar 
* wxStrcpy(wxChar 
*dest
, const wxChar 
*src
) 
1138   while ((*dest
++ = *src
++)); 
1142 WXDLLEXPORT wxChar 
* wxStrncat(wxChar 
*dest
, const wxChar 
*src
, size_t n
) 
1145   while (*dest
) dest
++; 
1146   while (n 
&& (*dest
++ = *src
++)) n
--; 
1150 WXDLLEXPORT 
int wxStrncmp(const wxChar 
*s1
, const wxChar 
*s2
, size_t n
) 
1152   while (n 
&& (*s1 
== *s2
) && *s1
) n
--, s1
++, s2
++; 
1154     if ((wxUChar
)*s1 
< (wxUChar
)*s2
) return -1; 
1155     if ((wxUChar
)*s1 
> (wxUChar
)*s2
) return 1; 
1160 WXDLLEXPORT wxChar 
* wxStrncpy(wxChar 
*dest
, const wxChar 
*src
, size_t n
) 
1163   while (n 
&& (*dest
++ = *src
++)) n
--; 
1164   while (n
) *dest
++=0, n
--; // the docs specify padding with zeroes 
1168 WXDLLEXPORT 
const wxChar 
* wxStrpbrk(const wxChar 
*s
, const wxChar 
*accept
) 
1170   while (*s 
&& !wxStrchr(accept
, *s
)) 
1173   return *s 
? s 
: NULL
; 
1176 WXDLLEXPORT 
const wxChar 
* wxStrrchr(const wxChar 
*s
, wxChar c
) 
1178     const wxChar 
*ret 
= NULL
; 
1190 WXDLLEXPORT 
size_t wxStrspn(const wxChar 
*s
, const wxChar 
*accept
) 
1193   while (wxStrchr(accept
, *s
++)) len
++; 
1197 WXDLLEXPORT 
const wxChar 
*wxStrstr(const wxChar 
*haystack
, const wxChar 
*needle
) 
1199     wxCHECK_RET( needle
, NULL
, _T("NULL argument in wxStrstr") ); 
1201     // VZ: this is not exactly the most efficient string search algorithm... 
1203     const size_t len 
= wxStrlen(needle
); 
1205     while ( const wxChar 
*fnd 
= wxStrchr(haystack
, *needle
) ) 
1207         if ( !wxStrncmp(fnd
, needle
, len
) ) 
1216 WXDLLEXPORT 
double wxStrtod(const wxChar 
*nptr
, wxChar 
**endptr
) 
1218   const wxChar 
*start 
= nptr
; 
1220   // FIXME: only correct for C locale 
1221   while (wxIsspace(*nptr
)) nptr
++; 
1222   if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1223   while (wxIsdigit(*nptr
)) nptr
++; 
1224   if (*nptr 
== wxT('.')) { 
1226     while (wxIsdigit(*nptr
)) nptr
++; 
1228   if (*nptr 
== wxT('E') || *nptr 
== wxT('e')) { 
1230     if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1231     while (wxIsdigit(*nptr
)) nptr
++; 
1234   wxString 
data(nptr
, nptr
-start
); 
1235   wxWX2MBbuf dat 
= data
.mb_str(wxConvLocal
); 
1236   char *rdat 
= wxMBSTRINGCAST dat
; 
1237   double ret 
= strtod(dat
, &rdat
); 
1239   if (endptr
) *endptr 
= (wxChar 
*)(start 
+ (rdat 
- (const char *)dat
)); 
1244 WXDLLEXPORT 
long int wxStrtol(const wxChar 
*nptr
, wxChar 
**endptr
, int base
) 
1246   const wxChar 
*start 
= nptr
; 
1248   // FIXME: only correct for C locale 
1249   while (wxIsspace(*nptr
)) nptr
++; 
1250   if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1251   if (((base 
== 0) || (base 
== 16)) && 
1252       (nptr
[0] == wxT('0') && nptr
[1] == wxT('x'))) { 
1256   else if ((base 
== 0) && (nptr
[0] == wxT('0'))) base 
= 8; 
1257   else if (base 
== 0) base 
= 10; 
1259   while ((wxIsdigit(*nptr
) && (*nptr 
- wxT('0') < base
)) || 
1260          (wxIsalpha(*nptr
) && (wxToupper(*nptr
) - wxT('A') + 10 < base
))) nptr
++; 
1262   wxString 
data(nptr
, nptr
-start
); 
1263   wxWX2MBbuf dat 
= data
.mb_str(wxConvLocal
); 
1264   char *rdat 
= wxMBSTRINGCAST dat
; 
1265   long int ret 
= strtol(dat
, &rdat
, base
); 
1267   if (endptr
) *endptr 
= (wxChar 
*)(start 
+ (rdat 
- (const char *)dat
)); 
1271 #endif // wxNEED_WX_STRING_H 
1273 #ifdef wxNEED_WX_STDIO_H 
1274 WXDLLEXPORT 
FILE * wxFopen(const wxChar 
*path
, const wxChar 
*mode
) 
1276     char mode_buffer
[10]; 
1277     for (size_t i 
= 0; i 
< wxStrlen(mode
)+1; i
++) 
1278        mode_buffer
[i
] = (char) mode
[i
]; 
1280     return fopen( wxConvFile
.cWX2MB(path
), mode_buffer 
); 
1283 WXDLLEXPORT 
FILE * wxFreopen(const wxChar 
*path
, const wxChar 
*mode
, FILE *stream
) 
1285     char mode_buffer
[10]; 
1286     for (size_t i 
= 0; i 
< wxStrlen(mode
)+1; i
++) 
1287        mode_buffer
[i
] = (char) mode
[i
]; 
1289     return freopen( wxConvFile
.cWX2MB(path
), mode_buffer
, stream 
); 
1292 WXDLLEXPORT 
int wxRemove(const wxChar 
*path
) 
1294     return remove( wxConvFile
.cWX2MB(path
) ); 
1297 WXDLLEXPORT 
int wxRename(const wxChar 
*oldpath
, const wxChar 
*newpath
) 
1299     return rename( wxConvFile
.cWX2MB(oldpath
), wxConvFile
.cWX2MB(newpath
) ); 
1304 double   WXDLLEXPORT 
wxAtof(const wxChar 
*psz
) 
1309     if (str
.ToDouble(& d
)) 
1314     return atof(wxConvLocal
.cWX2MB(psz
)); 
1319 #ifdef wxNEED_WX_STDLIB_H 
1320 int      WXDLLEXPORT 
wxAtoi(const wxChar 
*psz
) 
1322   return atoi(wxConvLocal
.cWX2MB(psz
)); 
1325 long     WXDLLEXPORT 
wxAtol(const wxChar 
*psz
) 
1327   return atol(wxConvLocal
.cWX2MB(psz
)); 
1330 wxChar 
* WXDLLEXPORT 
wxGetenv(const wxChar 
*name
) 
1332   static wxHashTable env
; 
1334   // check if we already have stored the converted env var 
1335   wxObject 
*data 
= env
.Get(name
); 
1338     // nope, retrieve it, 
1340     wxCharBuffer buffer 
= wxConvLocal
.cWX2MB(name
); 
1341     // printf( "buffer %s\n", (const char*) buffer ); 
1342     const char *val 
= getenv( (const char *)buffer 
); 
1344     const char *val 
= getenv( name 
); 
1347     if (!val
) return (wxChar 
*)NULL
; 
1348     // printf( "home %s\n", val ); 
1352     data 
= (wxObject 
*)new wxString(val
, wxConvLocal
); 
1354     data 
= (wxObject 
*)new wxString(val
); 
1358     env
.Put(name
, data
); 
1360   // return converted env var 
1361   return (wxChar 
*)((wxString 
*)data
)->c_str(); 
1364 int WXDLLEXPORT 
wxSystem(const wxChar 
*psz
) 
1366     return system(wxConvLocal
.cWX2MB(psz
)); 
1369 #endif // wxNEED_WX_STDLIB_H 
1371 #ifdef wxNEED_WX_TIME_H 
1372 WXDLLEXPORT 
size_t   wxStrftime(wxChar 
*s
, size_t max
, const wxChar 
*fmt
, const struct tm 
*tm
) 
1376     char *buf 
= (char *)malloc(max
); 
1377     size_t ret 
= strftime(buf
, max
, wxConvLocal
.cWX2MB(fmt
), tm
); 
1380         wxStrcpy(s
, wxConvLocal
.cMB2WX(buf
)); 
1391 #endif // wxNEED_WX_TIME_H 
1394 WXDLLEXPORT wxChar 
*wxCtime(const time_t *timep
) 
1396     static wxChar   buf
[128]; 
1398     wxStrncpy( buf
, wxConvertMB2WX( ctime( timep 
) ), sizeof( buf 
) ); 
1399     buf
[ sizeof( buf 
) - 1 ] = _T('\0'); 
1405 #endif // wxUSE_WCHAR_T 
1407 // ---------------------------------------------------------------------------- 
1408 // functions which we may need even if !wxUSE_WCHAR_T 
1409 // ---------------------------------------------------------------------------- 
1413 WXDLLEXPORT wxChar 
* wxStrtok(wxChar 
*psz
, const wxChar 
*delim
, wxChar 
**save_ptr
) 
1422     psz 
+= wxStrspn(psz
, delim
); 
1425         *save_ptr 
= (wxChar 
*)NULL
; 
1426         return (wxChar 
*)NULL
; 
1430     psz 
= wxStrpbrk(psz
, delim
); 
1433         *save_ptr 
= (wxChar
*)NULL
; 
1438         *save_ptr 
= psz 
+ 1; 
1446 // ---------------------------------------------------------------------------- 
1447 // missing C RTL functions 
1448 // ---------------------------------------------------------------------------- 
1450 #if (defined(__MWERKS__) && !defined(__MACH__) && (__MSL__ < 0x00008000)) || \ 
1451      defined(__WXWINCE__) 
1452 char *strdup(const char *s
) 
1454     char *dest 
= (char*) malloc( strlen( s 
) + 1 ) ; 
1456         strcpy( dest 
, s 
) ; 
1461 #if (defined(__MWERKS__) && !defined(__MACH__)) || (defined(__WXWINCE__) && _WIN32_WCE <= 211) 
1463 int isascii( int c 
) 
1465     return ( c 
>= 0 && c 
< 128 ); 
1469 #if defined(__WXWINCE__) && (_WIN32_WCE <= 211) 
1470 #if (_WIN32_WCE < 300) 
1471 void *calloc( size_t num
, size_t size 
) 
1473     void** ptr 
= (void **)malloc(num 
* size
); 
1474     memset( ptr
, 0, num 
* size
);