fixed wxScanf() etc. to compile with Visual C++ again
[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 #ifndef wxStrtoll
54 #ifdef __WXWINCE__
55 // there is no errno.h under CE apparently
56 #define wxSET_ERRNO(value)
57 #else
58 #include <errno.h>
59
60 #define wxSET_ERRNO(value) errno = value
61 #endif
62 #endif
63
64 #if defined(__MWERKS__) && __MSL__ >= 0x6000
65 namespace std {}
66 using namespace std ;
67 #endif
68
69 #if wxUSE_WCHAR_T
70 size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
71 {
72 // assume that we have mbsrtowcs() too if we have wcsrtombs()
73 #ifdef HAVE_WCSRTOMBS
74 mbstate_t mbstate;
75 memset(&mbstate, 0, sizeof(mbstate_t));
76 #endif
77
78 if (buf) {
79 if (!n || !*psz) {
80 if (n) *buf = wxT('\0');
81 return 0;
82 }
83 #ifdef HAVE_WCSRTOMBS
84 return mbsrtowcs(buf, &psz, n, &mbstate);
85 #else
86 return wxMbstowcs(buf, psz, n);
87 #endif
88 }
89
90 // note that we rely on common (and required by Unix98 but unfortunately not
91 // C99) extension which allows to call mbs(r)towcs() with NULL output pointer
92 // to just get the size of the needed buffer -- this is needed as otherwise
93 // we have no idea about how much space we need and if the CRT doesn't
94 // support it (the only currently known example being Metrowerks, see
95 // wx/wxchar.h) we don't use its mbstowcs() at all
96 #ifdef HAVE_WCSRTOMBS
97 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
98 #else
99 return wxMbstowcs((wchar_t *) NULL, psz, 0);
100 #endif
101 }
102
103 size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
104 {
105 #ifdef HAVE_WCSRTOMBS
106 mbstate_t mbstate;
107 memset(&mbstate, 0, sizeof(mbstate_t));
108 #endif
109
110 if (buf) {
111 if (!n || !*pwz) {
112 // glibc2.1 chokes on null input
113 if (n) *buf = '\0';
114 return 0;
115 }
116 #ifdef HAVE_WCSRTOMBS
117 return wcsrtombs(buf, &pwz, n, &mbstate);
118 #else
119 return wxWcstombs(buf, pwz, n);
120 #endif
121 }
122
123 #ifdef HAVE_WCSRTOMBS
124 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
125 #else
126 return wxWcstombs((char *) NULL, pwz, 0);
127 #endif
128 }
129 #endif // wxUSE_WCHAR_T
130
131 bool WXDLLEXPORT wxOKlibc()
132 {
133 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__)
134 // glibc 2.0 uses UTF-8 even when it shouldn't
135 wchar_t res = 0;
136 if ((MB_CUR_MAX == 2) &&
137 (wxMB2WC(&res, "\xdd\xa5", 1) == 1) &&
138 (res==0x765)) {
139 // this is UTF-8 allright, check whether that's what we want
140 char *cur_locale = setlocale(LC_CTYPE, NULL);
141 if ((strlen(cur_locale) < 4) ||
142 (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
143 (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
144 // nope, don't use libc conversion
145 return false;
146 }
147 }
148 #endif
149 return true;
150 }
151
152 // ============================================================================
153 // printf() functions business
154 // ============================================================================
155
156 // special test mode: define all functions below even if we don't really need
157 // them to be able to test them
158 #ifdef wxTEST_PRINTF
159 #undef wxFprintf
160 #undef wxPrintf
161 #undef wxSprintf
162 #undef wxVfprintf
163 #undef wxVsprintf
164 #undef wxVprintf
165 #undef wxVsnprintf_
166
167 #define wxNEED_WPRINTF
168
169 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr );
170 #endif
171
172 #if defined(__DMC__)
173 /* Digital Mars adds count to _stprintf (C99) so convert */
174 #if wxUSE_UNICODE
175 int wxSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
176 {
177 va_list arglist;
178
179 va_start( arglist, format );
180 int iLen = swprintf ( s, -1, format, arglist );
181 va_end( arglist );
182 return iLen ;
183 }
184
185 #endif // wxUSE_UNICODE
186
187 #endif //__DMC__
188
189 // ----------------------------------------------------------------------------
190 // implement the standard IO functions for wide char if libc doesn't have them
191 // ----------------------------------------------------------------------------
192
193 #ifdef wxNEED_FPUTS
194 int wxFputs(const wchar_t *ws, FILE *stream)
195 {
196 wxCharBuffer buf(wxConvLibc.cWC2MB(ws));
197 if ( !buf )
198 return -1;
199
200 // counting the number of wide characters written isn't worth the trouble,
201 // simply distinguish between ok and error
202 return fputs(buf, stream) == -1 ? -1 : 0;
203 }
204 #endif // wxNEED_FPUTS
205
206 #ifdef wxNEED_PUTS
207 int wxPuts(const wxChar *ws)
208 {
209 int rc = wxFputs(ws, stdout);
210 if ( rc != -1 )
211 {
212 if ( wxFputs(L"\n", stdout) == -1 )
213 return -1;
214
215 rc++;
216 }
217
218 return rc;
219 }
220 #endif // wxNEED_PUTS
221
222 #ifdef wxNEED_PUTC
223 int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
224 {
225 wchar_t ws[2] = { wc, L'\0' };
226
227 return wxFputs(ws, stream);
228 }
229 #endif // wxNEED_PUTC
230
231 // NB: we only implement va_list functions here, the ones taking ... are
232 // defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
233 // the definitions there to avoid duplicating them here
234 #ifdef wxNEED_WPRINTF
235
236 // TODO: implement the scanf() functions
237 static int vwscanf(const wxChar *format, va_list argptr)
238 {
239 wxFAIL_MSG( _T("TODO") );
240
241 return -1;
242 }
243
244 static int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr)
245 {
246 // The best we can do without proper Unicode support in glibc is to
247 // convert the strings into MB representation and run ANSI version
248 // of the function. This doesn't work with %c and %s because of difference
249 // in size of char and wchar_t, though.
250
251 wxCHECK_MSG( wxStrstr(format, _T("%s")) == NULL, -1,
252 _T("incomplete vswscanf implementation doesn't allow %s") );
253 wxCHECK_MSG( wxStrstr(format, _T("%c")) == NULL, -1,
254 _T("incomplete vswscanf implementation doesn't allow %c") );
255
256 return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argptr);
257 }
258
259 static int vfwscanf(FILE *stream, const wxChar *format, va_list argptr)
260 {
261 wxFAIL_MSG( _T("TODO") );
262
263 return -1;
264 }
265
266 #define vswprintf wxVsnprintf_
267
268 static int vfwprintf(FILE *stream, const wxChar *format, va_list argptr)
269 {
270 wxString s;
271 int rc = s.PrintfV(format, argptr);
272
273 if ( rc != -1 )
274 {
275 // we can't do much better without Unicode support in libc...
276 if ( fprintf(stream, "%s", (const char*)s.mb_str() ) == -1 )
277 return -1;
278 }
279
280 return rc;
281 }
282
283 static int vwprintf(const wxChar *format, va_list argptr)
284 {
285 return wxVfprintf(stdout, format, argptr);
286 }
287
288 #endif // wxNEED_WPRINTF
289
290 #ifdef wxNEED_PRINTF_CONVERSION
291
292 // ----------------------------------------------------------------------------
293 // wxFormatConverter: class doing the "%s" -> "%ls" conversion
294 // ----------------------------------------------------------------------------
295
296 /*
297 Here are the gory details. We want to follow the Windows/MS conventions,
298 that is to have
299
300 In ANSI mode:
301
302 format specifier results in
303 -----------------------------------
304 %c, %hc, %hC char
305 %lc, %C, %lC wchar_t
306
307 In Unicode mode:
308
309 format specifier results in
310 -----------------------------------
311 %hc, %C, %hC char
312 %c, %lc, %lC wchar_t
313
314
315 while on POSIX systems we have %C identical to %lc and %c always means char
316 (in any mode) while %lc always means wchar_t,
317
318 So to use native functions in order to get our semantics we must do the
319 following translations in Unicode mode (nothing to do in ANSI mode):
320
321 wxWidgets specifier POSIX specifier
322 ----------------------------------------
323
324 %hc, %C, %hC %c
325 %c %lc
326
327
328 And, of course, the same should be done for %s as well.
329 */
330
331 class wxFormatConverter
332 {
333 public:
334 wxFormatConverter(const wxChar *format);
335
336 // notice that we only translated the string if m_fmtOrig == NULL (as set
337 // by CopyAllBefore()), otherwise we should simply use the original format
338 operator const wxChar *() const
339 { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
340
341 private:
342 // copy another character to the translated format: this function does the
343 // copy if we are translating but doesn't do anything at all if we don't,
344 // so we don't create the translated format string at all unless we really
345 // need to (i.e. InsertFmtChar() is called)
346 wxChar CopyFmtChar(wxChar ch)
347 {
348 if ( !m_fmtOrig )
349 {
350 // we're translating, do copy
351 m_fmt += ch;
352 }
353 else
354 {
355 // simply increase the count which should be copied by
356 // CopyAllBefore() later if needed
357 m_nCopied++;
358 }
359
360 return ch;
361 }
362
363 // insert an extra character
364 void InsertFmtChar(wxChar ch)
365 {
366 if ( m_fmtOrig )
367 {
368 // so far we haven't translated anything yet
369 CopyAllBefore();
370 }
371
372 m_fmt += ch;
373 }
374
375 void CopyAllBefore()
376 {
377 wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
378
379 m_fmt = wxString(m_fmtOrig, m_nCopied);
380
381 // we won't need it any longer
382 m_fmtOrig = NULL;
383 }
384
385 static bool IsFlagChar(wxChar ch)
386 {
387 return ch == _T('-') || ch == _T('+') ||
388 ch == _T('0') || ch == _T(' ') || ch == _T('#');
389 }
390
391 void SkipDigits(const wxChar **ptpc)
392 {
393 while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
394 CopyFmtChar(*(*ptpc)++);
395 }
396
397 // the translated format
398 wxString m_fmt;
399
400 // the original format
401 const wxChar *m_fmtOrig;
402
403 // the number of characters already copied
404 size_t m_nCopied;
405 };
406
407 wxFormatConverter::wxFormatConverter(const wxChar *format)
408 {
409 m_fmtOrig = format;
410 m_nCopied = 0;
411
412 while ( *format )
413 {
414 if ( CopyFmtChar(*format++) == _T('%') )
415 {
416 // skip any flags
417 while ( IsFlagChar(*format) )
418 CopyFmtChar(*format++);
419
420 // and possible width
421 if ( *format == _T('*') )
422 CopyFmtChar(*format++);
423 else
424 SkipDigits(&format);
425
426 // precision?
427 if ( *format == _T('.') )
428 {
429 CopyFmtChar(*format++);
430 if ( *format == _T('*') )
431 CopyFmtChar(*format++);
432 else
433 SkipDigits(&format);
434 }
435
436 // next we can have a size modifier
437 enum
438 {
439 Default,
440 Short,
441 Long
442 } size;
443
444 switch ( *format )
445 {
446 case _T('h'):
447 size = Short;
448 format++;
449 break;
450
451 case _T('l'):
452 // "ll" has a different meaning!
453 if ( format[1] != _T('l') )
454 {
455 size = Long;
456 format++;
457 break;
458 }
459 //else: fall through
460
461 default:
462 size = Default;
463 }
464
465 // and finally we should have the type
466 switch ( *format )
467 {
468 case _T('C'):
469 case _T('S'):
470 // %C and %hC -> %c and %lC -> %lc
471 if ( size == Long )
472 CopyFmtChar(_T('l'));
473
474 InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
475 break;
476
477 case _T('c'):
478 case _T('s'):
479 // %c -> %lc but %hc stays %hc and %lc is still %lc
480 if ( size == Default)
481 InsertFmtChar(_T('l'));
482 // fall through
483
484 default:
485 // nothing special to do
486 if ( size != Default )
487 CopyFmtChar(*(format - 1));
488 CopyFmtChar(*format++);
489 }
490 }
491 }
492 }
493
494 #else // !wxNEED_PRINTF_CONVERSION
495 // no conversion necessary
496 #define wxFormatConverter(x) (x)
497 #endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION
498
499 #ifdef __WXDEBUG__
500 // For testing the format converter
501 wxString wxConvertFormat(const wxChar *format)
502 {
503 return wxString(wxFormatConverter(format));
504 }
505 #endif
506
507 // ----------------------------------------------------------------------------
508 // wxPrintf(), wxScanf() and relatives
509 // ----------------------------------------------------------------------------
510
511 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
512
513 // FIXME-UTF8: do format conversion using (modified) wxFormatConverter in
514 // template wrappers, not here; note that it will needed to
515 // translate all forms of string specifiers to %(l)s for wxPrintf(),
516 // but it only should do what it did in 2.8 for wxScanf()!
517
518 int wxCRT_Printf( const wxChar *format, ... )
519 {
520 va_list argptr;
521 va_start(argptr, format);
522
523 int ret = vwprintf( wxFormatConverter(format), argptr );
524
525 va_end(argptr);
526
527 return ret;
528 }
529
530 int wxCRT_Fprintf( FILE *stream, const wxChar *format, ... )
531 {
532 va_list argptr;
533 va_start( argptr, format );
534
535 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
536
537 va_end(argptr);
538
539 return ret;
540 }
541
542 int wxCRT_Vfprintf( FILE *stream, const wxChar *format, va_list argptr )
543 {
544 return vfwprintf( stream, wxFormatConverter(format), argptr );
545 }
546
547 int wxCRT_Vprintf( const wxChar *format, va_list argptr )
548 {
549 return vwprintf( wxFormatConverter(format), argptr );
550 }
551
552 #ifndef wxCRT_Vsnprintf
553 int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
554 {
555 return vswprintf( str, size, wxFormatConverter(format), argptr );
556 }
557 #endif // wxCRT_Vsnprintf
558
559 int wxCRT_Vsprintf( wxChar *str, const wxChar *format, va_list argptr )
560 {
561 // same as for wxSprintf()
562 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
563 }
564
565 int wxCRT_ScanfW(const wchar_t *format, ...)
566 {
567 va_list argptr;
568 va_start(argptr, format);
569
570 int ret = vwscanf(wxFormatConverter(format), argptr);
571
572 va_end(argptr);
573
574 return ret;
575 }
576
577 int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...)
578 {
579 va_list argptr;
580 va_start(argptr, format);
581
582 int ret = vswscanf(str, wxFormatConverter(format), argptr);
583
584 va_end(argptr);
585
586 return ret;
587 }
588
589 int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...)
590 {
591 va_list argptr;
592 va_start(argptr, format);
593 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
594
595 va_end(argptr);
596
597 return ret;
598 }
599
600 int wxCRT_VsscanfW(const wchar_t *str, const wchar_t *format, va_list argptr)
601 {
602 return vswscanf(str, wxFormatConverter(format), argptr);
603 }
604
605 #endif // wxNEED_PRINTF_CONVERSION
606
607
608 // ----------------------------------------------------------------------------
609 // wrappers to printf and scanf function families
610 // ----------------------------------------------------------------------------
611
612 #if !wxUSE_UTF8_LOCALE_ONLY
613 int wxDoSprintfWchar(char *str, const wxChar *format, ...)
614 {
615 va_list argptr;
616 va_start(argptr, format);
617
618 int rv = wxVsprintf(str, format, argptr);
619
620 va_end(argptr);
621 return rv;
622 }
623 #endif // !wxUSE_UTF8_LOCALE_ONLY
624
625 #if wxUSE_UNICODE_UTF8
626 int wxDoSprintfUtf8(char *str, const char *format, ...)
627 {
628 va_list argptr;
629 va_start(argptr, format);
630
631 int rv = wxVsprintf(str, format, argptr);
632
633 va_end(argptr);
634 return rv;
635 }
636 #endif // wxUSE_UNICODE_UTF8
637
638 #if wxUSE_UNICODE
639
640 #if !wxUSE_UTF8_LOCALE_ONLY
641 int wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...)
642 {
643 va_list argptr;
644 va_start(argptr, format);
645
646 int rv = wxVsprintf(str, format, argptr);
647
648 va_end(argptr);
649 return rv;
650 }
651 #endif // !wxUSE_UTF8_LOCALE_ONLY
652
653 #if wxUSE_UNICODE_UTF8
654 int wxDoSprintfUtf8(wchar_t *str, const char *format, ...)
655 {
656 va_list argptr;
657 va_start(argptr, format);
658
659 int rv = wxVsprintf(str, format, argptr);
660
661 va_end(argptr);
662 return rv;
663 }
664 #endif // wxUSE_UNICODE_UTF8
665
666 #endif // wxUSE_UNICODE
667
668 #if !wxUSE_UTF8_LOCALE_ONLY
669 int wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...)
670 {
671 va_list argptr;
672 va_start(argptr, format);
673
674 int rv = wxVsnprintf(str, size, format, argptr);
675
676 va_end(argptr);
677 return rv;
678 }
679 #endif // !wxUSE_UTF8_LOCALE_ONLY
680
681 #if wxUSE_UNICODE_UTF8
682 int wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...)
683 {
684 va_list argptr;
685 va_start(argptr, format);
686
687 int rv = wxVsnprintf(str, size, format, argptr);
688
689 va_end(argptr);
690 return rv;
691 }
692 #endif // wxUSE_UNICODE_UTF8
693
694 #if wxUSE_UNICODE
695
696 #if !wxUSE_UTF8_LOCALE_ONLY
697 int wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...)
698 {
699 va_list argptr;
700 va_start(argptr, format);
701
702 int rv = wxVsnprintf(str, size, format, argptr);
703
704 va_end(argptr);
705 return rv;
706 }
707 #endif // !wxUSE_UTF8_LOCALE_ONLY
708
709 #if wxUSE_UNICODE_UTF8
710 int wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...)
711 {
712 va_list argptr;
713 va_start(argptr, format);
714
715 int rv = wxVsnprintf(str, size, format, argptr);
716
717 va_end(argptr);
718 return rv;
719 }
720 #endif // wxUSE_UNICODE_UTF8
721
722 #endif // wxUSE_UNICODE
723
724
725 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
726 #define vsnprintf wx_fixed_vsnprintf
727 #endif
728
729 #if wxUSE_UNICODE
730
731 #if !wxUSE_UTF8_LOCALE_ONLY
732 static int ConvertStringToBuf(const wxString& s, char *out, size_t outsize)
733 {
734 const wxWX2WCbuf buf = s.wc_str();
735
736 size_t len = wxConvLibc.FromWChar(out, outsize, buf);
737 if ( len != wxCONV_FAILED )
738 return len-1;
739 else
740 return wxConvLibc.FromWChar(NULL, 0, buf);
741 }
742 #endif // !wxUSE_UTF8_LOCALE_ONLY
743
744 #if wxUSE_UNICODE_UTF8
745 static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize)
746 {
747 const wxWX2WCbuf buf(s.wc_str());
748 size_t len = wxWcslen(buf);
749 if ( outsize > len )
750 memcpy(out, buf, (len+1) * sizeof(wchar_t));
751 // else: not enough space
752 return len;
753 }
754 #endif // wxUSE_UNICODE_UTF8
755
756 template<typename T>
757 static size_t PrintfViaString(T *out, size_t outsize,
758 const wxString& format, va_list argptr)
759 {
760 wxString s;
761 s.PrintfV(format, argptr);
762
763 return ConvertStringToBuf(s, out, outsize);
764 }
765 #endif // wxUSE_UNICODE
766
767 int wxVsprintf(char *str, const wxString& format, va_list argptr)
768 {
769 #if wxUSE_UTF8_LOCALE_ONLY
770 return vsprintf(str, format.wx_str(), argptr);
771 #else
772 #if wxUSE_UNICODE_UTF8
773 if ( wxLocaleIsUtf8 )
774 return vsprintf(str, format.wx_str(), argptr);
775 else
776 #endif
777 #if wxUSE_UNICODE
778 return PrintfViaString(str, wxNO_LEN, format, argptr);
779 #else
780 return wxCRT_Vsprintf(str, format, argptr);
781 #endif
782 #endif
783 }
784
785 #if wxUSE_UNICODE
786 int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr)
787 {
788 #if wxUSE_UNICODE_WCHAR
789 return wxCRT_Vsprintf(str, format, argptr);
790 #else // wxUSE_UNICODE_UTF8
791 #if !wxUSE_UTF8_LOCALE_ONLY
792 if ( !wxLocaleIsUtf8 )
793 return wxCRT_Vsprintf(str, format, argptr);
794 else
795 #endif
796 return PrintfViaString(str, wxNO_LEN, format, argptr);
797 #endif // wxUSE_UNICODE_UTF8
798 }
799 #endif // wxUSE_UNICODE
800
801 int wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr)
802 {
803 int rv;
804 #if wxUSE_UTF8_LOCALE_ONLY
805 rv = vsnprintf(str, size, format.wx_str(), argptr);
806 #else
807 #if wxUSE_UNICODE_UTF8
808 if ( wxLocaleIsUtf8 )
809 rv = vsnprintf(str, size, format.wx_str(), argptr);
810 else
811 #endif
812 #if wxUSE_UNICODE
813 {
814 // NB: if this code is called, then wxString::PrintV() would use the
815 // wchar_t* version of wxVsnprintf(), so it's safe to use PrintV()
816 // from here
817 rv = PrintfViaString(str, size, format, argptr);
818 }
819 #else
820 rv = wxCRT_Vsnprintf(str, size, format, argptr);
821 #endif
822 #endif
823
824 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
825 // doesn't nul terminate on truncation.
826 str[size - 1] = 0;
827
828 return rv;
829 }
830
831 #if wxUSE_UNICODE
832 int wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr)
833 {
834 int rv;
835
836 #if wxUSE_UNICODE_WCHAR
837 rv = wxCRT_Vsnprintf(str, size, format, argptr);
838 #else // wxUSE_UNICODE_UTF8
839 #if !wxUSE_UTF8_LOCALE_ONLY
840 if ( !wxLocaleIsUtf8 )
841 rv = wxCRT_Vsnprintf(str, size, format, argptr);
842 else
843 #endif
844 {
845 // NB: if this code is called, then wxString::PrintV() would use the
846 // char* version of wxVsnprintf(), so it's safe to use PrintV()
847 // from here
848 rv = PrintfViaString(str, size, format, argptr);
849 }
850 #endif // wxUSE_UNICODE_UTF8
851
852 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
853 // doesn't nul terminate on truncation.
854 str[size - 1] = 0;
855
856 return rv;
857 }
858 #endif // wxUSE_UNICODE
859
860 #if wxUSE_WCHAR_T
861
862 // ----------------------------------------------------------------------------
863 // ctype.h stuff (currently unused)
864 // ----------------------------------------------------------------------------
865
866 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
867 inline WORD wxMSW_ctype(wxChar ch)
868 {
869 WORD ret;
870 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
871 return ret;
872 }
873
874 WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
875 WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
876 WXDLLEXPORT int wxIscntrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
877 WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
878 WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
879 WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
880 WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
881 WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
882 WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
883 WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
884 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
885 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
886 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
887 #endif
888
889 #ifdef wxNEED_WX_MBSTOWCS
890
891 WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
892 {
893 if (!out)
894 {
895 size_t outsize = 0;
896 while(*in++)
897 outsize++;
898 return outsize;
899 }
900
901 const char* origin = in;
902
903 while (outlen-- && *in)
904 {
905 *out++ = (wchar_t) *in++;
906 }
907
908 *out = '\0';
909
910 return in - origin;
911 }
912
913 WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
914 {
915 if (!out)
916 {
917 size_t outsize = 0;
918 while(*in++)
919 outsize++;
920 return outsize;
921 }
922
923 const wchar_t* origin = in;
924
925 while (outlen-- && *in)
926 {
927 *out++ = (char) *in++;
928 }
929
930 *out = '\0';
931
932 return in - origin;
933 }
934
935 #endif // wxNEED_WX_MBSTOWCS
936
937 #if defined(wxNEED_WX_CTYPE_H)
938
939 #include <CoreFoundation/CoreFoundation.h>
940
941 #define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
942 #define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
943 #define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
944 #define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
945 //CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
946 #define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
947 //CFCharacterSetRef cfprintset = !kCFCharacterSetControl
948 #define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
949 #define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
950 #define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
951
952 WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
953 WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
954 WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
955 WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
956 WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
957 WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
958 WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
959 WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
960 WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
961 WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
962 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
963 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
964 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
965
966 #endif // wxNEED_WX_CTYPE_H
967
968 #ifndef wxStrdupA
969
970 WXDLLEXPORT char *wxStrdupA(const char *s)
971 {
972 return strcpy((char *)malloc(strlen(s) + 1), s);
973 }
974
975 #endif // wxStrdupA
976
977 #ifndef wxStrdupW
978
979 WXDLLEXPORT wchar_t * wxStrdupW(const wchar_t *pwz)
980 {
981 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
982 wchar_t *ret = (wchar_t *) malloc(size);
983 memcpy(ret, pwz, size);
984 return ret;
985 }
986
987 #endif // wxStrdupW
988
989 #ifndef wxStricmp
990 int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
991 {
992 register wxChar c1, c2;
993 do {
994 c1 = wxTolower(*psz1++);
995 c2 = wxTolower(*psz2++);
996 } while ( c1 && (c1 == c2) );
997 return c1 - c2;
998 }
999 #endif
1000
1001 #ifndef wxStricmp
1002 int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
1003 {
1004 // initialize the variables just to suppress stupid gcc warning
1005 register wxChar c1 = 0, c2 = 0;
1006 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
1007 if (n) {
1008 if (c1 < c2) return -1;
1009 if (c1 > c2) return 1;
1010 }
1011 return 0;
1012 }
1013 #endif
1014
1015 #ifndef wxSetlocale_
1016 wxWCharBuffer wxSetlocale_(int category, const wxChar *locale)
1017 {
1018 char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
1019
1020 return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
1021 }
1022
1023 wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
1024 {
1025 wxWCharBuffer rv = wxSetlocale_(category, locale);
1026 if ( rv )
1027 wxUpdateLocaleIsUtf8();
1028 return rv;
1029 }
1030 #else // defined(wxSetlocale_)
1031 wxChar *wxSetlocale(int category, const wxChar *locale)
1032 {
1033 wxChar *rv = wxSetlocale_(category, locale);
1034 if ( rv )
1035 wxUpdateLocaleIsUtf8();
1036 return rv;
1037 }
1038 #endif // wxSetlocale_ defined or not
1039
1040 #if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
1041 WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
1042 {
1043 size_t n = 0;
1044 while ( *s++ )
1045 n++;
1046
1047 return n;
1048 }
1049 #endif
1050
1051 // ----------------------------------------------------------------------------
1052 // string.h functions
1053 // ----------------------------------------------------------------------------
1054
1055 #ifdef wxNEED_WX_STRING_H
1056
1057 // RN: These need to be c externed for the regex lib
1058 #ifdef __cplusplus
1059 extern "C" {
1060 #endif
1061
1062 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
1063 {
1064 wxChar *ret = dest;
1065 while (*dest) dest++;
1066 while ((*dest++ = *src++));
1067 return ret;
1068 }
1069
1070 WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
1071 {
1072 // be careful here as the terminating NUL makes part of the string
1073 while ( *s != c )
1074 {
1075 if ( !*s++ )
1076 return NULL;
1077 }
1078
1079 return s;
1080 }
1081
1082 WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
1083 {
1084 while ((*s1 == *s2) && *s1) s1++, s2++;
1085 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1086 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1087 return 0;
1088 }
1089
1090 WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
1091 {
1092 wxChar *ret = dest;
1093 while ((*dest++ = *src++));
1094 return ret;
1095 }
1096
1097 WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
1098 {
1099 size_t n = 0;
1100 while ( *s++ )
1101 n++;
1102
1103 return n;
1104 }
1105
1106
1107 WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
1108 {
1109 wxChar *ret = dest;
1110 while (*dest) dest++;
1111 while (n && (*dest++ = *src++)) n--;
1112 return ret;
1113 }
1114
1115 WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
1116 {
1117 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
1118 if (n) {
1119 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1120 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1121 }
1122 return 0;
1123 }
1124
1125 WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
1126 {
1127 wxChar *ret = dest;
1128 while (n && (*dest++ = *src++)) n--;
1129 while (n) *dest++=0, n--; // the docs specify padding with zeroes
1130 return ret;
1131 }
1132
1133 WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
1134 {
1135 while (*s && !wxStrchr(accept, *s))
1136 s++;
1137
1138 return *s ? s : NULL;
1139 }
1140
1141 WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
1142 {
1143 const wxChar *ret = NULL;
1144 do
1145 {
1146 if ( *s == c )
1147 ret = s;
1148 s++;
1149 }
1150 while ( *s );
1151
1152 return ret;
1153 }
1154
1155 WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
1156 {
1157 size_t len = 0;
1158 while (wxStrchr(accept, *s++)) len++;
1159 return len;
1160 }
1161
1162 WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
1163 {
1164 wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
1165
1166 // VZ: this is not exactly the most efficient string search algorithm...
1167
1168 const size_t len = wxStrlen(needle);
1169
1170 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
1171 {
1172 if ( !wxStrncmp(fnd, needle, len) )
1173 return fnd;
1174
1175 haystack = fnd + 1;
1176 }
1177
1178 return NULL;
1179 }
1180
1181 #ifdef __cplusplus
1182 }
1183 #endif
1184
1185 WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
1186 {
1187 const wxChar *start = nptr;
1188
1189 // FIXME: only correct for C locale
1190 while (wxIsspace(*nptr)) nptr++;
1191 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1192 while (wxIsdigit(*nptr)) nptr++;
1193 if (*nptr == wxT('.')) {
1194 nptr++;
1195 while (wxIsdigit(*nptr)) nptr++;
1196 }
1197 if (*nptr == wxT('E') || *nptr == wxT('e')) {
1198 nptr++;
1199 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1200 while (wxIsdigit(*nptr)) nptr++;
1201 }
1202
1203 wxString data(nptr, nptr-start);
1204 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1205 char *rdat = wxMBSTRINGCAST dat;
1206 double ret = strtod(dat, &rdat);
1207
1208 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1209
1210 return ret;
1211 }
1212
1213 WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
1214 {
1215 const wxChar *start = nptr;
1216
1217 // FIXME: only correct for C locale
1218 while (wxIsspace(*nptr)) nptr++;
1219 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1220 if (((base == 0) || (base == 16)) &&
1221 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
1222 nptr += 2;
1223 base = 16;
1224 }
1225 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
1226 else if (base == 0) base = 10;
1227
1228 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
1229 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
1230
1231 wxString data(start, nptr-start);
1232 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1233 char *rdat = wxMBSTRINGCAST dat;
1234 long int ret = strtol(dat, &rdat, base);
1235
1236 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1237
1238 return ret;
1239 }
1240
1241 WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
1242 {
1243 return (unsigned long int) wxStrtol(nptr, endptr, base);
1244 }
1245
1246 #endif // wxNEED_WX_STRING_H
1247
1248 #ifdef wxNEED_WX_STDIO_H
1249 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
1250 {
1251 char mode_buffer[10];
1252 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1253 mode_buffer[i] = (char) mode[i];
1254
1255 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
1256 }
1257
1258 WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
1259 {
1260 char mode_buffer[10];
1261 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1262 mode_buffer[i] = (char) mode[i];
1263
1264 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
1265 }
1266
1267 WXDLLEXPORT int wxRemove(const wxChar *path)
1268 {
1269 return remove( wxConvFile.cWX2MB(path) );
1270 }
1271
1272 WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
1273 {
1274 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
1275 }
1276 #endif
1277
1278 #ifndef wxAtof
1279 double WXDLLEXPORT wxAtof(const wxChar *psz)
1280 {
1281 #ifdef __WXWINCE__
1282 double d;
1283 wxString str(psz);
1284 if (str.ToDouble(& d))
1285 return d;
1286
1287 return 0.0;
1288 #else
1289 return atof(wxConvLibc.cWX2MB(psz));
1290 #endif
1291 }
1292 #endif
1293
1294 #ifdef wxNEED_WX_STDLIB_H
1295 int WXDLLEXPORT wxAtoi(const wxChar *psz)
1296 {
1297 return atoi(wxConvLibc.cWX2MB(psz));
1298 }
1299
1300 long WXDLLEXPORT wxAtol(const wxChar *psz)
1301 {
1302 return atol(wxConvLibc.cWX2MB(psz));
1303 }
1304
1305 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
1306 {
1307 #if wxUSE_UNICODE
1308 // NB: buffer returned by getenv() is allowed to be overwritten next
1309 // time getenv() is called, so it is OK to use static string
1310 // buffer to hold the data.
1311 static wxWCharBuffer value((wxChar*)NULL);
1312 value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
1313 return value.data();
1314 #else
1315 return getenv(name);
1316 #endif
1317 }
1318
1319 #endif // wxNEED_WX_STDLIB_H
1320
1321 #ifdef wxNEED_WXSYSTEM
1322 int WXDLLEXPORT wxSystem(const wxChar *psz)
1323 {
1324 return system(wxConvLibc.cWX2MB(psz));
1325 }
1326 #endif // wxNEED_WXSYSTEM
1327
1328 #ifdef wxNEED_WX_TIME_H
1329 WXDLLEXPORT size_t
1330 wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
1331 {
1332 if ( !maxsize )
1333 return 0;
1334
1335 wxCharBuffer buf(maxsize);
1336
1337 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
1338 if ( !bufFmt )
1339 return 0;
1340
1341 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
1342 if ( !ret )
1343 return 0;
1344
1345 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
1346 if ( !wbuf )
1347 return 0;
1348
1349 wxStrncpy(s, wbuf, maxsize);
1350 return wxStrlen(s);
1351 }
1352 #endif // wxNEED_WX_TIME_H
1353
1354 #ifndef wxCtime
1355 WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
1356 {
1357 // normally the string is 26 chars but give one more in case some broken
1358 // DOS compiler decides to use "\r\n" instead of "\n" at the end
1359 static wxChar buf[27];
1360
1361 // ctime() is guaranteed to return a string containing only ASCII
1362 // characters, as its format is always the same for any locale
1363 wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
1364 buf[WXSIZEOF(buf) - 1] = _T('\0');
1365
1366 return buf;
1367 }
1368 #endif // wxCtime
1369
1370 #endif // wxUSE_WCHAR_T
1371
1372 #ifndef wxStrtoll
1373 static wxULongLong_t wxStrtoullBase(const wxChar* nptr, wxChar** endptr, int base, wxChar* sign)
1374 {
1375 wxULongLong_t sum = 0;
1376 wxString wxstr(nptr);
1377 wxString::const_iterator i = wxstr.begin();
1378 wxString::const_iterator end = wxstr.end();
1379
1380 // Skip spaces
1381 while ( i != end && wxIsspace(*i) ) i++;
1382
1383 // Starts with sign?
1384 *sign = wxT(' ');
1385 if ( i != end )
1386 {
1387 wxChar c = *i;
1388 if ( c == wxT('+') || c == wxT('-') )
1389 {
1390 *sign = c;
1391 i++;
1392 }
1393 }
1394
1395 // Starts with 0x?
1396 if ( i != end && *i == wxT('0') )
1397 {
1398 i++;
1399 if ( i != end )
1400 {
1401 if ( *i == wxT('x') && (base == 16 || base == 0) )
1402 {
1403 base = 16;
1404 i++;
1405 }
1406 else
1407 {
1408 if ( endptr )
1409 *endptr = (wxChar*) nptr;
1410 wxSET_ERRNO(EINVAL);
1411 return sum;
1412 }
1413 }
1414 else
1415 i--;
1416 }
1417
1418 if ( base == 0 )
1419 base = 10;
1420
1421 for ( ; i != end; i++ )
1422 {
1423 unsigned int n;
1424
1425 wxChar c = *i;
1426 if ( c >= wxT('0') )
1427 {
1428 if ( c <= wxT('9') )
1429 n = c - wxT('0');
1430 else
1431 n = wxTolower(c) - wxT('a') + 10;
1432 }
1433 else
1434 break;
1435
1436 if ( n >= (unsigned int)base )
1437 // Invalid character (for this base)
1438 break;
1439
1440 wxULongLong_t prevsum = sum;
1441 sum = (sum * base) + n;
1442
1443 if ( sum < prevsum )
1444 {
1445 wxSET_ERRNO(ERANGE);
1446 break;
1447 }
1448 }
1449
1450 if ( endptr )
1451 {
1452 *endptr = (wxChar*)(nptr + (i - wxstr.begin()));
1453 }
1454
1455 return sum;
1456 }
1457
1458 wxULongLong_t wxStrtoull(const wxChar* nptr, wxChar** endptr, int base)
1459 {
1460 wxChar sign;
1461 wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
1462
1463 if ( sign == wxT('-') )
1464 {
1465 wxSET_ERRNO(ERANGE);
1466 uval = 0;
1467 }
1468
1469 return uval;
1470 }
1471
1472 wxLongLong_t wxStrtoll(const wxChar* nptr, wxChar** endptr, int base)
1473 {
1474 wxChar sign;
1475 wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
1476 wxLongLong_t val = 0;
1477
1478 if ( sign == wxT('-') )
1479 {
1480 if ( uval <= wxULL(wxINT64_MAX+1) )
1481 {
1482 if ( uval == wxULL(wxINT64_MAX+1))
1483 val = -((wxLongLong_t)wxINT64_MAX) - 1;
1484 else
1485 val = -((wxLongLong_t)uval);
1486 }
1487 else
1488 {
1489 wxSET_ERRNO(ERANGE);
1490 }
1491 }
1492 else if ( uval <= wxINT64_MAX )
1493 {
1494 val = uval;
1495 }
1496 else
1497 {
1498 wxSET_ERRNO(ERANGE);
1499 }
1500
1501 return val;
1502 }
1503 #endif // wxStrtoll
1504
1505 // ----------------------------------------------------------------------------
1506 // functions which we may need even if !wxUSE_WCHAR_T
1507 // ----------------------------------------------------------------------------
1508
1509 #ifndef wxStrtok
1510
1511 WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
1512 {
1513 if (!psz)
1514 {
1515 psz = *save_ptr;
1516 if ( !psz )
1517 return NULL;
1518 }
1519
1520 psz += wxStrspn(psz, delim);
1521 if (!*psz)
1522 {
1523 *save_ptr = (wxChar *)NULL;
1524 return (wxChar *)NULL;
1525 }
1526
1527 wxChar *ret = psz;
1528 psz = wxStrpbrk(psz, delim);
1529 if (!psz)
1530 {
1531 *save_ptr = (wxChar*)NULL;
1532 }
1533 else
1534 {
1535 *psz = wxT('\0');
1536 *save_ptr = psz + 1;
1537 }
1538
1539 return ret;
1540 }
1541
1542 #endif // wxStrtok
1543
1544 // ----------------------------------------------------------------------------
1545 // missing C RTL functions
1546 // ----------------------------------------------------------------------------
1547
1548 #ifdef wxNEED_STRDUP
1549
1550 char *strdup(const char *s)
1551 {
1552 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
1553 if ( dest )
1554 strcpy( dest , s ) ;
1555 return dest ;
1556 }
1557 #endif // wxNEED_STRDUP
1558
1559 #if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
1560
1561 void *calloc( size_t num, size_t size )
1562 {
1563 void** ptr = (void **)malloc(num * size);
1564 memset( ptr, 0, num * size);
1565 return ptr;
1566 }
1567
1568 #endif // __WXWINCE__ <= 211
1569
1570 #ifdef __WXWINCE__
1571
1572 int wxRemove(const wxChar *path)
1573 {
1574 return ::DeleteFile(path) == 0;
1575 }
1576
1577 #endif
1578
1579
1580 // ----------------------------------------------------------------------------
1581 // wxLocaleIsUtf8
1582 // ----------------------------------------------------------------------------
1583
1584 #if wxUSE_UNICODE_UTF8
1585
1586 #if !wxUSE_UTF8_LOCALE_ONLY
1587 bool wxLocaleIsUtf8 = false; // the safer setting if not known
1588 #endif
1589
1590 static bool wxIsLocaleUtf8()
1591 {
1592 // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
1593 // because a) it may be unavailable in some builds and b) has slightly
1594 // different semantics (default locale instead of current)
1595
1596 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
1597 // GNU libc provides current character set this way (this conforms to
1598 // Unix98)
1599 const char *charset = nl_langinfo(CODESET);
1600 if ( charset )
1601 {
1602 // "UTF-8" is used by modern glibc versions, but test other variants
1603 // as well, just in case:
1604 if ( strcmp(charset, "UTF-8") == 0 ||
1605 strcmp(charset, "utf-8") == 0 ||
1606 strcmp(charset, "UTF8") == 0 ||
1607 strcmp(charset, "utf8") == 0 )
1608 {
1609 return true;
1610 }
1611 }
1612 #endif
1613
1614 // check if we're running under the "C" locale: it is 7bit subset
1615 // of UTF-8, so it can be safely used with the UTF-8 build:
1616 const char *lc_ctype = setlocale(LC_CTYPE, NULL);
1617 if ( lc_ctype &&
1618 (strcmp(lc_ctype, "C") == 0 || strcmp(lc_ctype, "POSIX") == 0) )
1619 {
1620 return true;
1621 }
1622
1623 // we don't know what charset libc is using, so assume the worst
1624 // to be safe:
1625 return false;
1626 }
1627
1628 void wxUpdateLocaleIsUtf8()
1629 {
1630 #if wxUSE_UTF8_LOCALE_ONLY
1631 if ( !wxIsLocaleUtf8() )
1632 {
1633 wxLogFatalError(_T("This program requires UTF-8 locale to run."));
1634 }
1635 #else // !wxUSE_UTF8_LOCALE_ONLY
1636 wxLocaleIsUtf8 = wxIsLocaleUtf8();
1637 #endif
1638 }
1639
1640 #endif // wxUSE_UNICODE_UTF8
1641
1642 // ============================================================================
1643 // wx wrappers for CRT functions
1644 // ============================================================================
1645
1646
1647 // ----------------------------------------------------------------------------
1648 // wxScanf() and friends
1649 // ----------------------------------------------------------------------------
1650
1651 #ifndef __VISUALC__
1652 int wxVsscanf(const char *str, const char *format, va_list ap)
1653 { return wxCRT_VsscanfA(str, format, ap); }
1654 int wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap)
1655 { return wxCRT_VsscanfW(str, format, ap); }
1656 int wxVsscanf(const wxCharBuffer& str, const char *format, va_list ap)
1657 { return wxCRT_VsscanfA(str, format, ap); }
1658 int wxVsscanf(const wxWCharBuffer& str, const wchar_t *format, va_list ap)
1659 { return wxCRT_VsscanfW(str, format, ap); }
1660 int wxVsscanf(const wxString& str, const char *format, va_list ap)
1661 { return wxCRT_VsscanfA(str.mb_str(), format, ap); }
1662 int wxVsscanf(const wxString& str, const wchar_t *format, va_list ap)
1663 { return wxCRT_VsscanfW(str.wc_str(), format, ap); }
1664 int wxVsscanf(const wxCStrData& str, const char *format, va_list ap)
1665 { return wxCRT_VsscanfA(str.AsCharBuf(), format, ap); }
1666 int wxVsscanf(const wxCStrData& str, const wchar_t *format, va_list ap)
1667 { return wxCRT_VsscanfW(str.AsWCharBuf(), format, ap); }
1668 #endif // !__VISUALC__