]> git.saurik.com Git - wxWidgets.git/blob - src/common/wxcrt.cpp
add wx/unix/private directory
[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 int vwscanf(const wxChar *format, va_list argptr)
238 {
239 wxFAIL_MSG( _T("TODO") );
240
241 return -1;
242 }
243
244 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 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 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 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 int wxCRT_Scanf( const wxChar *format, ... )
514 {
515 va_list argptr;
516 va_start(argptr, format);
517
518 int ret = vwscanf(wxFormatConverter(format), argptr );
519
520 va_end(argptr);
521
522 return ret;
523 }
524
525 int wxCRT_Sscanf( const wxChar *str, const wxChar *format, ... )
526 {
527 va_list argptr;
528 va_start(argptr, format);
529
530 int ret = vswscanf( str, wxFormatConverter(format), argptr );
531
532 va_end(argptr);
533
534 return ret;
535 }
536
537 int wxCRT_Fscanf( FILE *stream, const wxChar *format, ... )
538 {
539 va_list argptr;
540 va_start(argptr, format);
541 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
542
543 va_end(argptr);
544
545 return ret;
546 }
547
548 int wxCRT_Printf( const wxChar *format, ... )
549 {
550 va_list argptr;
551 va_start(argptr, format);
552
553 int ret = vwprintf( wxFormatConverter(format), argptr );
554
555 va_end(argptr);
556
557 return ret;
558 }
559
560 int wxCRT_Fprintf( FILE *stream, const wxChar *format, ... )
561 {
562 va_list argptr;
563 va_start( argptr, format );
564
565 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
566
567 va_end(argptr);
568
569 return ret;
570 }
571
572 int wxCRT_Vsscanf( const wxChar *str, const wxChar *format, va_list argptr )
573 {
574 return vswscanf( str, wxFormatConverter(format), argptr );
575 }
576
577 int wxCRT_Vfprintf( FILE *stream, const wxChar *format, va_list argptr )
578 {
579 return vfwprintf( stream, wxFormatConverter(format), argptr );
580 }
581
582 int wxCRT_Vprintf( const wxChar *format, va_list argptr )
583 {
584 return vwprintf( wxFormatConverter(format), argptr );
585 }
586
587 #ifndef wxCRT_Vsnprintf
588 int wxCRT_Vsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
589 {
590 return vswprintf( str, size, wxFormatConverter(format), argptr );
591 }
592 #endif // wxCRT_Vsnprintf
593
594 int wxCRT_Vsprintf( wxChar *str, const wxChar *format, va_list argptr )
595 {
596 // same as for wxSprintf()
597 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
598 }
599
600 #endif // wxNEED_PRINTF_CONVERSION
601
602
603 // ----------------------------------------------------------------------------
604 // wrappers to printf and scanf function families
605 // ----------------------------------------------------------------------------
606
607 #if !wxUSE_UTF8_LOCALE_ONLY
608 int wxDoSprintfWchar(char *str, const wxChar *format, ...)
609 {
610 va_list argptr;
611 va_start(argptr, format);
612
613 int rv = wxVsprintf(str, format, argptr);
614
615 va_end(argptr);
616 return rv;
617 }
618 #endif // !wxUSE_UTF8_LOCALE_ONLY
619
620 #if wxUSE_UNICODE_UTF8
621 int wxDoSprintfUtf8(char *str, const char *format, ...)
622 {
623 va_list argptr;
624 va_start(argptr, format);
625
626 int rv = wxVsprintf(str, format, argptr);
627
628 va_end(argptr);
629 return rv;
630 }
631 #endif // wxUSE_UNICODE_UTF8
632
633 #if wxUSE_UNICODE
634
635 #if !wxUSE_UTF8_LOCALE_ONLY
636 int wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...)
637 {
638 va_list argptr;
639 va_start(argptr, format);
640
641 int rv = wxVsprintf(str, format, argptr);
642
643 va_end(argptr);
644 return rv;
645 }
646 #endif // !wxUSE_UTF8_LOCALE_ONLY
647
648 #if wxUSE_UNICODE_UTF8
649 int wxDoSprintfUtf8(wchar_t *str, const char *format, ...)
650 {
651 va_list argptr;
652 va_start(argptr, format);
653
654 int rv = wxVsprintf(str, format, argptr);
655
656 va_end(argptr);
657 return rv;
658 }
659 #endif // wxUSE_UNICODE_UTF8
660
661 #endif // wxUSE_UNICODE
662
663 #if !wxUSE_UTF8_LOCALE_ONLY
664 int wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...)
665 {
666 va_list argptr;
667 va_start(argptr, format);
668
669 int rv = wxVsnprintf(str, size, format, argptr);
670
671 va_end(argptr);
672 return rv;
673 }
674 #endif // !wxUSE_UTF8_LOCALE_ONLY
675
676 #if wxUSE_UNICODE_UTF8
677 int wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...)
678 {
679 va_list argptr;
680 va_start(argptr, format);
681
682 int rv = wxVsnprintf(str, size, format, argptr);
683
684 va_end(argptr);
685 return rv;
686 }
687 #endif // wxUSE_UNICODE_UTF8
688
689 #if wxUSE_UNICODE
690
691 #if !wxUSE_UTF8_LOCALE_ONLY
692 int wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...)
693 {
694 va_list argptr;
695 va_start(argptr, format);
696
697 int rv = wxVsnprintf(str, size, format, argptr);
698
699 va_end(argptr);
700 return rv;
701 }
702 #endif // !wxUSE_UTF8_LOCALE_ONLY
703
704 #if wxUSE_UNICODE_UTF8
705 int wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...)
706 {
707 va_list argptr;
708 va_start(argptr, format);
709
710 int rv = wxVsnprintf(str, size, format, argptr);
711
712 va_end(argptr);
713 return rv;
714 }
715 #endif // wxUSE_UNICODE_UTF8
716
717 #endif // wxUSE_UNICODE
718
719
720 #ifdef HAVE_BROKEN_VSNPRINTF_DECL
721 #define vsnprintf wx_fixed_vsnprintf
722 #endif
723
724 #if wxUSE_UNICODE
725
726 #if !wxUSE_UTF8_LOCALE_ONLY
727 static int ConvertStringToBuf(const wxString& s, char *out, size_t outsize)
728 {
729 const wxWX2WCbuf buf = s.wc_str();
730
731 size_t len = wxConvLibc.FromWChar(out, outsize, buf);
732 if ( len != wxCONV_FAILED )
733 return len-1;
734 else
735 return wxConvLibc.FromWChar(NULL, 0, buf);
736 }
737 #endif // !wxUSE_UTF8_LOCALE_ONLY
738
739 #if wxUSE_UNICODE_UTF8
740 static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize)
741 {
742 const wxWX2WCbuf buf(s.wc_str());
743 size_t len = wxWcslen(buf);
744 if ( outsize > len )
745 memcpy(out, buf, (len+1) * sizeof(wchar_t));
746 // else: not enough space
747 return len;
748 }
749 #endif // wxUSE_UNICODE_UTF8
750
751 template<typename T>
752 static size_t PrintfViaString(T *out, size_t outsize,
753 const wxString& format, va_list argptr)
754 {
755 wxString s;
756 s.PrintfV(format, argptr);
757
758 return ConvertStringToBuf(s, out, outsize);
759 }
760 #endif // wxUSE_UNICODE
761
762 int wxVsprintf(char *str, const wxString& format, va_list argptr)
763 {
764 #if wxUSE_UTF8_LOCALE_ONLY
765 return vsprintf(str, format.wx_str(), argptr);
766 #else
767 #if wxUSE_UNICODE_UTF8
768 if ( wxLocaleIsUtf8 )
769 return vsprintf(str, format.wx_str(), argptr);
770 else
771 #endif
772 #if wxUSE_UNICODE
773 return PrintfViaString(str, wxNO_LEN, format, argptr);
774 #else
775 return wxCRT_Vsprintf(str, format, argptr);
776 #endif
777 #endif
778 }
779
780 #if wxUSE_UNICODE
781 int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr)
782 {
783 #if wxUSE_UNICODE_WCHAR
784 return wxCRT_Vsprintf(str, format, argptr);
785 #else // wxUSE_UNICODE_UTF8
786 #if !wxUSE_UTF8_LOCALE_ONLY
787 if ( !wxLocaleIsUtf8 )
788 return wxCRT_Vsprintf(str, format, argptr);
789 else
790 #endif
791 return PrintfViaString(str, wxNO_LEN, format, argptr);
792 #endif // wxUSE_UNICODE_UTF8
793 }
794 #endif // wxUSE_UNICODE
795
796 int wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr)
797 {
798 int rv;
799 #if wxUSE_UTF8_LOCALE_ONLY
800 rv = vsnprintf(str, size, format.wx_str(), argptr);
801 #else
802 #if wxUSE_UNICODE_UTF8
803 if ( wxLocaleIsUtf8 )
804 rv = vsnprintf(str, size, format.wx_str(), argptr);
805 else
806 #endif
807 #if wxUSE_UNICODE
808 {
809 // NB: if this code is called, then wxString::PrintV() would use the
810 // wchar_t* version of wxVsnprintf(), so it's safe to use PrintV()
811 // from here
812 rv = PrintfViaString(str, size, format, argptr);
813 }
814 #else
815 rv = wxCRT_Vsnprintf(str, size, format, argptr);
816 #endif
817 #endif
818
819 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
820 // doesn't nul terminate on truncation.
821 str[size - 1] = 0;
822
823 return rv;
824 }
825
826 #if wxUSE_UNICODE
827 int wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr)
828 {
829 int rv;
830
831 #if wxUSE_UNICODE_WCHAR
832 rv = wxCRT_Vsnprintf(str, size, format, argptr);
833 #else // wxUSE_UNICODE_UTF8
834 #if !wxUSE_UTF8_LOCALE_ONLY
835 if ( !wxLocaleIsUtf8 )
836 rv = wxCRT_Vsnprintf(str, size, format, argptr);
837 else
838 #endif
839 {
840 // NB: if this code is called, then wxString::PrintV() would use the
841 // char* version of wxVsnprintf(), so it's safe to use PrintV()
842 // from here
843 rv = PrintfViaString(str, size, format, argptr);
844 }
845 #endif // wxUSE_UNICODE_UTF8
846
847 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
848 // doesn't nul terminate on truncation.
849 str[size - 1] = 0;
850
851 return rv;
852 }
853 #endif // wxUSE_UNICODE
854
855 #if wxUSE_WCHAR_T
856
857 // ----------------------------------------------------------------------------
858 // ctype.h stuff (currently unused)
859 // ----------------------------------------------------------------------------
860
861 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
862 inline WORD wxMSW_ctype(wxChar ch)
863 {
864 WORD ret;
865 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
866 return ret;
867 }
868
869 WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
870 WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
871 WXDLLEXPORT int wxIscntrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
872 WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
873 WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
874 WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
875 WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
876 WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
877 WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
878 WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
879 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
880 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
881 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
882 #endif
883
884 #ifdef wxNEED_WX_MBSTOWCS
885
886 WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
887 {
888 if (!out)
889 {
890 size_t outsize = 0;
891 while(*in++)
892 outsize++;
893 return outsize;
894 }
895
896 const char* origin = in;
897
898 while (outlen-- && *in)
899 {
900 *out++ = (wchar_t) *in++;
901 }
902
903 *out = '\0';
904
905 return in - origin;
906 }
907
908 WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
909 {
910 if (!out)
911 {
912 size_t outsize = 0;
913 while(*in++)
914 outsize++;
915 return outsize;
916 }
917
918 const wchar_t* origin = in;
919
920 while (outlen-- && *in)
921 {
922 *out++ = (char) *in++;
923 }
924
925 *out = '\0';
926
927 return in - origin;
928 }
929
930 #endif // wxNEED_WX_MBSTOWCS
931
932 #if defined(wxNEED_WX_CTYPE_H)
933
934 #include <CoreFoundation/CoreFoundation.h>
935
936 #define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
937 #define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
938 #define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
939 #define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
940 //CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
941 #define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
942 //CFCharacterSetRef cfprintset = !kCFCharacterSetControl
943 #define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
944 #define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
945 #define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
946
947 WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
948 WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
949 WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
950 WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
951 WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
952 WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
953 WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
954 WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
955 WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
956 WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
957 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
958 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
959 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
960
961 #endif // wxNEED_WX_CTYPE_H
962
963 #ifndef wxStrdupA
964
965 WXDLLEXPORT char *wxStrdupA(const char *s)
966 {
967 return strcpy((char *)malloc(strlen(s) + 1), s);
968 }
969
970 #endif // wxStrdupA
971
972 #ifndef wxStrdupW
973
974 WXDLLEXPORT wchar_t * wxStrdupW(const wchar_t *pwz)
975 {
976 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
977 wchar_t *ret = (wchar_t *) malloc(size);
978 memcpy(ret, pwz, size);
979 return ret;
980 }
981
982 #endif // wxStrdupW
983
984 #ifndef wxStricmp
985 int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
986 {
987 register wxChar c1, c2;
988 do {
989 c1 = wxTolower(*psz1++);
990 c2 = wxTolower(*psz2++);
991 } while ( c1 && (c1 == c2) );
992 return c1 - c2;
993 }
994 #endif
995
996 #ifndef wxStricmp
997 int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
998 {
999 // initialize the variables just to suppress stupid gcc warning
1000 register wxChar c1 = 0, c2 = 0;
1001 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
1002 if (n) {
1003 if (c1 < c2) return -1;
1004 if (c1 > c2) return 1;
1005 }
1006 return 0;
1007 }
1008 #endif
1009
1010 #ifndef wxSetlocale_
1011 wxWCharBuffer wxSetlocale_(int category, const wxChar *locale)
1012 {
1013 char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
1014
1015 return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
1016 }
1017
1018 wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
1019 {
1020 wxWCharBuffer rv = wxSetlocale_(category, locale);
1021 if ( rv )
1022 wxUpdateLocaleIsUtf8();
1023 return rv;
1024 }
1025 #else // defined(wxSetlocale_)
1026 wxChar *wxSetlocale(int category, const wxChar *locale)
1027 {
1028 wxChar *rv = wxSetlocale_(category, locale);
1029 if ( rv )
1030 wxUpdateLocaleIsUtf8();
1031 return rv;
1032 }
1033 #endif // wxSetlocale_ defined or not
1034
1035 #if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
1036 WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
1037 {
1038 size_t n = 0;
1039 while ( *s++ )
1040 n++;
1041
1042 return n;
1043 }
1044 #endif
1045
1046 // ----------------------------------------------------------------------------
1047 // string.h functions
1048 // ----------------------------------------------------------------------------
1049
1050 #ifdef wxNEED_WX_STRING_H
1051
1052 // RN: These need to be c externed for the regex lib
1053 #ifdef __cplusplus
1054 extern "C" {
1055 #endif
1056
1057 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
1058 {
1059 wxChar *ret = dest;
1060 while (*dest) dest++;
1061 while ((*dest++ = *src++));
1062 return ret;
1063 }
1064
1065 WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
1066 {
1067 // be careful here as the terminating NUL makes part of the string
1068 while ( *s != c )
1069 {
1070 if ( !*s++ )
1071 return NULL;
1072 }
1073
1074 return s;
1075 }
1076
1077 WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
1078 {
1079 while ((*s1 == *s2) && *s1) s1++, s2++;
1080 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1081 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1082 return 0;
1083 }
1084
1085 WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
1086 {
1087 wxChar *ret = dest;
1088 while ((*dest++ = *src++));
1089 return ret;
1090 }
1091
1092 WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
1093 {
1094 size_t n = 0;
1095 while ( *s++ )
1096 n++;
1097
1098 return n;
1099 }
1100
1101
1102 WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
1103 {
1104 wxChar *ret = dest;
1105 while (*dest) dest++;
1106 while (n && (*dest++ = *src++)) n--;
1107 return ret;
1108 }
1109
1110 WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
1111 {
1112 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
1113 if (n) {
1114 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1115 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1116 }
1117 return 0;
1118 }
1119
1120 WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
1121 {
1122 wxChar *ret = dest;
1123 while (n && (*dest++ = *src++)) n--;
1124 while (n) *dest++=0, n--; // the docs specify padding with zeroes
1125 return ret;
1126 }
1127
1128 WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
1129 {
1130 while (*s && !wxStrchr(accept, *s))
1131 s++;
1132
1133 return *s ? s : NULL;
1134 }
1135
1136 WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
1137 {
1138 const wxChar *ret = NULL;
1139 do
1140 {
1141 if ( *s == c )
1142 ret = s;
1143 s++;
1144 }
1145 while ( *s );
1146
1147 return ret;
1148 }
1149
1150 WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
1151 {
1152 size_t len = 0;
1153 while (wxStrchr(accept, *s++)) len++;
1154 return len;
1155 }
1156
1157 WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
1158 {
1159 wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
1160
1161 // VZ: this is not exactly the most efficient string search algorithm...
1162
1163 const size_t len = wxStrlen(needle);
1164
1165 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
1166 {
1167 if ( !wxStrncmp(fnd, needle, len) )
1168 return fnd;
1169
1170 haystack = fnd + 1;
1171 }
1172
1173 return NULL;
1174 }
1175
1176 #ifdef __cplusplus
1177 }
1178 #endif
1179
1180 WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
1181 {
1182 const wxChar *start = nptr;
1183
1184 // FIXME: only correct for C locale
1185 while (wxIsspace(*nptr)) nptr++;
1186 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1187 while (wxIsdigit(*nptr)) nptr++;
1188 if (*nptr == wxT('.')) {
1189 nptr++;
1190 while (wxIsdigit(*nptr)) nptr++;
1191 }
1192 if (*nptr == wxT('E') || *nptr == wxT('e')) {
1193 nptr++;
1194 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1195 while (wxIsdigit(*nptr)) nptr++;
1196 }
1197
1198 wxString data(nptr, nptr-start);
1199 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1200 char *rdat = wxMBSTRINGCAST dat;
1201 double ret = strtod(dat, &rdat);
1202
1203 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1204
1205 return ret;
1206 }
1207
1208 WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
1209 {
1210 const wxChar *start = nptr;
1211
1212 // FIXME: only correct for C locale
1213 while (wxIsspace(*nptr)) nptr++;
1214 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1215 if (((base == 0) || (base == 16)) &&
1216 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
1217 nptr += 2;
1218 base = 16;
1219 }
1220 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
1221 else if (base == 0) base = 10;
1222
1223 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
1224 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
1225
1226 wxString data(start, nptr-start);
1227 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1228 char *rdat = wxMBSTRINGCAST dat;
1229 long int ret = strtol(dat, &rdat, base);
1230
1231 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1232
1233 return ret;
1234 }
1235
1236 WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
1237 {
1238 return (unsigned long int) wxStrtol(nptr, endptr, base);
1239 }
1240
1241 #endif // wxNEED_WX_STRING_H
1242
1243 #ifdef wxNEED_WX_STDIO_H
1244 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
1245 {
1246 char mode_buffer[10];
1247 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1248 mode_buffer[i] = (char) mode[i];
1249
1250 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
1251 }
1252
1253 WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
1254 {
1255 char mode_buffer[10];
1256 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1257 mode_buffer[i] = (char) mode[i];
1258
1259 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
1260 }
1261
1262 WXDLLEXPORT int wxRemove(const wxChar *path)
1263 {
1264 return remove( wxConvFile.cWX2MB(path) );
1265 }
1266
1267 WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
1268 {
1269 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
1270 }
1271 #endif
1272
1273 #ifndef wxAtof
1274 double WXDLLEXPORT wxAtof(const wxChar *psz)
1275 {
1276 #ifdef __WXWINCE__
1277 double d;
1278 wxString str(psz);
1279 if (str.ToDouble(& d))
1280 return d;
1281
1282 return 0.0;
1283 #else
1284 return atof(wxConvLibc.cWX2MB(psz));
1285 #endif
1286 }
1287 #endif
1288
1289 #ifdef wxNEED_WX_STDLIB_H
1290 int WXDLLEXPORT wxAtoi(const wxChar *psz)
1291 {
1292 return atoi(wxConvLibc.cWX2MB(psz));
1293 }
1294
1295 long WXDLLEXPORT wxAtol(const wxChar *psz)
1296 {
1297 return atol(wxConvLibc.cWX2MB(psz));
1298 }
1299
1300 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
1301 {
1302 #if wxUSE_UNICODE
1303 // NB: buffer returned by getenv() is allowed to be overwritten next
1304 // time getenv() is called, so it is OK to use static string
1305 // buffer to hold the data.
1306 static wxWCharBuffer value((wxChar*)NULL);
1307 value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
1308 return value.data();
1309 #else
1310 return getenv(name);
1311 #endif
1312 }
1313
1314 #endif // wxNEED_WX_STDLIB_H
1315
1316 #ifdef wxNEED_WXSYSTEM
1317 int WXDLLEXPORT wxSystem(const wxChar *psz)
1318 {
1319 return system(wxConvLibc.cWX2MB(psz));
1320 }
1321 #endif // wxNEED_WXSYSTEM
1322
1323 #ifdef wxNEED_WX_TIME_H
1324 WXDLLEXPORT size_t
1325 wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
1326 {
1327 if ( !maxsize )
1328 return 0;
1329
1330 wxCharBuffer buf(maxsize);
1331
1332 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
1333 if ( !bufFmt )
1334 return 0;
1335
1336 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
1337 if ( !ret )
1338 return 0;
1339
1340 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
1341 if ( !wbuf )
1342 return 0;
1343
1344 wxStrncpy(s, wbuf, maxsize);
1345 return wxStrlen(s);
1346 }
1347 #endif // wxNEED_WX_TIME_H
1348
1349 #ifndef wxCtime
1350 WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
1351 {
1352 // normally the string is 26 chars but give one more in case some broken
1353 // DOS compiler decides to use "\r\n" instead of "\n" at the end
1354 static wxChar buf[27];
1355
1356 // ctime() is guaranteed to return a string containing only ASCII
1357 // characters, as its format is always the same for any locale
1358 wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
1359 buf[WXSIZEOF(buf) - 1] = _T('\0');
1360
1361 return buf;
1362 }
1363 #endif // wxCtime
1364
1365 #endif // wxUSE_WCHAR_T
1366
1367 #ifndef wxStrtoll
1368 static wxULongLong_t wxStrtoullBase(const wxChar* nptr, wxChar** endptr, int base, wxChar* sign)
1369 {
1370 wxULongLong_t sum = 0;
1371 wxString wxstr(nptr);
1372 wxString::const_iterator i = wxstr.begin();
1373 wxString::const_iterator end = wxstr.end();
1374
1375 // Skip spaces
1376 while ( i != end && wxIsspace(*i) ) i++;
1377
1378 // Starts with sign?
1379 *sign = wxT(' ');
1380 if ( i != end )
1381 {
1382 wxChar c = *i;
1383 if ( c == wxT('+') || c == wxT('-') )
1384 {
1385 *sign = c;
1386 i++;
1387 }
1388 }
1389
1390 // Starts with 0x?
1391 if ( i != end && *i == wxT('0') )
1392 {
1393 i++;
1394 if ( i != end )
1395 {
1396 if ( *i == wxT('x') && (base == 16 || base == 0) )
1397 {
1398 base = 16;
1399 i++;
1400 }
1401 else
1402 {
1403 if ( endptr )
1404 *endptr = (wxChar*) nptr;
1405 wxSET_ERRNO(EINVAL);
1406 return sum;
1407 }
1408 }
1409 else
1410 i--;
1411 }
1412
1413 if ( base == 0 )
1414 base = 10;
1415
1416 for ( ; i != end; i++ )
1417 {
1418 unsigned int n;
1419
1420 wxChar c = *i;
1421 if ( c >= wxT('0') )
1422 {
1423 if ( c <= wxT('9') )
1424 n = c - wxT('0');
1425 else
1426 n = wxTolower(c) - wxT('a') + 10;
1427 }
1428 else
1429 break;
1430
1431 if ( n >= (unsigned int)base )
1432 // Invalid character (for this base)
1433 break;
1434
1435 wxULongLong_t prevsum = sum;
1436 sum = (sum * base) + n;
1437
1438 if ( sum < prevsum )
1439 {
1440 wxSET_ERRNO(ERANGE);
1441 break;
1442 }
1443 }
1444
1445 if ( endptr )
1446 {
1447 *endptr = (wxChar*)(nptr + (i - wxstr.begin()));
1448 }
1449
1450 return sum;
1451 }
1452
1453 wxULongLong_t wxStrtoull(const wxChar* nptr, wxChar** endptr, int base)
1454 {
1455 wxChar sign;
1456 wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
1457
1458 if ( sign == wxT('-') )
1459 {
1460 wxSET_ERRNO(ERANGE);
1461 uval = 0;
1462 }
1463
1464 return uval;
1465 }
1466
1467 wxLongLong_t wxStrtoll(const wxChar* nptr, wxChar** endptr, int base)
1468 {
1469 wxChar sign;
1470 wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
1471 wxLongLong_t val = 0;
1472
1473 if ( sign == wxT('-') )
1474 {
1475 if ( uval <= wxULL(wxINT64_MAX+1) )
1476 {
1477 if ( uval == wxULL(wxINT64_MAX+1))
1478 val = -((wxLongLong_t)wxINT64_MAX) - 1;
1479 else
1480 val = -((wxLongLong_t)uval);
1481 }
1482 else
1483 {
1484 wxSET_ERRNO(ERANGE);
1485 }
1486 }
1487 else if ( uval <= wxINT64_MAX )
1488 {
1489 val = uval;
1490 }
1491 else
1492 {
1493 wxSET_ERRNO(ERANGE);
1494 }
1495
1496 return val;
1497 }
1498 #endif // wxStrtoll
1499
1500 // ----------------------------------------------------------------------------
1501 // functions which we may need even if !wxUSE_WCHAR_T
1502 // ----------------------------------------------------------------------------
1503
1504 #ifndef wxStrtok
1505
1506 WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
1507 {
1508 if (!psz)
1509 {
1510 psz = *save_ptr;
1511 if ( !psz )
1512 return NULL;
1513 }
1514
1515 psz += wxStrspn(psz, delim);
1516 if (!*psz)
1517 {
1518 *save_ptr = (wxChar *)NULL;
1519 return (wxChar *)NULL;
1520 }
1521
1522 wxChar *ret = psz;
1523 psz = wxStrpbrk(psz, delim);
1524 if (!psz)
1525 {
1526 *save_ptr = (wxChar*)NULL;
1527 }
1528 else
1529 {
1530 *psz = wxT('\0');
1531 *save_ptr = psz + 1;
1532 }
1533
1534 return ret;
1535 }
1536
1537 #endif // wxStrtok
1538
1539 // ----------------------------------------------------------------------------
1540 // missing C RTL functions
1541 // ----------------------------------------------------------------------------
1542
1543 #ifdef wxNEED_STRDUP
1544
1545 char *strdup(const char *s)
1546 {
1547 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
1548 if ( dest )
1549 strcpy( dest , s ) ;
1550 return dest ;
1551 }
1552 #endif // wxNEED_STRDUP
1553
1554 #if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
1555
1556 void *calloc( size_t num, size_t size )
1557 {
1558 void** ptr = (void **)malloc(num * size);
1559 memset( ptr, 0, num * size);
1560 return ptr;
1561 }
1562
1563 #endif // __WXWINCE__ <= 211
1564
1565 #ifdef __WXWINCE__
1566
1567 int wxRemove(const wxChar *path)
1568 {
1569 return ::DeleteFile(path) == 0;
1570 }
1571
1572 #endif
1573
1574
1575 // ----------------------------------------------------------------------------
1576 // wxLocaleIsUtf8
1577 // ----------------------------------------------------------------------------
1578
1579 #if wxUSE_UNICODE_UTF8
1580
1581 #if !wxUSE_UTF8_LOCALE_ONLY
1582 bool wxLocaleIsUtf8 = false; // the safer setting if not known
1583 #endif
1584
1585 static bool wxIsLocaleUtf8()
1586 {
1587 // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
1588 // because a) it may be unavailable in some builds and b) has slightly
1589 // different semantics (default locale instead of current)
1590
1591 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
1592 // GNU libc provides current character set this way (this conforms to
1593 // Unix98)
1594 const char *charset = nl_langinfo(CODESET);
1595 if ( charset )
1596 {
1597 // "UTF-8" is used by modern glibc versions, but test other variants
1598 // as well, just in case:
1599 if ( strcmp(charset, "UTF-8") == 0 ||
1600 strcmp(charset, "utf-8") == 0 ||
1601 strcmp(charset, "UTF8") == 0 ||
1602 strcmp(charset, "utf8") == 0 )
1603 {
1604 return true;
1605 }
1606 }
1607 #endif
1608
1609 // check if we're running under the "C" locale: it is 7bit subset
1610 // of UTF-8, so it can be safely used with the UTF-8 build:
1611 const char *lc_ctype = setlocale(LC_CTYPE, NULL);
1612 if ( lc_ctype &&
1613 (strcmp(lc_ctype, "C") == 0 || strcmp(lc_ctype, "POSIX") == 0) )
1614 {
1615 return true;
1616 }
1617
1618 // we don't know what charset libc is using, so assume the worst
1619 // to be safe:
1620 return false;
1621 }
1622
1623 void wxUpdateLocaleIsUtf8()
1624 {
1625 #if wxUSE_UTF8_LOCALE_ONLY
1626 if ( !wxIsLocaleUtf8() )
1627 {
1628 wxLogFatalError(_T("This program requires UTF-8 locale to run."));
1629 }
1630 #else // !wxUSE_UTF8_LOCALE_ONLY
1631 wxLocaleIsUtf8 = wxIsLocaleUtf8();
1632 #endif
1633 }
1634
1635 #endif // wxUSE_UTF8_LOCALE_ONLY