1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxChar implementation 
   8 // Copyright:   (c) wxWindows copyright 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  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/wxchar.h" 
  39   #include "wx/string.h" 
  43 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H) 
  51 size_t WXDLLEXPORT 
wxMB2WC(wchar_t *buf
, const char *psz
, size_t n
) 
  53   // assume that we have mbsrtowcs() too if we have wcsrtombs() 
  56   memset(&mbstate
, 0, sizeof(mbstate_t)); 
  61       if (n
) *buf 
= wxT('\0'); 
  65     return mbsrtowcs(buf
, &psz
, n
, &mbstate
); 
  67     return mbstowcs(buf
, psz
, n
); 
  72   return mbsrtowcs((wchar_t *) NULL
, &psz
, 0, &mbstate
); 
  74   return mbstowcs((wchar_t *) NULL
, psz
, 0); 
  78 size_t WXDLLEXPORT 
wxWC2MB(char *buf
, const wchar_t *pwz
, size_t n
) 
  82   memset(&mbstate
, 0, sizeof(mbstate_t)); 
  87       // glibc2.1 chokes on null input 
  92     return wcsrtombs(buf
, &pwz
, n
, &mbstate
); 
  94     return wcstombs(buf
, pwz
, n
); 
  99   return wcsrtombs((char *) NULL
, &pwz
, 0, &mbstate
); 
 101   return wcstombs((char *) NULL
, pwz
, 0); 
 104 #endif // wxUSE_WCHAR_T 
 106 bool WXDLLEXPORT 
