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