split wxchar.h into several smaller headers
[wxWidgets.git] / src / common / wxcrt.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/wxcrt.cpp
3 // Purpose: wxChar CRT wrappers implementation
4 // Author: Ove Kaven
5 // Modified by: Ron Lee, Francesco Montorsi
6 // Created: 09/04/99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets copyright
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // headers, declarations, constants
14 // ===========================================================================
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/wxchar.h"
24
25 #define _ISOC9X_SOURCE 1 // to get vsscanf()
26 #define _BSD_SOURCE 1 // to still get strdup()
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifndef __WXWINCE__
33 #include <time.h>
34 #include <locale.h>
35 #else
36 #include "wx/msw/wince/time.h"
37 #endif
38
39 #ifndef WX_PRECOMP
40 #include "wx/string.h"
41 #include "wx/hash.h"
42 #include "wx/utils.h" // for wxMin and wxMax
43 #include "wx/log.h"
44 #endif
45
46 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
47 #include <windef.h>
48 #include <winbase.h>
49 #include <winnls.h>
50 #include <winnt.h>
51 #endif
52
53 #if defined(__MWERKS__) && __MSL__ >= 0x6000
54 namespace std {}
55 using namespace std ;
56 #endif
57
58 #if wxUSE_WCHAR_T
59 size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
60 {
61 // assume that we have mbsrtowcs() too if we have wcsrtombs()
62 #ifdef HAVE_WCSRTOMBS
63 mbstate_t mbstate;
64 memset(&mbstate, 0, sizeof(mbstate_t));
65 #endif
66
67 if (buf) {
68 if (!n || !*psz) {
69 if (n) *buf = wxT('\0');
70 return 0;
71 }
72 #ifdef HAVE_WCSRTOMBS
73 return mbsrtowcs(buf, &psz, n, &mbstate);
74 #else
75 return wxMbstowcs(buf, psz, n);
76 #endif
77 }
78
79 // note that we rely on common (and required by Unix98 but unfortunately not
80 // C99) extension which allows to call mbs(r)towcs() with NULL output pointer
81 // to just get the size of the needed buffer -- this is needed as otherwise
82 // we have no idea about how much space we need and if the CRT doesn't
83 // support it (the only currently known example being Metrowerks, see
84 // wx/wxchar.h) we don't use its mbstowcs() at all
85 #ifdef HAVE_WCSRTOMBS
86 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
87 #else
88 return wxMbstowcs((wchar_t *) NULL, psz, 0);
89 #endif
90 }
91
92 size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
93 {
94 #ifdef HAVE_WCSRTOMBS
95 mbstate_t mbstate;
96 memset(&mbstate, 0, sizeof(mbstate_t));
97 #endif
98
99 if (buf) {
100 if (!n || !*pwz) {
101 // glibc2.1 chokes on null input
102 if (n) *buf = '\0';
103 return 0;
104 }
105 #ifdef HAVE_WCSRTOMBS
106 return wcsrtombs(buf, &pwz, n, &mbstate);
107 #else
108 return wxWcstombs(buf, pwz, n);
109 #endif
110 }
111
112 #ifdef HAVE_WCSRTOMBS
113 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
114 #else
115 return wxWcstombs((char *) NULL, pwz, 0);
116 #endif
117 }
118 #endif // wxUSE_WCHAR_T
119
120 bool WXDLLEXPORT wxOKlibc()
121 {
122 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__)
123 // glibc 2.0 uses UTF-8 even when it shouldn't
124 wchar_t res = 0;
125 if ((MB_CUR_MAX == 2) &&
126 (wxMB2WC(&res, "\xdd\xa5", 1) == 1) &&
127 (res==0x765)) {
128 // this is UTF-8 allright, check whether that's what we want
129 char *cur_locale = setlocale(LC_CTYPE, NULL);
130 if ((strlen(cur_locale) < 4) ||
131 (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
132 (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
133 // nope, don't use libc conversion
134 return false;
135 }
136 }
137 #endif
138 return true;
139 }
140
141 // ============================================================================
142 // printf() functions business
143 // ============================================================================
144
145 // special test mode: define all functions below even if we don't really need
146 // them to be able to test them
147 #ifdef wxTEST_PRINTF
148 #undef wxFprintf
149 #undef wxPrintf
150 #undef wxSprintf
151 #undef wxVfprintf
152 #undef wxVsprintf
153 #undef wxVprintf
154 #undef wxVsnprintf_
155 #undef wxSnprintf_
156
157 #define wxNEED_WPRINTF
158
159 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr );
160 #endif
161
162 #if !defined(wxSnprintf_)
163 int WXDLLEXPORT wxDoSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...)
164 {
165 va_list argptr;
166 va_start(argptr, format);
167
168 int iLen = wxVsnprintf_(buf, len, format, argptr);
169
170 va_end(argptr);
171
172 return iLen;
173 }
174 #endif // wxSnprintf_
175
176 #if defined(__DMC__)
177 /* Digital Mars adds count to _stprintf (C99) so convert */
178 #if wxUSE_UNICODE
179 int wxDoSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
180 {
181 va_list arglist;
182
183 va_start( arglist, format );
184 int iLen = swprintf ( s, -1, format, arglist );
185 va_end( arglist );
186 return iLen ;
187 }
188
189 #endif // wxUSE_UNICODE
190
191 #endif //__DMC__
192
193 // ----------------------------------------------------------------------------
194 // implement the standard IO functions for wide char if libc doesn't have them
195 // ----------------------------------------------------------------------------
196
197 #ifdef wxNEED_FPUTS
198 int wxFputs(const wchar_t *ws, FILE *stream)
199 {
200 wxCharBuffer buf(wxConvLibc.cWC2MB(ws));
201 if ( !buf )
202 return -1;
203
204 // counting the number of wide characters written isn't worth the trouble,
205 // simply distinguish between ok and error
206 return fputs(buf, stream) == -1 ? -1 : 0;
207 }
208 #endif // wxNEED_FPUTS
209
210 #ifdef wxNEED_PUTS
211 int wxPuts(const wxChar *ws)
212 {
213 int rc = wxFputs(ws, stdout);
214 if ( rc != -1 )
215 {
216 if ( wxFputs(L"\n", stdout) == -1 )
217 return -1;
218
219 rc++;
220 }
221
222 return rc;
223 }
224 #endif // wxNEED_PUTS
225
226 #ifdef wxNEED_PUTC
227 int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
228 {
229 wchar_t ws[2] = { wc, L'\0' };
230
231 return wxFputs(ws, stream);
232 }
233 #endif // wxNEED_PUTC
234
235 // NB: we only implement va_list functions here, the ones taking ... are
236 // defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
237 // the definitions there to avoid duplicating them here
238 #ifdef wxNEED_WPRINTF
239
240 // TODO: implement the scanf() functions
241 int vwscanf(const wxChar *format, va_list argptr)
242 {
243 wxFAIL_MSG( _T("TODO") );
244
245 return -1;
246 }
247
248 int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr)
249 {
250 // The best we can do without proper Unicode support in glibc is to
251 // convert the strings into MB representation and run ANSI version
252 // of the function. This doesn't work with %c and %s because of difference
253 // in size of char and wchar_t, though.
254
255 wxCHECK_MSG( wxStrstr(format, _T("%s")) == NULL, -1,
256 _T("incomplete vswscanf implementation doesn't allow %s") );
257 wxCHECK_MSG( wxStrstr(format, _T("%c")) == NULL, -1,
258 _T("incomplete vswscanf implementation doesn't allow %c") );
259
260 va_list argcopy;
261 wxVaCopy(argcopy, argptr);
262 return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argcopy);
263 }
264
265 int vfwscanf(FILE *stream, const wxChar *format, va_list argptr)
266 {
267 wxFAIL_MSG( _T("TODO") );
268
269 return -1;
270 }
271
272 #define vswprintf wxVsnprintf_
273
274 int vfwprintf(FILE *stream, const wxChar *format, va_list argptr)
275 {
276 wxString s;
277 int rc = s.PrintfV(format, argptr);
278
279 if ( rc != -1 )
280 {
281 // we can't do much better without Unicode support in libc...
282 if ( fprintf(stream, "%s", (const char*)s.mb_str() ) == -1 )
283 return -1;
284 }
285
286 return rc;
287 }
288
289 int vwprintf(const wxChar *format, va_list argptr)
290 {
291 return wxVfprintf(stdout, format, argptr);
292 }
293
294 #endif // wxNEED_WPRINTF
295
296 #ifdef wxNEED_PRINTF_CONVERSION
297
298 // ----------------------------------------------------------------------------
299 // wxFormatConverter: class doing the "%s" -> "%ls" conversion
300 // ----------------------------------------------------------------------------
301
302 /*
303 Here are the gory details. We want to follow the Windows/MS conventions,
304 that is to have
305
306 In ANSI mode:
307
308 format specifier results in
309 -----------------------------------
310 %c, %hc, %hC char
311 %lc, %C, %lC wchar_t
312
313 In Unicode mode:
314
315 format specifier results in
316 -----------------------------------
317 %hc, %C, %hC char
318 %c, %lc, %lC wchar_t
319
320
321 while on POSIX systems we have %C identical to %lc and %c always means char
322 (in any mode) while %lc always means wchar_t,
323
324 So to use native functions in order to get our semantics we must do the
325 following translations in Unicode mode (nothing to do in ANSI mode):
326
327 wxWidgets specifier POSIX specifier
328 ----------------------------------------
329
330 %hc, %C, %hC %c
331 %c %lc
332
333
334 And, of course, the same should be done for %s as well.
335 */
336
337 class wxFormatConverter
338 {
339 public:
340 wxFormatConverter(const wxChar *format);
341
342 // notice that we only translated the string if m_fmtOrig == NULL (as set
343 // by CopyAllBefore()), otherwise we should simply use the original format
344 operator const wxChar *() const
345 { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
346
347 private:
348 // copy another character to the translated format: this function does the
349 // copy if we are translating but doesn't do anything at all if we don't,
350 // so we don't create the translated format string at all unless we really
351 // need to (i.e. InsertFmtChar() is called)
352 wxChar CopyFmtChar(wxChar ch)
353 {
354 if ( !m_fmtOrig )
355 {
356 // we're translating, do copy
357 m_fmt += ch;
358 }
359 else
360 {
361 // simply increase the count which should be copied by
362 // CopyAllBefore() later if needed
363 m_nCopied++;
364 }
365
366 return ch;
367 }
368
369 // insert an extra character
370 void InsertFmtChar(wxChar ch)
371 {
372 if ( m_fmtOrig )
373 {
374 // so far we haven't translated anything yet
375 CopyAllBefore();
376 }
377
378 m_fmt += ch;
379 }
380
381 void CopyAllBefore()
382 {
383 wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
384
385 m_fmt = wxString(m_fmtOrig, m_nCopied);
386
387 // we won't need it any longer
388 m_fmtOrig = NULL;
389 }
390
391 static bool IsFlagChar(wxChar ch)
392 {
393 return ch == _T('-') || ch == _T('+') ||
394 ch == _T('0') || ch == _T(' ') || ch == _T('#');
395 }
396
397 void SkipDigits(const wxChar **ptpc)
398 {
399 while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
400 CopyFmtChar(*(*ptpc)++);
401 }
402
403 // the translated format
404 wxString m_fmt;
405
406 // the original format
407 const wxChar *m_fmtOrig;
408
409 // the number of characters already copied
410 size_t m_nCopied;
411 };
412
413 wxFormatConverter::wxFormatConverter(const wxChar *format)
414 {
415 m_fmtOrig = format;
416 m_nCopied = 0;
417
418 while ( *format )
419 {
420 if ( CopyFmtChar(*format++) == _T('%') )
421 {
422 // skip any flags
423 while ( IsFlagChar(*format) )
424 CopyFmtChar(*format++);
425
426 // and possible width
427 if ( *format == _T('*') )
428 CopyFmtChar(*format++);
429 else
430 SkipDigits(&format);
431
432 // precision?
433 if ( *format == _T('.') )
434 {
435 CopyFmtChar(*format++);
436 if ( *format == _T('*') )
437 CopyFmtChar(*format++);
438 else
439 SkipDigits(&format);
440 }
441
442 // next we can have a size modifier
443 enum
444 {
445 Default,
446 Short,
447 Long
448 } size;
449
450 switch ( *format )
451 {
452 case _T('h'):
453 size = Short;
454 format++;
455 break;
456
457 case _T('l'):
458 // "ll" has a different meaning!
459 if ( format[1] != _T('l') )
460 {
461 size = Long;
462 format++;
463 break;
464 }
465 //else: fall through
466
467 default:
468 size = Default;
469 }
470
471 // and finally we should have the type
472 switch ( *format )
473 {
474 case _T('C'):
475 case _T('S'):
476 // %C and %hC -> %c and %lC -> %lc
477 if ( size == Long )
478 CopyFmtChar(_T('l'));
479
480 InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
481 break;
482
483 case _T('c'):
484 case _T('s'):
485 // %c -> %lc but %hc stays %hc and %lc is still %lc
486 if ( size == Default)
487 InsertFmtChar(_T('l'));
488 // fall through
489
490 default:
491 // nothing special to do
492 if ( size != Default )
493 CopyFmtChar(*(format - 1));
494 CopyFmtChar(*format++);
495 }
496 }
497 }
498 }
499
500 #else // !wxNEED_PRINTF_CONVERSION
501 // no conversion necessary
502 #define wxFormatConverter(x) (x)
503 #endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION
504
505 #ifdef __WXDEBUG__
506 // For testing the format converter
507 wxString wxConvertFormat(const wxChar *format)
508 {
509 return wxString(wxFormatConverter(format));
510 }
511 #endif
512
513 // ----------------------------------------------------------------------------
514 // wxPrintf(), wxScanf() and relatives
515 // ----------------------------------------------------------------------------
516
517 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
518
519 int wxDoScanf( const wxChar *format, ... )
520 {
521 va_list argptr;
522 va_start(argptr, format);
523
524 int ret = vwscanf(wxFormatConverter(format), argptr );
525
526 va_end(argptr);
527
528 return ret;
529 }
530
531 int wxDoSscanf( const wxChar *str, const wxChar *format, ... )
532 {
533 va_list argptr;
534 va_start(argptr, format);
535
536 int ret = vswscanf( str, wxFormatConverter(format), argptr );
537
538 va_end(argptr);
539
540 return ret;
541 }
542
543 int wxDoFscanf( FILE *stream, const wxChar *format, ... )
544 {
545 va_list argptr;
546 va_start(argptr, format);
547 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
548
549 va_end(argptr);
550
551 return ret;
552 }
553
554 int wxDoPrintf( const wxChar *format, ... )
555 {
556 va_list argptr;
557 va_start(argptr, format);
558
559 int ret = vwprintf( wxFormatConverter(format), argptr );
560
561 va_end(argptr);
562
563 return ret;
564 }
565
566 #ifndef wxSnprintf
567 int wxDoSnprintf( wxChar *str, size_t size, const wxChar *format, ... )
568 {
569 va_list argptr;
570 va_start(argptr, format);
571
572 int ret = vswprintf( str, size, wxFormatConverter(format), argptr );
573
574 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
575 // doesn't nul terminate on truncation.
576 str[size - 1] = 0;
577
578 va_end(argptr);
579
580 return ret;
581 }
582 #endif // wxSnprintf
583
584 int wxDoSprintf( wxChar *str, const wxChar *format, ... )
585 {
586 va_list argptr;
587 va_start(argptr, format);
588
589 // note that wxString::FormatV() uses wxVsnprintf(), not wxSprintf(), so
590 // it's safe to implement this one in terms of it
591 wxString s(wxString::FormatV(format, argptr));
592 wxStrcpy(str, s);
593
594 va_end(argptr);
595
596 return s.length();
597 }
598
599 int wxDoFprintf( FILE *stream, const wxChar *format, ... )
600 {
601 va_list argptr;
602 va_start( argptr, format );
603
604 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
605
606 va_end(argptr);
607
608 return ret;
609 }
610
611 int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr )
612 {
613 return vswscanf( str, wxFormatConverter(format), argptr );
614 }
615
616 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr )
617 {
618 return vfwprintf( stream, wxFormatConverter(format), argptr );
619 }
620
621 int wxVprintf( const wxChar *format, va_list argptr )
622 {
623 return vwprintf( wxFormatConverter(format), argptr );
624 }
625
626 #ifndef wxVsnprintf
627 int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
628 {
629 return vswprintf( str, size, wxFormatConverter(format), argptr );
630 }
631 #endif // wxVsnprintf
632
633 int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr )
634 {
635 // same as for wxSprintf()
636 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
637 }
638
639 #endif // wxNEED_PRINTF_CONVERSION
640
641 #if wxUSE_WCHAR_T
642
643 // ----------------------------------------------------------------------------
644 // ctype.h stuff (currently unused)
645 // ----------------------------------------------------------------------------
646
647 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
648 inline WORD wxMSW_ctype(wxChar ch)
649 {
650 WORD ret;
651 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
652 return ret;
653 }
654
655 WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
656 WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
657 WXDLLEXPORT int wxIscntrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
658 WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
659 WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
660 WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
661 WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
662 WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
663 WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
664 WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
665 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
666 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
667 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
668 #endif
669
670 #ifdef wxNEED_WX_MBSTOWCS
671
672 WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
673 {
674 if (!out)
675 {
676 size_t outsize = 0;
677 while(*in++)
678 outsize++;
679 return outsize;
680 }
681
682 const char* origin = in;
683
684 while (outlen-- && *in)
685 {
686 *out++ = (wchar_t) *in++;
687 }
688
689 *out = '\0';
690
691 return in - origin;
692 }
693
694 WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
695 {
696 if (!out)
697 {
698 size_t outsize = 0;
699 while(*in++)
700 outsize++;
701 return outsize;
702 }
703
704 const wchar_t* origin = in;
705
706 while (outlen-- && *in)
707 {
708 *out++ = (char) *in++;
709 }
710
711 *out = '\0';
712
713 return in - origin;
714 }
715
716 #endif // wxNEED_WX_MBSTOWCS
717
718 #if defined(wxNEED_WX_CTYPE_H)
719
720 #include <CoreFoundation/CoreFoundation.h>
721
722 #define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
723 #define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
724 #define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
725 #define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
726 //CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
727 #define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
728 //CFCharacterSetRef cfprintset = !kCFCharacterSetControl
729 #define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
730 #define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
731 #define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
732
733 WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
734 WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
735 WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
736 WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
737 WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
738 WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
739 WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
740 WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
741 WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
742 WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
743 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
744 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
745 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
746
747 #endif // wxNEED_WX_CTYPE_H
748
749 #ifndef wxStrdupA
750
751 WXDLLEXPORT char *wxStrdupA(const char *s)
752 {
753 return strcpy((char *)malloc(strlen(s) + 1), s);
754 }
755
756 #endif // wxStrdupA
757
758 #ifndef wxStrdupW
759
760 WXDLLEXPORT wchar_t * wxStrdupW(const wchar_t *pwz)
761 {
762 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
763 wchar_t *ret = (wchar_t *) malloc(size);
764 memcpy(ret, pwz, size);
765 return ret;
766 }
767
768 #endif // wxStrdupW
769
770 #ifndef wxStricmp
771 int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
772 {
773 register wxChar c1, c2;
774 do {
775 c1 = wxTolower(*psz1++);
776 c2 = wxTolower(*psz2++);
777 } while ( c1 && (c1 == c2) );
778 return c1 - c2;
779 }
780 #endif
781
782 #ifndef wxStricmp
783 int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
784 {
785 // initialize the variables just to suppress stupid gcc warning
786 register wxChar c1 = 0, c2 = 0;
787 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
788 if (n) {
789 if (c1 < c2) return -1;
790 if (c1 > c2) return 1;
791 }
792 return 0;
793 }
794 #endif
795
796 #ifndef wxSetlocale
797 WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
798 {
799 char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
800
801 return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
802 }
803 #endif
804
805 #if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
806 WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
807 {
808 size_t n = 0;
809 while ( *s++ )
810 n++;
811
812 return n;
813 }
814 #endif
815
816 // ----------------------------------------------------------------------------
817 // string.h functions
818 // ----------------------------------------------------------------------------
819
820 #ifdef wxNEED_WX_STRING_H
821
822 // RN: These need to be c externed for the regex lib
823 #ifdef __cplusplus
824 extern "C" {
825 #endif
826
827 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
828 {
829 wxChar *ret = dest;
830 while (*dest) dest++;
831 while ((*dest++ = *src++));
832 return ret;
833 }
834
835 WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
836 {
837 // be careful here as the terminating NUL makes part of the string
838 while ( *s != c )
839 {
840 if ( !*s++ )
841 return NULL;
842 }
843
844 return s;
845 }
846
847 WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
848 {
849 while ((*s1 == *s2) && *s1) s1++, s2++;
850 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
851 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
852 return 0;
853 }
854
855 WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
856 {
857 wxChar *ret = dest;
858 while ((*dest++ = *src++));
859 return ret;
860 }
861
862 WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
863 {
864 size_t n = 0;
865 while ( *s++ )
866 n++;
867
868 return n;
869 }
870
871
872 WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
873 {
874 wxChar *ret = dest;
875 while (*dest) dest++;
876 while (n && (*dest++ = *src++)) n--;
877 return ret;
878 }
879
880 WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
881 {
882 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
883 if (n) {
884 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
885 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
886 }
887 return 0;
888 }
889
890 WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
891 {
892 wxChar *ret = dest;
893 while (n && (*dest++ = *src++)) n--;
894 while (n) *dest++=0, n--; // the docs specify padding with zeroes
895 return ret;
896 }
897
898 WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
899 {
900 while (*s && !wxStrchr(accept, *s))
901 s++;
902
903 return *s ? s : NULL;
904 }
905
906 WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
907 {
908 const wxChar *ret = NULL;
909 do
910 {
911 if ( *s == c )
912 ret = s;
913 s++;
914 }
915 while ( *s );
916
917 return ret;
918 }
919
920 WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
921 {
922 size_t len = 0;
923 while (wxStrchr(accept, *s++)) len++;
924 return len;
925 }
926
927 WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
928 {
929 wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
930
931 // VZ: this is not exactly the most efficient string search algorithm...
932
933 const size_t len = wxStrlen(needle);
934
935 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
936 {
937 if ( !wxStrncmp(fnd, needle, len) )
938 return fnd;
939
940 haystack = fnd + 1;
941 }
942
943 return NULL;
944 }
945
946 #ifdef __cplusplus
947 }
948 #endif
949
950 WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
951 {
952 const wxChar *start = nptr;
953
954 // FIXME: only correct for C locale
955 while (wxIsspace(*nptr)) nptr++;
956 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
957 while (wxIsdigit(*nptr)) nptr++;
958 if (*nptr == wxT('.')) {
959 nptr++;
960 while (wxIsdigit(*nptr)) nptr++;
961 }
962 if (*nptr == wxT('E') || *nptr == wxT('e')) {
963 nptr++;
964 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
965 while (wxIsdigit(*nptr)) nptr++;
966 }
967
968 wxString data(nptr, nptr-start);
969 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
970 char *rdat = wxMBSTRINGCAST dat;
971 double ret = strtod(dat, &rdat);
972
973 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
974
975 return ret;
976 }
977
978 WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
979 {
980 const wxChar *start = nptr;
981
982 // FIXME: only correct for C locale
983 while (wxIsspace(*nptr)) nptr++;
984 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
985 if (((base == 0) || (base == 16)) &&
986 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
987 nptr += 2;
988 base = 16;
989 }
990 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
991 else if (base == 0) base = 10;
992
993 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
994 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
995
996 wxString data(start, nptr-start);
997 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
998 char *rdat = wxMBSTRINGCAST dat;
999 long int ret = strtol(dat, &rdat, base);
1000
1001 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1002
1003 return ret;
1004 }
1005
1006 WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
1007 {
1008 return (unsigned long int) wxStrtol(nptr, endptr, base);
1009 }
1010
1011 #endif // wxNEED_WX_STRING_H
1012
1013 #ifdef wxNEED_WX_STDIO_H
1014 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
1015 {
1016 char mode_buffer[10];
1017 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1018 mode_buffer[i] = (char) mode[i];
1019
1020 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
1021 }
1022
1023 WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
1024 {
1025 char mode_buffer[10];
1026 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1027 mode_buffer[i] = (char) mode[i];
1028
1029 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
1030 }
1031
1032 WXDLLEXPORT int wxRemove(const wxChar *path)
1033 {
1034 return remove( wxConvFile.cWX2MB(path) );
1035 }
1036
1037 WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
1038 {
1039 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
1040 }
1041 #endif
1042
1043 #ifndef wxAtof
1044 double WXDLLEXPORT wxAtof(const wxChar *psz)
1045 {
1046 #ifdef __WXWINCE__
1047 double d;
1048 wxString str(psz);
1049 if (str.ToDouble(& d))
1050 return d;
1051
1052 return 0.0;
1053 #else
1054 return atof(wxConvLibc.cWX2MB(psz));
1055 #endif
1056 }
1057 #endif
1058
1059 #ifdef wxNEED_WX_STDLIB_H
1060 int WXDLLEXPORT wxAtoi(const wxChar *psz)
1061 {
1062 return atoi(wxConvLibc.cWX2MB(psz));
1063 }
1064
1065 long WXDLLEXPORT wxAtol(const wxChar *psz)
1066 {
1067 return atol(wxConvLibc.cWX2MB(psz));
1068 }
1069
1070 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
1071 {
1072 #if wxUSE_UNICODE
1073 // NB: buffer returned by getenv() is allowed to be overwritten next
1074 // time getenv() is called, so it is OK to use static string
1075 // buffer to hold the data.
1076 static wxWCharBuffer value((wxChar*)NULL);
1077 value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
1078 return value.data();
1079 #else
1080 return getenv(name);
1081 #endif
1082 }
1083
1084 int WXDLLEXPORT wxSystem(const wxChar *psz)
1085 {
1086 return system(wxConvLibc.cWX2MB(psz));
1087 }
1088
1089 #endif // wxNEED_WX_STDLIB_H
1090
1091 #ifdef wxNEED_WX_TIME_H
1092 WXDLLEXPORT size_t
1093 wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
1094 {
1095 if ( !maxsize )
1096 return 0;
1097
1098 wxCharBuffer buf(maxsize);
1099
1100 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
1101 if ( !bufFmt )
1102 return 0;
1103
1104 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
1105 if ( !ret )
1106 return 0;
1107
1108 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
1109 if ( !wbuf )
1110 return 0;
1111
1112 wxStrncpy(s, wbuf, maxsize);
1113 return wxStrlen(s);
1114 }
1115 #endif // wxNEED_WX_TIME_H
1116
1117 #ifndef wxCtime
1118 WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
1119 {
1120 // normally the string is 26 chars but give one more in case some broken
1121 // DOS compiler decides to use "\r\n" instead of "\n" at the end
1122 static wxChar buf[27];
1123
1124 // ctime() is guaranteed to return a string containing only ASCII
1125 // characters, as its format is always the same for any locale
1126 wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
1127 buf[WXSIZEOF(buf) - 1] = _T('\0');
1128
1129 return buf;
1130 }
1131 #endif // wxCtime
1132
1133 #endif // wxUSE_WCHAR_T
1134
1135 // ----------------------------------------------------------------------------
1136 // functions which we may need even if !wxUSE_WCHAR_T
1137 // ----------------------------------------------------------------------------
1138
1139 #ifndef wxStrtok
1140
1141 WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
1142 {
1143 if (!psz)
1144 {
1145 psz = *save_ptr;
1146 if ( !psz )
1147 return NULL;
1148 }
1149
1150 psz += wxStrspn(psz, delim);
1151 if (!*psz)
1152 {
1153 *save_ptr = (wxChar *)NULL;
1154 return (wxChar *)NULL;
1155 }
1156
1157 wxChar *ret = psz;
1158 psz = wxStrpbrk(psz, delim);
1159 if (!psz)
1160 {
1161 *save_ptr = (wxChar*)NULL;
1162 }
1163 else
1164 {
1165 *psz = wxT('\0');
1166 *save_ptr = psz + 1;
1167 }
1168
1169 return ret;
1170 }
1171
1172 #endif // wxStrtok
1173
1174 // ----------------------------------------------------------------------------
1175 // missing C RTL functions
1176 // ----------------------------------------------------------------------------
1177
1178 #ifdef wxNEED_STRDUP
1179
1180 char *strdup(const char *s)
1181 {
1182 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
1183 if ( dest )
1184 strcpy( dest , s ) ;
1185 return dest ;
1186 }
1187 #endif // wxNEED_STRDUP
1188
1189 #if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
1190
1191 void *calloc( size_t num, size_t size )
1192 {
1193 void** ptr = (void **)malloc(num * size);
1194 memset( ptr, 0, num * size);
1195 return ptr;
1196 }
1197
1198 #endif // __WXWINCE__ <= 211
1199
1200 #ifdef __WXWINCE__
1201
1202 int wxRemove(const wxChar *path)
1203 {
1204 return ::DeleteFile(path) == 0;
1205 }
1206
1207 #endif