wxOKlibc() 
 108 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__) 
 109   // glibc 2.0 uses UTF-8 even when it shouldn't 
 111   if ((MB_CUR_MAX 
== 2) && 
 112       (wxMB2WC(&res
, "\xdd\xa5", 1) == 1) && 
 114     // this is UTF-8 allright, check whether that's what we want 
 115     char *cur_locale 
= setlocale(LC_CTYPE
, NULL
); 
 116     if ((strlen(cur_locale
) < 4) || 
 117             (strcasecmp(cur_locale 
+ strlen(cur_locale
) - 4, "utf8")) || 
 118             (strcasecmp(cur_locale 
+ strlen(cur_locale
) - 5, "utf-8"))) { 
 119       // nope, don't use libc conversion 
 127 // ============================================================================ 
 128 // printf() functions business 
 129 // ============================================================================ 
 131 // special test mode: define all functions below even if we don't really need 
 132 // them to be able to test them 
 143     #define wxNEED_WPRINTF 
 145     int wxVfprintf( FILE *stream
, const wxChar 
*format
, va_list argptr 
); 
 148 // ---------------------------------------------------------------------------- 
 149 // implement [v]snprintf() if the system doesn't provide a safe one 
 150 // ---------------------------------------------------------------------------- 
 152 #if !defined(wxVsnprintf_) 
 153 int WXDLLEXPORT 
wxVsnprintf_(wxChar 
*buf
, size_t lenMax
, 
 154                              const wxChar 
*format
, va_list argptr
) 
 156     // buffer to avoid dynamic memory allocation each time for small strings 
 157     char szScratch
[1024]; 
 159     // number of characters in the buffer so far, must be less than lenMax 
 162     for ( size_t n 
= 0; ; n
++ ) 
 164         const wxChar chCur 
= format
[n
]; 
 166         if ( chCur 
== wxT('%') ) 
 168             static char s_szFlags
[256] = "%"; 
 170             bool adj_left 
= FALSE
, 
 175             size_t min_width 
= 0, 
 176                    max_width 
= wxSTRING_MAXLEN
; 
 181                 if (in_prec && !prec_dot) \ 
 183                     s_szFlags[flagofs++] = '.'; \ 
 187 #define APPEND_CH(ch) \ 
 188                 if ( lenCur == lenMax ) \ 
 193 #define APPEND_STR(s) \ 
 195                     for ( const wxChar *p = s; *p; p++ ) \ 
 202                 const wxChar ch 
= format
[++n
]; 
 222                         s_szFlags
[flagofs
++] = ch
; 
 228                         s_szFlags
[flagofs
++] = ch
; 
 236                         // dot will be auto-added to s_szFlags if non-negative 
 243                         s_szFlags
[flagofs
++] = ch
; 
 249                         s_szFlags
[flagofs
++] = ch
; 
 256                         s_szFlags
[flagofs
++] = ch
; 
 262                         s_szFlags
[flagofs
++] = ch
; 
 267                             int len 
= va_arg(argptr
, int); 
 278                                     adj_left 
= !adj_left
; 
 279                                     s_szFlags
[flagofs
++] = '-'; 
 284                             flagofs 
+= ::sprintf(s_szFlags
+flagofs
,"%d",len
); 
 288                     case wxT('1'): case wxT('2'): case wxT('3'): 
 289                     case wxT('4'): case wxT('5'): case wxT('6'): 
 290                     case wxT('7'): case wxT('8'): case wxT('9'): 
 294                             while ( (format
[n
] >= wxT('0')) && 
 295                                     (format
[n
] <= wxT('9')) ) 
 297                                 s_szFlags
[flagofs
++] = format
[n
]; 
 298                                 len 
= len
*10 + (format
[n
] - wxT('0')); 
 307                             n
--; // the main loop pre-increments n again 
 318                         s_szFlags
[flagofs
++] = ch
; 
 319                         s_szFlags
[flagofs
] = '\0'; 
 322                             int val 
= va_arg(argptr
, int); 
 323                             ::sprintf(szScratch
, s_szFlags
, val
); 
 327                             // NB: 'short int' value passed through '...' 
 328                             //      is promoted to 'int', so we have to get 
 329                             //      an int from stack even if we need a short 
 330                             short int val 
= (short int) va_arg(argptr
, int); 
 331                             ::sprintf(szScratch
, s_szFlags
, val
); 
 335                             long int val 
= va_arg(argptr
, long int); 
 336                             ::sprintf(szScratch
, s_szFlags
, val
); 
 341                             long long int val 
= va_arg(argptr
, long long int); 
 342                             ::sprintf(szScratch
, s_szFlags
, val
); 
 344                             long int val 
= va_arg(argptr
, long int); 
 345                             ::sprintf(szScratch
, s_szFlags
, val
); 
 346 #endif // long long/!long long 
 350                             size_t val 
= va_arg(argptr
, size_t); 
 351                             ::sprintf(szScratch
, s_szFlags
, val
); 
 355                             const wxMB2WXbuf tmp 
= 
 356                                 wxConvLibc
.cMB2WX(szScratch
); 
 369                         s_szFlags
[flagofs
++] = ch
; 
 370                         s_szFlags
[flagofs
] = '\0'; 
 373                             long double val 
= va_arg(argptr
, long double); 
 374                             ::sprintf(szScratch
, s_szFlags
, val
); 
 378                             double val 
= va_arg(argptr
, double); 
 379                             ::sprintf(szScratch
, s_szFlags
, val
); 
 383                             const wxMB2WXbuf tmp 
= 
 384                                 wxConvLibc
.cMB2WX(szScratch
); 
 393                             void *val 
= va_arg(argptr
, void *); 
 395                             s_szFlags
[flagofs
++] = ch
; 
 396                             s_szFlags
[flagofs
] = '\0'; 
 397                             ::sprintf(szScratch
, s_szFlags
, val
); 
 399                             const wxMB2WXbuf tmp 
= 
 400                                 wxConvLibc
.cMB2WX(szScratch
); 
 409                             wxChar val 
= va_arg(argptr
, int); 
 410                             // we don't need to honor padding here, do we? 
 420                             // wx extension: we'll let %hs mean non-Unicode 
 422                             char *val 
= va_arg(argptr
, char *); 
 424                             // ASCII->Unicode constructor handles max_width 
 426                             wxString 
s(val
, wxConvLibc
, max_width
); 
 428                             size_t len 
= wxSTRING_MAXLEN
; 
 432                                       val
[len
] && (len 
< max_width
); 
 438                             wxString 
s(val
, len
); 
 440                             if (s
.Len() < min_width
) 
 441                                 s
.Pad(min_width 
- s
.Len(), wxT(' '), adj_left
); 
 447                             wxChar 
*val 
= va_arg(argptr
, wxChar 
*); 
 448                             size_t len 
= wxSTRING_MAXLEN
; 
 452                                       val
[len
] && (len 
< max_width
); 
 459                             wxString 
s(val
, len
); 
 460                             if (s
.Len() < min_width
) 
 461                                 s
.Pad(min_width 
- s
.Len(), wxT(' '), adj_left
); 
 471                             int *val 
= va_arg(argptr
, int *); 
 476                             short int *val 
= va_arg(argptr
, short int *); 
 481                             long int *val 
= va_arg(argptr
, long int *); 
 488                         // bad format, leave unchanged 
 514 #endif // !wxVsnprintfA 
 516 #if !defined(wxSnprintf_) 
 517 int WXDLLEXPORT 
wxSnprintf_(wxChar 
*buf
, size_t len
, const wxChar 
*format
, ...) 
 520     va_start(argptr
, format
); 
 522     int iLen 
= wxVsnprintf_(buf
, len
, format
, argptr
); 
 528 #endif // wxSnprintf_ 
 530 // ---------------------------------------------------------------------------- 
 531 // implement the standard IO functions for wide char if libc doesn't have them 
 532 // ---------------------------------------------------------------------------- 
 536 int wxFputs(const wchar_t *ws
, FILE *stream
) 
 538     // counting the number of wide characters written isn't worth the trouble, 
 539     // simply distinguish between ok and error 
 540     return fputs(wxConvLibc
.cWC2MB(ws
), stream
) == -1 ? -1 : 0; 
 543 int /* not wint_t */ wxPutc(wchar_t wc
, FILE *stream
) 
 545     wchar_t ws
[2] = { wc
, L
'\0' }; 
 547     return wxFputs(ws
, stream
); 
 550 #endif // wxNEED_FPUTWC 
 552 // NB: we only implement va_list functions here, the ones taking ... are 
 553 //     defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse 
 554 //     the definitions there to avoid duplicating them here 
 555 #ifdef wxNEED_WPRINTF 
 557 // TODO: implement the scanf() functions 
 558 int vwscanf(const wxChar 
*format
, va_list argptr
) 
 560     wxFAIL_MSG( _T("TODO") ); 
 565 int vswscanf(const wxChar 
*ws
, const wxChar 
*format
, va_list argptr
) 
 567     wxFAIL_MSG( _T("TODO") ); 
 572 int vfwscanf(FILE *stream
, const wxChar 
*format
, va_list argptr
) 
 574     wxFAIL_MSG( _T("TODO") ); 
 579 #define vswprintf wxVsnprintf_ 
 581 int vfwprintf(FILE *stream
, const wxChar 
*format
, va_list argptr
) 
 584     int rc 
= s
.PrintfV(format
, argptr
); 
 588         // we can't do much better without Unicode support in libc... 
 589         if ( fprintf(stream
, "%s", s
.mb_str()) == -1 ) 
 596 int vwprintf(const wxChar 
*format
, va_list argptr
) 
 598     return wxVfprintf(stdout
, format
, argptr
); 
 601 #endif // wxNEED_WPRINTF 
 603 #ifdef wxNEED_PRINTF_CONVERSION 
 605 // ---------------------------------------------------------------------------- 
 606 // wxFormatConverter: class doing the "%s" -> "%ls" conversion 
 607 // ---------------------------------------------------------------------------- 
 610    Here are the gory details. We want to follow the Windows/MS conventions, 
 615    format specifier         results in 
 616    ----------------------------------- 
 622    format specifier         results in 
 623    ----------------------------------- 
 628    while on POSIX systems we have %C identical to %lc and %c always means char 
 629    (in any mode) while %lc always means wchar_t, 
 631    So to use native functions in order to get our semantics we must do the 
 632    following translations in Unicode mode (nothing to do in ANSI mode): 
 634    wxWindows specifier      POSIX specifier 
 635    ---------------------------------------- 
 641    And, of course, the same should be done for %s as well. 
 644 class wxFormatConverter
 
 647     wxFormatConverter(const wxChar 
*format
); 
 649     // notice that we only translated the string if m_fmtOrig == NULL (as set 
 650     // by CopyAllBefore()), otherwise we should simply use the original format 
 651     operator const wxChar 
*() const 
 652         { return m_fmtOrig 
? m_fmtOrig 
: m_fmt
.c_str(); } 
 655     // copy another character to the translated format: this function does the 
 656     // copy if we are translating but doesn't do anything at all if we don't, 
 657     // so we don't create the translated format string at all unless we really 
 658     // need to (i.e. InsertFmtChar() is called) 
 659     wxChar 
CopyFmtChar(wxChar ch
) 
 663             // we're translating, do copy 
 668             // simply increase the count which should be copied by 
 669             // CopyAllBefore() later if needed 
 676     // insert an extra character 
 677     void InsertFmtChar(wxChar ch
) 
 681             // so far we haven't translated anything yet 
 690         wxASSERT_MSG( m_fmtOrig 
&& m_fmt
.empty(), _T("logic error") ); 
 692         m_fmt 
= wxString(m_fmtOrig
, m_nCopied
); 
 694         // we won't need it any longer 
 698     static bool IsFlagChar(wxChar ch
) 
 700         return ch 
== _T('-') || ch 
== _T('+') || 
 701                ch 
== _T('0') || ch 
== _T(' ') || ch 
== _T('#'); 
 704     void SkipDigits(const wxChar 
**ppc
) 
 706         while ( **ppc 
>= _T('0') && **ppc 
<= _T('9') ) 
 707             CopyFmtChar(*(*ppc
)++); 
 710     // the translated format 
 713     // the original format 
 714     const wxChar 
*m_fmtOrig
; 
 716     // the number of characters already copied 
 720 wxFormatConverter::wxFormatConverter(const wxChar 
*format
) 
 727         if ( CopyFmtChar(*format
++) == _T('%') ) 
 730             while ( IsFlagChar(*format
) ) 
 731                 CopyFmtChar(*format
++); 
 733             // and possible width 
 734             if ( *format 
== _T('*') ) 
 735                 CopyFmtChar(*format
++); 
 740             if ( *format 
== _T('.') ) 
 745             // next we can have a size modifier 
 761                     // "ll" has a different meaning! 
 762                     if ( format
[1] != _T('l') ) 
 774             // and finally we should have the type 
 779                     // %C and %hC -> %c and %lC -> %lc 
 781                         CopyFmtChar(_T('l')); 
 783                     InsertFmtChar(*format
++ == _T('C') ? _T('c') : _T('s')); 
 788                     // %c -> %lc but %hc stays %hc and %lc is still %lc 
 792                             InsertFmtChar(_T('l')); 
 796                             CopyFmtChar(_T('h')); 
 805                     // nothing special to do 
 806                     CopyFmtChar(*format
++); 
 812 #else // !wxNEED_PRINTF_CONVERSION 
 813     // no conversion necessary 
 814     #define wxFormatConverter(x) (x) 
 815 #endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION 
 817 // ---------------------------------------------------------------------------- 
 818 // wxPrintf(), wxScanf() and relatives 
 819 // ---------------------------------------------------------------------------- 
 821 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF) 
 823 int wxScanf( const wxChar 
*format
, ... ) 
 826     va_start(argptr
, format
); 
 828     int ret 
= vwscanf(wxFormatConverter(format
), argptr 
); 
 835 int wxSscanf( const wxChar 
*str
, const wxChar 
*format
, ... ) 
 838     va_start(argptr
, format
); 
 840     int ret 
= vswscanf( str
, wxFormatConverter(format
), argptr 
); 
 847 int wxFscanf( FILE *stream
, const wxChar 
*format
, ... ) 
 850     va_start(argptr
, format
); 
 852     int ret 
= vfwscanf(stream
, wxFormatConverter(format
), argptr
); 
 859 int wxPrintf( const wxChar 
*format
, ... ) 
 862     va_start(argptr
, format
); 
 864     int ret 
= vwprintf( wxFormatConverter(format
), argptr 
); 
 872 int wxSnprintf( wxChar 
*str
, size_t size
, const wxChar 
*format
, ... ) 
 875     va_start(argptr
, format
); 
 877     int ret 
= vswprintf( str
, size
, wxFormatConverter(format
), argptr 
); 
 885 int wxSprintf( wxChar 
*str
, const wxChar 
*format
, ... ) 
 888     va_start(argptr
, format
); 
 890     // callers of wxSprintf() deserve what they get 
 891     int ret 
= vswprintf( str
, UINT_MAX
, wxFormatConverter(format
), argptr 
); 
 898 int wxFprintf( FILE *stream
, const wxChar 
*format
, ... ) 
 901     va_start( argptr
, format 
); 
 903     int ret 
= vfwprintf( stream
, wxFormatConverter(format
), argptr 
); 
 910 int wxVsscanf( const wxChar 
*str
, const wxChar 
*format
, va_list argptr 
) 
 912     return vswscanf( str
, wxFormatConverter(format
), argptr 
); 
 915 int wxVfprintf( FILE *stream
, const wxChar 
*format
, va_list argptr 
) 
 917     return vfwprintf( stream
, wxFormatConverter(format
), argptr 
); 
 920 int wxVprintf( const wxChar 
*format
, va_list argptr 
) 
 922     return vwprintf( wxFormatConverter(format
), argptr 
); 
 926 int wxVsnprintf( wxChar 
*str
, size_t size
, const wxChar 
*format
, va_list argptr 
) 
 928     return vswprintf( str
, size
, wxFormatConverter(format
), argptr 
); 
 930 #endif // wxVsnprintf 
 932 int wxVsprintf( wxChar 
*str
, const wxChar 
*format
, va_list argptr 
) 
 934     // same as for wxSprintf() 
 935     return vswprintf(str
, UINT_MAX
, wxFormatConverter(format
), argptr
); 
 938 #endif // wxNEED_PRINTF_CONVERSION 
 942 // ---------------------------------------------------------------------------- 
 943 // ctype.h stuff (currently unused) 
 944 // ---------------------------------------------------------------------------- 
 946 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H) 
 947 inline WORD 
