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