wxMSW_ctype(wxChar ch
) 
 950   GetStringTypeEx(LOCALE_USER_DEFAULT
, CT_CTYPE1
, &ch
, 1, &ret
); 
 954 WXDLLEXPORT 
int wxIsalnum(wxChar ch
) { return IsCharAlphaNumeric(ch
); } 
 955 WXDLLEXPORT 
int wxIsalpha(wxChar ch
) { return IsCharAlpha(ch
); } 
 956 WXDLLEXPORT 
int wxIsctrl(wxChar ch
) { return wxMSW_ctype(ch
) & C1_CNTRL
; } 
 957 WXDLLEXPORT 
int wxIsdigit(wxChar ch
) { return wxMSW_ctype(ch
) & C1_DIGIT
; } 
 958 WXDLLEXPORT 
int wxIsgraph(wxChar ch
) { return wxMSW_ctype(ch
) & (C1_DIGIT
|C1_PUNCT
|C1_ALPHA
); } 
 959 WXDLLEXPORT 
int wxIslower(wxChar ch
) { return IsCharLower(ch
); } 
 960 WXDLLEXPORT 
int wxIsprint(wxChar ch
) { return wxMSW_ctype(ch
) & (C1_DIGIT
|C1_SPACE
|C1_PUNCT
|C1_ALPHA
); } 
 961 WXDLLEXPORT 
int wxIspunct(wxChar ch
) { return wxMSW_ctype(ch
) & C1_PUNCT
; } 
 962 WXDLLEXPORT 
int wxIsspace(wxChar ch
) { return wxMSW_ctype(ch
) & C1_SPACE
; } 
 963 WXDLLEXPORT 
int wxIsupper(wxChar ch
) { return IsCharUpper(ch
); } 
 964 WXDLLEXPORT 
int wxIsxdigit(wxChar ch
) { return wxMSW_ctype(ch
) & C1_XDIGIT
; } 
 965 WXDLLEXPORT 
int wxTolower(wxChar ch
) { return (wxChar
)CharLower((LPTSTR
)(ch
)); } 
 966 WXDLLEXPORT 
int wxToupper(wxChar ch
) { return (wxChar
)CharUpper((LPTSTR
)(ch
)); } 
 971 WXDLLEXPORT 
char *wxStrdupA(const char *s
) 
 973     return strcpy((char *)malloc(strlen(s
) + 1), s
); 
 980 WXDLLEXPORT 
wchar_t * wxStrdupW(const wchar_t *pwz
) 
 982   size_t size 
= (wxWcslen(pwz
) + 1) * sizeof(wchar_t); 
 983   wchar_t *ret 
= (wchar_t *) malloc(size
); 
 984   memcpy(ret
, pwz
, size
); 
 991 int WXDLLEXPORT 
wxStricmp(const wxChar 
*psz1
, const wxChar 
*psz2
) 
 993   register wxChar c1
, c2
; 
 995     c1 
= wxTolower(*psz1
++); 
 996     c2 
= wxTolower(*psz2
++); 
 997   } while ( c1 
&& (c1 
== c2
) ); 
1003 int WXDLLEXPORT 
wxStrnicmp(const wxChar 
*s1
, const wxChar 
*s2
, size_t n
) 
1005   register wxChar c1
, c2
; 
1006   while (n 
&& ((c1 
= wxTolower(*s1
)) == (c2 
= wxTolower(*s2
)) ) && c1
) n
--, s1
++, s2
++; 
1008     if (c1 
< c2
) return -1; 
1009     if (c1 
> c2
) return 1; 
1016 WXDLLEXPORT wxWCharBuffer 
wxSetlocale(int category
, const wxChar 
*locale
) 
1018     char *localeOld 
= setlocale(category
, wxConvLocal
.cWX2MB(locale
)); 
1020     return wxWCharBuffer(wxConvLocal
.cMB2WC(localeOld
)); 
1024 // ---------------------------------------------------------------------------- 
1025 // string.h functions 
1026 // ---------------------------------------------------------------------------- 
1028 #ifdef wxNEED_WX_STRING_H 
1029 WXDLLEXPORT wxChar 
* wxStrcat(wxChar 
*dest
, const wxChar 
*src
) 
1032   while (*dest
) dest
++; 
1033   while ((*dest
++ = *src
++)); 
1037 WXDLLEXPORT 
const wxChar 
* wxStrchr(const wxChar 
*s
, wxChar c
) 
1039     // be careful here as the terminating NUL makes part of the string 
1049 WXDLLEXPORT 
int wxStrcmp(const wxChar 
*s1
, const wxChar 
*s2
) 
1051   while ((*s1 
== *s2
) && *s1
) s1
++, s2
++; 
1052   if ((wxUChar
)*s1 
< (wxUChar
)*s2
) return -1; 
1053   if ((wxUChar
)*s1 
> (wxUChar
)*s2
) return 1; 
1057 WXDLLEXPORT wxChar 
* wxStrcpy(wxChar 
*dest
, const wxChar 
*src
) 
1060   while ((*dest
++ = *src
++)); 
1064 WXDLLEXPORT wxChar 
* wxStrncat(wxChar 
*dest
, const wxChar 
*src
, size_t n
) 
1067   while (*dest
) dest
++; 
1068   while (n 
&& (*dest
++ = *src
++)) n
--; 
1072 WXDLLEXPORT 
int wxStrncmp(const wxChar 
*s1
, const wxChar 
*s2
, size_t n
) 
1074   while (n 
&& (*s1 
== *s2
) && *s1
) n
--, s1
++, s2
++; 
1076     if ((wxUChar
)*s1 
< (wxUChar
)*s2
) return -1; 
1077     if ((wxUChar
)*s1 
> (wxUChar
)*s2
) return 1; 
1082 WXDLLEXPORT wxChar 
* wxStrncpy(wxChar 
*dest
, const wxChar 
*src
, size_t n
) 
1085   while (n 
&& (*dest
++ = *src
++)) n
--; 
1086   while (n
) *dest
++=0, n
--; // the docs specify padding with zeroes 
1090 WXDLLEXPORT 
const wxChar 
* wxStrpbrk(const wxChar 
*s
, const wxChar 
*accept
) 
1092   while (*s 
&& !wxStrchr(accept
, *s
)) 
1095   return *s 
? s 
: NULL
; 
1098 WXDLLEXPORT 
const wxChar 
* wxStrrchr(const wxChar 
*s
, wxChar c
) 
1100     const wxChar 
*ret 
= NULL
; 
1112 WXDLLEXPORT 
size_t wxStrspn(const wxChar 
*s
, const wxChar 
*accept
) 
1115   while (wxStrchr(accept
, *s
++)) len
++; 
1119 WXDLLEXPORT 
const wxChar 
*wxStrstr(const wxChar 
*haystack
, const wxChar 
*needle
) 
1121     wxCHECK_RET( needle
, NULL
, _T("NULL argument in wxStrstr") ); 
1123     // VZ: this is not exactly the most efficient string search algorithm... 
1125     const size_t len 
= wxStrlen(needle
); 
1127     while ( const wxChar 
*fnd 
= wxStrchr(haystack
, *needle
) ) 
1129         if ( !wxStrncmp(fnd
, needle
, len
) ) 
1138 WXDLLEXPORT 
double wxStrtod(const wxChar 
*nptr
, wxChar 
**endptr
) 
1140   const wxChar 
*start 
= nptr
; 
1142   // FIXME: only correct for C locale 
1143   while (wxIsspace(*nptr
)) nptr
++; 
1144   if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1145   while (wxIsdigit(*nptr
)) nptr
++; 
1146   if (*nptr 
== wxT('.')) { 
1148     while (wxIsdigit(*nptr
)) nptr
++; 
1150   if (*nptr 
== wxT('E') || *nptr 
== wxT('e')) { 
1152     if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1153     while (wxIsdigit(*nptr
)) nptr
++; 
1156   wxString 
data(nptr
, nptr
-start
); 
1157   wxWX2MBbuf dat 
= data
.mb_str(wxConvLocal
); 
1158   char *rdat 
= wxMBSTRINGCAST dat
; 
1159   double ret 
= strtod(dat
, &rdat
); 
1161   if (endptr
) *endptr 
= (wxChar 
*)(start 
+ (rdat 
- (const char *)dat
)); 
1166 WXDLLEXPORT 
long int wxStrtol(const wxChar 
*nptr
, wxChar 
**endptr
, int base
) 
1168   const wxChar 
*start 
= nptr
; 
1170   // FIXME: only correct for C locale 
1171   while (wxIsspace(*nptr
)) nptr
++; 
1172   if (*nptr 
== wxT('+') || *nptr 
== wxT('-')) nptr
++; 
1173   if (((base 
== 0) || (base 
== 16)) && 
1174       (nptr
[0] == wxT('0') && nptr
[1] == wxT('x'))) { 
1178   else if ((base 
== 0) && (nptr
[0] == wxT('0'))) base 
= 8; 
1179   else if (base 
== 0) base 
= 10; 
1181   while ((wxIsdigit(*nptr
) && (*nptr 
- wxT('0') < base
)) || 
1182          (wxIsalpha(*nptr
) && (wxToupper(*nptr
) - wxT('A') + 10 < base
))) nptr
++; 
1184   wxString 
data(nptr
, nptr
-start
); 
1185   wxWX2MBbuf dat 
= data
.mb_str(wxConvLocal
); 
1186   char *rdat 
= wxMBSTRINGCAST dat
; 
1187   long int ret 
= strtol(dat
, &rdat
, base
); 
1189   if (endptr
) *endptr 
= (wxChar 
*)(start 
+ (rdat 
- (const char *)dat
)); 
1193 #endif // wxNEED_WX_STRING_H 
1195 #ifdef wxNEED_WX_STDIO_H 
1196 WXDLLEXPORT 
FILE * wxFopen(const wxChar 
*path
, const wxChar 
*mode
) 
1198     char mode_buffer
[10]; 
1199     for (size_t i 
= 0; i 
< wxStrlen(mode
)+1; i
++) 
1200        mode_buffer
[i
] = (char) mode
[i
]; 
1202     return fopen( wxConvFile
.cWX2MB(path
), mode_buffer 
); 
1205 WXDLLEXPORT 
FILE * wxFreopen(const wxChar 
*path
, const wxChar 
*mode
, FILE *stream
) 
1207     char mode_buffer
[10]; 
1208     for (size_t i 
= 0; i 
< wxStrlen(mode
)+1; i
++) 
1209        mode_buffer
[i
] = (char) mode
[i
]; 
1211     return freopen( wxConvFile
.cWX2MB(path
), mode_buffer
, stream 
); 
1214 WXDLLEXPORT 
int wxRemove(const wxChar 
*path
) 
1216     return remove( wxConvFile
.cWX2MB(path
) ); 
1219 WXDLLEXPORT 
int wxRename(const wxChar 
*oldpath
, const wxChar 
*newpath
) 
1221     return rename( wxConvFile
.cWX2MB(oldpath
), wxConvFile
.cWX2MB(newpath
) ); 
1226 double   WXDLLEXPORT 
wxAtof(const wxChar 
*psz
) 
1228   return atof(wxConvLocal
.cWX2MB(psz
)); 
1232 #ifdef wxNEED_WX_STDLIB_H 
1233 int      WXDLLEXPORT 
wxAtoi(const wxChar 
*psz
) 
1235   return atoi(wxConvLocal
.cWX2MB(psz
)); 
1238 long     WXDLLEXPORT 
wxAtol(const wxChar 
*psz
) 
1240   return atol(wxConvLocal
.cWX2MB(psz
)); 
1243 wxChar 
* WXDLLEXPORT 
wxGetenv(const wxChar 
*name
) 
1245   static wxHashTable env
; 
1247   // check if we already have stored the converted env var 
1248   wxObject 
*data 
= env
.Get(name
); 
1251     // nope, retrieve it, 
1253     wxCharBuffer buffer 
= wxConvLocal
.cWX2MB(name
); 
1254     // printf( "buffer %s\n", (const char*) buffer ); 
1255     const char *val 
= getenv( (const char *)buffer 
); 
1257     const char *val 
= getenv( name 
); 
1260     if (!val
) return (wxChar 
*)NULL
; 
1261     // printf( "home %s\n", val ); 
1264 #ifdef wxUSE_UNICODE 
1265     data 
= (wxObject 
*)new wxString(val
, wxConvLocal
); 
1267     data 
= (wxObject 
*)new wxString(val
); 
1271     env
.Put(name
, data
); 
1273   // return converted env var 
1274   return (wxChar 
*)((wxString 
*)data
)->c_str(); 
1277 int WXDLLEXPORT 
wxSystem(const wxChar 
*psz
) 
1279     return system(wxConvLocal
.cWX2MB(psz
)); 
1282 #endif // wxNEED_WX_STDLIB_H 
1284 #ifdef wxNEED_WX_TIME_H 
1285 WXDLLEXPORT 
size_t   wxStrftime(wxChar 
*s
, size_t max
, const wxChar 
*fmt
, const struct tm 
*tm
) 
1289     char *buf 
= (char *)malloc(max
); 
1290     size_t ret 
= strftime(buf
, max
, wxConvLocal
.cWX2MB(fmt
), tm
); 
1293         wxStrcpy(s
, wxConvLocal
.cMB2WX(buf
)); 
1304 #endif // wxNEED_WX_TIME_H 
1306 #endif // wxUSE_WCHAR_T 
1308 // ---------------------------------------------------------------------------- 
1309 // functions which we may need even if !wxUSE_WCHAR_T 
1310 // ---------------------------------------------------------------------------- 
1314 WXDLLEXPORT wxChar 
* wxStrtok(wxChar 
*psz
, const wxChar 
*delim
, wxChar 
**save_ptr
) 
1323     psz 
+= wxStrspn(psz
, delim
); 
1326         *save_ptr 
= (wxChar 
*)NULL
; 
1327         return (wxChar 
*)NULL
; 
1331     psz 
= wxStrpbrk(psz
, delim
); 
1334         *save_ptr 
= (wxChar
*)NULL
; 
1339         *save_ptr 
= psz 
+ 1;