]> git.saurik.com Git - wxWidgets.git/blame - src/common/wxcrt.cpp
fix compilation in ANSI STL build
[wxWidgets.git] / src / common / wxcrt.cpp
CommitLineData
dd0ef332
VS
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
3a3dde0d 23#include "wx/crt.h"
dd0ef332
VS
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
52de37c7
VS
46#ifdef __WXWINCE__
47 // there is no errno.h under CE apparently
48 #define wxSET_ERRNO(value)
49#else
50 #include <errno.h>
17482893 51
52de37c7 52 #define wxSET_ERRNO(value) errno = value
17482893
VZ
53#endif
54
dd0ef332
VS
55#if defined(__MWERKS__) && __MSL__ >= 0x6000
56namespace std {}
57using namespace std ;
58#endif
59
60#if wxUSE_WCHAR_T
61size_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
3a3dde0d 86 // wx/crt.h) we don't use its mbstowcs() at all
dd0ef332
VS
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
94size_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
122bool 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
52de37c7
VS
143char* 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
dd0ef332
VS
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_
dd0ef332
VS
168
169 #define wxNEED_WPRINTF
170
52de37c7 171 int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list argptr );
dd0ef332
VS
172#endif
173
dd0ef332 174#if defined(__DMC__)
52de37c7
VS
175/* Digital Mars adds count to _stprintf (C99) so convert */
176int wxCRT_SprintfW (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
177{
178 va_list arglist;
dd0ef332 179
52de37c7
VS
180 va_start( arglist, format );
181 int iLen = swprintf ( s, -1, format, arglist );
182 va_end( arglist );
183 return iLen ;
184}
dd0ef332
VS
185#endif //__DMC__
186
187// ----------------------------------------------------------------------------
188// implement the standard IO functions for wide char if libc doesn't have them
189// ----------------------------------------------------------------------------
190
52de37c7
VS
191#ifndef wxCRT_FputsW
192int wxCRT_FputsW(const wchar_t *ws, FILE *stream)
dd0ef332
VS
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
52de37c7 200 return wxCRT_FputsA(buf, stream) == -1 ? -1 : 0;
dd0ef332 201}
52de37c7 202#endif // !wxCRT_FputsW
dd0ef332 203
52de37c7
VS
204#ifndef wxCRT_PutsW
205int wxCRT_PutsW(const wchar_t *ws)
dd0ef332 206{
52de37c7 207 int rc = wxCRT_FputsW(ws, stdout);
dd0ef332
VS
208 if ( rc != -1 )
209 {
52de37c7 210 if ( wxCRT_FputsW(L"\n", stdout) == -1 )
dd0ef332
VS
211 return -1;
212
213 rc++;
214 }
215
216 return rc;
217}
52de37c7 218#endif // !wxCRT_PutsW
dd0ef332 219
52de37c7
VS
220#ifndef wxCRT_FputcW
221int /* not wint_t */ wxCRT_FputcW(wchar_t wc, FILE *stream)
dd0ef332
VS
222{
223 wchar_t ws[2] = { wc, L'\0' };
224
52de37c7 225 return wxCRT_FputsW(ws, stream);
dd0ef332 226}
52de37c7 227#endif // !wxCRT_FputcW
dd0ef332
VS
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
52de37c7 235static int vwscanf(const wchar_t *format, va_list argptr)
dd0ef332
VS
236{
237 wxFAIL_MSG( _T("TODO") );
238
239 return -1;
240}
241
52de37c7 242static int vswscanf(const wchar_t *ws, const wchar_t *format, va_list argptr)
dd0ef332
VS
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
c6255a6e 254 return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argptr);
dd0ef332
VS
255}
256
52de37c7 257static int vfwscanf(FILE *stream, const wchar_t *format, va_list argptr)
dd0ef332
VS
258{
259 wxFAIL_MSG( _T("TODO") );
260
261 return -1;
262}
263
52de37c7 264#define vswprintf wxCRT_VsnprintfW_
dd0ef332 265
52de37c7 266static int vfwprintf(FILE *stream, const wchar_t *format, va_list argptr)
dd0ef332
VS
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
52de37c7 281static int vwprintf(const wchar_t *format, va_list argptr)
dd0ef332 282{
52de37c7 283 return wxCRT_VfprintfW(stdout, format, argptr);
dd0ef332
VS
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
329class wxFormatConverter
330{
331public:
f62262aa 332 wxFormatConverter(const wchar_t *format);
dd0ef332
VS
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
f62262aa 336 operator const wchar_t *() const
dd0ef332
VS
337 { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
338
339private:
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)
f62262aa 344 wchar_t CopyFmtChar(wchar_t ch)
dd0ef332
VS
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
f62262aa 362 void InsertFmtChar(wchar_t ch)
dd0ef332
VS
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
f62262aa 383 static bool IsFlagChar(wchar_t ch)
dd0ef332
VS
384 {
385 return ch == _T('-') || ch == _T('+') ||
386 ch == _T('0') || ch == _T(' ') || ch == _T('#');
387 }
388
f62262aa 389 void SkipDigits(const wchar_t **ptpc)
dd0ef332
VS
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
f62262aa 399 const wchar_t *m_fmtOrig;
dd0ef332
VS
400
401 // the number of characters already copied
402 size_t m_nCopied;
403};
404
f62262aa 405wxFormatConverter::wxFormatConverter(const wchar_t *format)
dd0ef332
VS
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
f62262aa 499wxString wxConvertFormat(const wchar_t *format)
dd0ef332
VS
500{
501 return wxString(wxFormatConverter(format));
502}
503#endif
504
505// ----------------------------------------------------------------------------
506// wxPrintf(), wxScanf() and relatives
507// ----------------------------------------------------------------------------
508
eb6cb207
VS
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
52de37c7
VS
514#ifndef wxCRT_PrintfW
515int wxCRT_PrintfW( const wchar_t *format, ... )
dd0ef332
VS
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}
52de37c7 526#endif
dd0ef332 527
52de37c7
VS
528#ifndef wxCRT_FprintfW
529int wxCRT_FprintfW( FILE *stream, const wchar_t *format, ... )
dd0ef332
VS
530{
531 va_list argptr;
2523e9b7 532 va_start( argptr, format );
dd0ef332 533
2523e9b7 534 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
dd0ef332
VS
535
536 va_end(argptr);
537
538 return ret;
539}
52de37c7 540#endif
dd0ef332 541
52de37c7
VS
542#ifndef wxCRT_VfprintfW
543int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list argptr )
2523e9b7
VS
544{
545 return vfwprintf( stream, wxFormatConverter(format), argptr );
546}
52de37c7 547#endif
2523e9b7 548
52de37c7
VS
549#ifndef wxCRT_VprintfW
550int wxCRT_VprintfW( const wchar_t *format, va_list argptr )
2523e9b7
VS
551{
552 return vwprintf( wxFormatConverter(format), argptr );
553}
52de37c7 554#endif
2523e9b7 555
52de37c7
VS
556#ifndef wxCRT_VsnprintfW
557int wxCRT_VsnprintfW(wchar_t *str, size_t size, const wchar_t *format, va_list argptr )
2523e9b7
VS
558{
559 return vswprintf( str, size, wxFormatConverter(format), argptr );
560}
52de37c7 561#endif // !wxCRT_VsnprintfW
2523e9b7 562
52de37c7
VS
563#ifndef wxCRT_VsprintfW
564int wxCRT_VsprintfW( wchar_t *str, const wchar_t *format, va_list argptr )
2523e9b7
VS
565{
566 // same as for wxSprintf()
567 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
568}
52de37c7 569#endif
2523e9b7 570
52de37c7 571#ifndef wxCRT_ScanfW
eb6cb207
VS
572int wxCRT_ScanfW(const wchar_t *format, ...)
573{
574 va_list argptr;
575 va_start(argptr, format);
576
28ffb1f2
JJ
577#ifdef __VMS
578#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
579 int ret = std::vwscanf(wxFormatConverter(format), argptr);
580#else
581 int ret = vwscanf(wxFormatConverter(format), argptr);
582#endif
583#else
584 int ret = vwscanf(wxFormatConverter(format), argptr);
585#endif
586
eb6cb207
VS
587 va_end(argptr);
588
589 return ret;
590}
52de37c7 591#endif
eb6cb207 592
52de37c7 593#ifndef wxCRT_SscanfW
eb6cb207
VS
594int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...)
595{
596 va_list argptr;
597 va_start(argptr, format);
598
28ffb1f2
JJ
599#ifdef __VMS
600#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
601 int ret = std::vswscanf(str, wxFormatConverter(format), argptr);
602#else
603 int ret = vswscanf(str, wxFormatConverter(format), argptr);
604#endif
605#else
606 int ret = vswscanf(str, wxFormatConverter(format), argptr);
607#endif
eb6cb207
VS
608
609 va_end(argptr);
610
611 return ret;
612}
52de37c7 613#endif
eb6cb207 614
52de37c7 615#ifndef wxCRT_FscanfW
eb6cb207
VS
616int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...)
617{
618 va_list argptr;
619 va_start(argptr, format);
28ffb1f2
JJ
620#ifdef __VMS
621#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
622 int ret = std::vfwscanf(stream, wxFormatConverter(format), argptr);
623#else
624 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
625#endif
626#else
627 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
628#endif
eb6cb207
VS
629
630 va_end(argptr);
631
632 return ret;
633}
52de37c7 634#endif
eb6cb207 635
52de37c7 636#ifndef wxCRT_VsscanfW
eb6cb207
VS
637int wxCRT_VsscanfW(const wchar_t *str, const wchar_t *format, va_list argptr)
638{
28ffb1f2
JJ
639#ifdef __VMS
640#if (__DECCXX_VER >= 70100000) && !defined(__STD_CFRONT) && !defined( __NONAMESPACE_STD )
641 return std::vswscanf(str, wxFormatConverter(format), argptr);
642#else
643 return vswscanf(str, wxFormatConverter(format), argptr);
644#endif
645#else
646 return vswscanf(str, wxFormatConverter(format), argptr);
647#endif
eb6cb207 648}
52de37c7 649#endif
2523e9b7
VS
650
651
652// ----------------------------------------------------------------------------
653// wrappers to printf and scanf function families
654// ----------------------------------------------------------------------------
655
d1f6e2cf
VS
656#if !wxUSE_UTF8_LOCALE_ONLY
657int wxDoSprintfWchar(char *str, const wxChar *format, ...)
dd0ef332
VS
658{
659 va_list argptr;
660 va_start(argptr, format);
661
2523e9b7 662 int rv = wxVsprintf(str, format, argptr);
dd0ef332
VS
663
664 va_end(argptr);
2523e9b7
VS
665 return rv;
666}
d1f6e2cf
VS
667#endif // !wxUSE_UTF8_LOCALE_ONLY
668
669#if wxUSE_UNICODE_UTF8
670int wxDoSprintfUtf8(char *str, const char *format, ...)
671{
672 va_list argptr;
673 va_start(argptr, format);
674
675 int rv = wxVsprintf(str, format, argptr);
676
677 va_end(argptr);
678 return rv;
679}
680#endif // wxUSE_UNICODE_UTF8
2523e9b7
VS
681
682#if wxUSE_UNICODE
d1f6e2cf
VS
683
684#if !wxUSE_UTF8_LOCALE_ONLY
685int wxDoSprintfWchar(wchar_t *str, const wxChar *format, ...)
2523e9b7
VS
686{
687 va_list argptr;
688 va_start(argptr, format);
dd0ef332 689
2523e9b7
VS
690 int rv = wxVsprintf(str, format, argptr);
691
692 va_end(argptr);
693 return rv;
dd0ef332 694}
d1f6e2cf
VS
695#endif // !wxUSE_UTF8_LOCALE_ONLY
696
697#if wxUSE_UNICODE_UTF8
698int wxDoSprintfUtf8(wchar_t *str, const char *format, ...)
699{
700 va_list argptr;
701 va_start(argptr, format);
702
703 int rv = wxVsprintf(str, format, argptr);
704
705 va_end(argptr);
706 return rv;
707}
708#endif // wxUSE_UNICODE_UTF8
709
710#endif // wxUSE_UNICODE
711
712#if !wxUSE_UTF8_LOCALE_ONLY
713int wxDoSnprintfWchar(char *str, size_t size, const wxChar *format, ...)
714{
715 va_list argptr;
716 va_start(argptr, format);
dd0ef332 717
d1f6e2cf
VS
718 int rv = wxVsnprintf(str, size, format, argptr);
719
720 va_end(argptr);
721 return rv;
722}
723#endif // !wxUSE_UTF8_LOCALE_ONLY
724
725#if wxUSE_UNICODE_UTF8
726int wxDoSnprintfUtf8(char *str, size_t size, const char *format, ...)
dd0ef332
VS
727{
728 va_list argptr;
2523e9b7 729 va_start(argptr, format);
dd0ef332 730
2523e9b7 731 int rv = wxVsnprintf(str, size, format, argptr);
dd0ef332
VS
732
733 va_end(argptr);
2523e9b7
VS
734 return rv;
735}
d1f6e2cf 736#endif // wxUSE_UNICODE_UTF8
dd0ef332 737
2523e9b7 738#if wxUSE_UNICODE
d1f6e2cf
VS
739
740#if !wxUSE_UTF8_LOCALE_ONLY
741int wxDoSnprintfWchar(wchar_t *str, size_t size, const wxChar *format, ...)
2523e9b7
VS
742{
743 va_list argptr;
744 va_start(argptr, format);
745
746 int rv = wxVsnprintf(str, size, format, argptr);
747
748 va_end(argptr);
749 return rv;
dd0ef332 750}
d1f6e2cf
VS
751#endif // !wxUSE_UTF8_LOCALE_ONLY
752
753#if wxUSE_UNICODE_UTF8
754int wxDoSnprintfUtf8(wchar_t *str, size_t size, const char *format, ...)
755{
756 va_list argptr;
757 va_start(argptr, format);
758
759 int rv = wxVsnprintf(str, size, format, argptr);
760
761 va_end(argptr);
762 return rv;
763}
764#endif // wxUSE_UNICODE_UTF8
765
766#endif // wxUSE_UNICODE
dd0ef332 767
2523e9b7
VS
768
769#ifdef HAVE_BROKEN_VSNPRINTF_DECL
770 #define vsnprintf wx_fixed_vsnprintf
771#endif
772
773#if wxUSE_UNICODE
d1f6e2cf
VS
774
775#if !wxUSE_UTF8_LOCALE_ONLY
2523e9b7 776static int ConvertStringToBuf(const wxString& s, char *out, size_t outsize)
dd0ef332 777{
2523e9b7
VS
778 const wxWX2WCbuf buf = s.wc_str();
779
780 size_t len = wxConvLibc.FromWChar(out, outsize, buf);
781 if ( len != wxCONV_FAILED )
782 return len-1;
783 else
784 return wxConvLibc.FromWChar(NULL, 0, buf);
dd0ef332 785}
d1f6e2cf 786#endif // !wxUSE_UTF8_LOCALE_ONLY
dd0ef332 787
2523e9b7
VS
788#if wxUSE_UNICODE_UTF8
789static int ConvertStringToBuf(const wxString& s, wchar_t *out, size_t outsize)
dd0ef332 790{
2523e9b7
VS
791 const wxWX2WCbuf buf(s.wc_str());
792 size_t len = wxWcslen(buf);
793 if ( outsize > len )
794 memcpy(out, buf, (len+1) * sizeof(wchar_t));
795 // else: not enough space
796 return len;
dd0ef332 797}
d1f6e2cf 798#endif // wxUSE_UNICODE_UTF8
dd0ef332 799
2523e9b7
VS
800template<typename T>
801static size_t PrintfViaString(T *out, size_t outsize,
802 const wxString& format, va_list argptr)
dd0ef332 803{
2523e9b7 804 wxString s;
c6255a6e 805 s.PrintfV(format, argptr);
2523e9b7
VS
806
807 return ConvertStringToBuf(s, out, outsize);
dd0ef332 808}
2523e9b7 809#endif // wxUSE_UNICODE
dd0ef332 810
2523e9b7 811int wxVsprintf(char *str, const wxString& format, va_list argptr)
dd0ef332 812{
2523e9b7 813#if wxUSE_UTF8_LOCALE_ONLY
c6255a6e 814 return vsprintf(str, format.wx_str(), argptr);
2523e9b7
VS
815#else
816 #if wxUSE_UNICODE_UTF8
817 if ( wxLocaleIsUtf8 )
c6255a6e 818 return vsprintf(str, format.wx_str(), argptr);
2523e9b7
VS
819 else
820 #endif
821 #if wxUSE_UNICODE
c6255a6e 822 return PrintfViaString(str, wxNO_LEN, format, argptr);
2523e9b7 823 #else
52de37c7 824 return wxCRT_VsprintfA(str, format.mb_str(), argptr);
2523e9b7
VS
825 #endif
826#endif
dd0ef332 827}
dd0ef332 828
2523e9b7
VS
829#if wxUSE_UNICODE
830int wxVsprintf(wchar_t *str, const wxString& format, va_list argptr)
dd0ef332 831{
2523e9b7 832#if wxUSE_UNICODE_WCHAR
52de37c7 833 return wxCRT_VsprintfW(str, format.wc_str(), argptr);
2523e9b7
VS
834#else // wxUSE_UNICODE_UTF8
835 #if !wxUSE_UTF8_LOCALE_ONLY
836 if ( !wxLocaleIsUtf8 )
52de37c7 837 return wxCRT_VsprintfW(str, format.wc_str(), argptr);
2523e9b7
VS
838 else
839 #endif
c6255a6e 840 return PrintfViaString(str, wxNO_LEN, format, argptr);
2523e9b7 841#endif // wxUSE_UNICODE_UTF8
dd0ef332 842}
2523e9b7 843#endif // wxUSE_UNICODE
dd0ef332 844
2523e9b7
VS
845int wxVsnprintf(char *str, size_t size, const wxString& format, va_list argptr)
846{
847 int rv;
2523e9b7 848#if wxUSE_UTF8_LOCALE_ONLY
52de37c7 849 rv = wxCRT_VsnprintfA(str, size, format.wx_str(), argptr);
2523e9b7
VS
850#else
851 #if wxUSE_UNICODE_UTF8
852 if ( wxLocaleIsUtf8 )
52de37c7 853 rv = wxCRT_VsnprintfA(str, size, format.wx_str(), argptr);
2523e9b7
VS
854 else
855 #endif
856 #if wxUSE_UNICODE
857 {
858 // NB: if this code is called, then wxString::PrintV() would use the
859 // wchar_t* version of wxVsnprintf(), so it's safe to use PrintV()
860 // from here
c6255a6e 861 rv = PrintfViaString(str, size, format, argptr);
2523e9b7
VS
862 }
863 #else
52de37c7 864 rv = wxCRT_VsnprintfA(str, size, format.mb_str(), argptr);
2523e9b7
VS
865 #endif
866#endif
867
868 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
869 // doesn't nul terminate on truncation.
870 str[size - 1] = 0;
871
872 return rv;
873}
874
875#if wxUSE_UNICODE
876int wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr)
877{
878 int rv;
2523e9b7
VS
879
880#if wxUSE_UNICODE_WCHAR
52de37c7 881 rv = wxCRT_VsnprintfW(str, size, format.wc_str(), argptr);
2523e9b7
VS
882#else // wxUSE_UNICODE_UTF8
883 #if !wxUSE_UTF8_LOCALE_ONLY
884 if ( !wxLocaleIsUtf8 )
52de37c7 885 rv = wxCRT_VsnprintfW(str, size, format.wc_str(), argptr);
2523e9b7
VS
886 else
887 #endif
888 {
889 // NB: if this code is called, then wxString::PrintV() would use the
890 // char* version of wxVsnprintf(), so it's safe to use PrintV()
891 // from here
c6255a6e 892 rv = PrintfViaString(str, size, format, argptr);
2523e9b7
VS
893 }
894#endif // wxUSE_UNICODE_UTF8
895
896 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
897 // doesn't nul terminate on truncation.
898 str[size - 1] = 0;
899
900 return rv;
901}
902#endif // wxUSE_UNICODE
dd0ef332
VS
903
904#if wxUSE_WCHAR_T
905
906// ----------------------------------------------------------------------------
907// ctype.h stuff (currently unused)
908// ----------------------------------------------------------------------------
909
dd0ef332
VS
910#ifdef wxNEED_WX_MBSTOWCS
911
912WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
913{
914 if (!out)
915 {
916 size_t outsize = 0;
917 while(*in++)
918 outsize++;
919 return outsize;
920 }
921
922 const char* origin = in;
923
924 while (outlen-- && *in)
925 {
926 *out++ = (wchar_t) *in++;
927 }
928
929 *out = '\0';
930
931 return in - origin;
932}
933
934WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
935{
936 if (!out)
937 {
938 size_t outsize = 0;
939 while(*in++)
940 outsize++;
941 return outsize;
942 }
943
944 const wchar_t* origin = in;
945
946 while (outlen-- && *in)
947 {
948 *out++ = (char) *in++;
949 }
950
951 *out = '\0';
952
953 return in - origin;
954}
955
956#endif // wxNEED_WX_MBSTOWCS
957
52de37c7
VS
958#ifndef wxCRT_StrdupA
959WXDLLEXPORT char *wxCRT_StrdupA(const char *s)
dd0ef332
VS
960{
961 return strcpy((char *)malloc(strlen(s) + 1), s);
962}
52de37c7 963#endif // wxCRT_StrdupA
dd0ef332 964
52de37c7
VS
965#ifndef wxCRT_StrdupW
966WXDLLEXPORT wchar_t * wxCRT_StrdupW(const wchar_t *pwz)
dd0ef332
VS
967{
968 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
969 wchar_t *ret = (wchar_t *) malloc(size);
970 memcpy(ret, pwz, size);
971 return ret;
972}
52de37c7 973#endif // wxCRT_StrdupW
dd0ef332 974
52de37c7
VS
975#ifndef wxCRT_StricmpA
976int WXDLLEXPORT wxCRT_StricmpA(const char *psz1, const char *psz2)
977{
978 register char c1, c2;
979 do {
980 c1 = wxTolower(*psz1++);
981 c2 = wxTolower(*psz2++);
982 } while ( c1 && (c1 == c2) );
983 return c1 - c2;
984}
985#endif // !defined(wxCRT_StricmpA)
dd0ef332 986
52de37c7
VS
987#ifndef wxCRT_StricmpW
988int WXDLLEXPORT wxCRT_StricmpW(const wchar_t *psz1, const wchar_t *psz2)
dd0ef332 989{
52de37c7 990 register wchar_t c1, c2;
dd0ef332
VS
991 do {
992 c1 = wxTolower(*psz1++);
993 c2 = wxTolower(*psz2++);
994 } while ( c1 && (c1 == c2) );
995 return c1 - c2;
996}
52de37c7 997#endif // !defined(wxCRT_StricmpW)
dd0ef332 998
52de37c7
VS
999#ifndef wxCRT_StrnicmpA
1000int WXDLLEXPORT wxCRT_StrnicmpA(const char *s1, const char *s2, size_t n)
dd0ef332
VS
1001{
1002 // initialize the variables just to suppress stupid gcc warning
52de37c7 1003 register char c1 = 0, c2 = 0;
dd0ef332
VS
1004 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
1005 if (n) {
1006 if (c1 < c2) return -1;
1007 if (c1 > c2) return 1;
1008 }
1009 return 0;
1010}
52de37c7 1011#endif // !defined(wxCRT_StrnicmpA)
cb352236 1012
52de37c7
VS
1013#ifndef wxCRT_StrnicmpW
1014int WXDLLEXPORT wxCRT_StrnicmpW(const wchar_t *s1, const wchar_t *s2, size_t n)
cb352236 1015{
52de37c7
VS
1016 // initialize the variables just to suppress stupid gcc warning
1017 register wchar_t c1 = 0, c2 = 0;
1018 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
1019 if (n) {
1020 if (c1 < c2) return -1;
1021 if (c1 > c2) return 1;
1022 }
1023 return 0;
dd0ef332 1024}
52de37c7 1025#endif // !defined(wxCRT_StrnicmpW)
dd0ef332
VS
1026
1027// ----------------------------------------------------------------------------
1028// string.h functions
1029// ----------------------------------------------------------------------------
1030
410390cf
VS
1031// this (and wxCRT_StrncmpW below) are extern "C" because they are needed
1032// by regex code, the rest isn't needed, so it's not declared as extern "C"
1033#ifndef wxCRT_StrlenW
1034extern "C" WXDLLEXPORT size_t wxCRT_StrlenW(const wchar_t *s)
dd0ef332
VS
1035{
1036 size_t n = 0;
1037 while ( *s++ )
1038 n++;
1039
1040 return n;
1041}
52de37c7 1042#endif
dd0ef332 1043
410390cf
VS
1044// ----------------------------------------------------------------------------
1045// stdlib.h functions
1046// ----------------------------------------------------------------------------
dd0ef332 1047
52de37c7
VS
1048#ifndef wxCRT_GetenvW
1049wchar_t* WXDLLEXPORT wxCRT_GetenvW(const wchar_t *name)
dd0ef332 1050{
dd0ef332
VS
1051 // NB: buffer returned by getenv() is allowed to be overwritten next
1052 // time getenv() is called, so it is OK to use static string
1053 // buffer to hold the data.
f62262aa
VS
1054 static wxWCharBuffer value((wchar_t*)NULL);
1055 value = wxConvLibc.cMB2WC(getenv(wxConvLibc.cWC2MB(name)));
dd0ef332 1056 return value.data();
dd0ef332 1057}
52de37c7 1058#endif // !wxCRT_GetenvW
dd0ef332 1059
52de37c7 1060#ifndef wxCRT_StrftimeW
dd0ef332 1061WXDLLEXPORT size_t
52de37c7 1062wxCRT_StrftimeW(wchar_t *s, size_t maxsize, const wchar_t *fmt, const struct tm *tm)
dd0ef332
VS
1063{
1064 if ( !maxsize )
1065 return 0;
1066
1067 wxCharBuffer buf(maxsize);
1068
1069 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
1070 if ( !bufFmt )
1071 return 0;
1072
1073 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
1074 if ( !ret )
1075 return 0;
1076
1077 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
1078 if ( !wbuf )
1079 return 0;
1080
52de37c7
VS
1081 wxCRT_StrncpyW(s, wbuf, maxsize);
1082 return wxCRT_StrlenW(s);
dd0ef332 1083}
52de37c7 1084#endif // !wxCRT_StrftimeW
dd0ef332
VS
1085
1086#endif // wxUSE_WCHAR_T
1087
52de37c7
VS
1088template<typename T>
1089static wxULongLong_t
1090wxCRT_StrtoullBase(const T* nptr, T** endptr, int base, T* sign)
17482893
VZ
1091{
1092 wxULongLong_t sum = 0;
1093 wxString wxstr(nptr);
1094 wxString::const_iterator i = wxstr.begin();
1095 wxString::const_iterator end = wxstr.end();
1096
1097 // Skip spaces
1098 while ( i != end && wxIsspace(*i) ) i++;
1099
1100 // Starts with sign?
1101 *sign = wxT(' ');
1102 if ( i != end )
1103 {
52de37c7 1104 T c = *i;
17482893
VZ
1105 if ( c == wxT('+') || c == wxT('-') )
1106 {
1107 *sign = c;
1108 i++;
1109 }
1110 }
1111
1112 // Starts with 0x?
1113 if ( i != end && *i == wxT('0') )
1114 {
1115 i++;
1116 if ( i != end )
1117 {
1118 if ( *i == wxT('x') && (base == 16 || base == 0) )
1119 {
1120 base = 16;
1121 i++;
1122 }
1123 else
1124 {
1125 if ( endptr )
52de37c7 1126 *endptr = (T*) nptr;
17482893
VZ
1127 wxSET_ERRNO(EINVAL);
1128 return sum;
1129 }
1130 }
1131 else
1132 i--;
1133 }
1134
1135 if ( base == 0 )
1136 base = 10;
1137
1138 for ( ; i != end; i++ )
1139 {
1140 unsigned int n;
1141
52de37c7 1142 T c = *i;
17482893
VZ
1143 if ( c >= wxT('0') )
1144 {
1145 if ( c <= wxT('9') )
1146 n = c - wxT('0');
1147 else
1148 n = wxTolower(c) - wxT('a') + 10;
1149 }
1150 else
1151 break;
1152
1153 if ( n >= (unsigned int)base )
1154 // Invalid character (for this base)
1155 break;
1156
1157 wxULongLong_t prevsum = sum;
1158 sum = (sum * base) + n;
1159
1160 if ( sum < prevsum )
1161 {
1162 wxSET_ERRNO(ERANGE);
1163 break;
1164 }
1165 }
1166
1167 if ( endptr )
1168 {
52de37c7 1169 *endptr = (T*)(nptr + (i - wxstr.begin()));
17482893
VZ
1170 }
1171
1172 return sum;
1173}
1174
52de37c7
VS
1175template<typename T>
1176static wxULongLong_t wxCRT_DoStrtoull(const T* nptr, T** endptr, int base)
17482893 1177{
52de37c7
VS
1178 T sign;
1179 wxULongLong_t uval = wxCRT_StrtoullBase(nptr, endptr, base, &sign);
17482893
VZ
1180
1181 if ( sign == wxT('-') )
1182 {
1183 wxSET_ERRNO(ERANGE);
1184 uval = 0;
1185 }
1186
1187 return uval;
1188}
1189
52de37c7
VS
1190template<typename T>
1191static wxLongLong_t wxCRT_DoStrtoll(const T* nptr, T** endptr, int base)
17482893 1192{
52de37c7
VS
1193 T sign;
1194 wxULongLong_t uval = wxCRT_StrtoullBase(nptr, endptr, base, &sign);
17482893
VZ
1195 wxLongLong_t val = 0;
1196
1197 if ( sign == wxT('-') )
1198 {
1199 if ( uval <= wxULL(wxINT64_MAX+1) )
1200 {
1201 if ( uval == wxULL(wxINT64_MAX+1))
1202 val = -((wxLongLong_t)wxINT64_MAX) - 1;
1203 else
1204 val = -((wxLongLong_t)uval);
1205 }
1206 else
1207 {
1208 wxSET_ERRNO(ERANGE);
1209 }
1210 }
1211 else if ( uval <= wxINT64_MAX )
1212 {
1213 val = uval;
1214 }
1215 else
1216 {
1217 wxSET_ERRNO(ERANGE);
1218 }
1219
1220 return val;
1221}
52de37c7
VS
1222
1223#ifndef wxCRT_StrtollA
1224wxLongLong_t wxCRT_StrtollA(const char* nptr, char** endptr, int base)
1225 { return wxCRT_DoStrtoll(nptr, endptr, base); }
1226#endif
1227#ifndef wxCRT_StrtollW
1228wxLongLong_t wxCRT_StrtollW(const wchar_t* nptr, wchar_t** endptr, int base)
1229 { return wxCRT_DoStrtoll(nptr, endptr, base); }
1230#endif
1231
1232#ifndef wxCRT_StrtoullA
1233wxULongLong_t wxCRT_StrtoullA(const char* nptr, char** endptr, int base)
1234 { return wxCRT_DoStrtoull(nptr, endptr, base); }
1235#endif
1236#ifndef wxCRT_StrtoullW
1237wxULongLong_t wxCRT_StrtoullW(const wchar_t* nptr, wchar_t** endptr, int base)
1238 { return wxCRT_DoStrtoull(nptr, endptr, base); }
1239#endif
17482893 1240
dd0ef332
VS
1241// ----------------------------------------------------------------------------
1242// functions which we may need even if !wxUSE_WCHAR_T
1243// ----------------------------------------------------------------------------
1244
52de37c7
VS
1245template<typename T>
1246static T *wxCRT_DoStrtok(T *psz, const T *delim, T **save_ptr)
dd0ef332
VS
1247{
1248 if (!psz)
1249 {
1250 psz = *save_ptr;
1251 if ( !psz )
1252 return NULL;
1253 }
1254
1255 psz += wxStrspn(psz, delim);
1256 if (!*psz)
1257 {
52de37c7
VS
1258 *save_ptr = (T *)NULL;
1259 return (T *)NULL;
dd0ef332
VS
1260 }
1261
52de37c7 1262 T *ret = psz;
dd0ef332
VS
1263 psz = wxStrpbrk(psz, delim);
1264 if (!psz)
1265 {
52de37c7 1266 *save_ptr = (T*)NULL;
dd0ef332
VS
1267 }
1268 else
1269 {
1270 *psz = wxT('\0');
1271 *save_ptr = psz + 1;
1272 }
1273
1274 return ret;
1275}
1276
52de37c7
VS
1277#ifndef wxCRT_StrtokA
1278char *wxCRT_StrtokA(char *psz, const char *delim, char **save_ptr)
1279 { return wxCRT_DoStrtok(psz, delim, save_ptr); }
1280#endif
1281#ifndef wxCRT_StrtokW
1282wchar_t *wxCRT_StrtokW(wchar_t *psz, const wchar_t *delim, wchar_t **save_ptr)
1283 { return wxCRT_DoStrtok(psz, delim, save_ptr); }
1284#endif
dd0ef332
VS
1285
1286// ----------------------------------------------------------------------------
1287// missing C RTL functions
1288// ----------------------------------------------------------------------------
1289
1290#ifdef wxNEED_STRDUP
1291
1292char *strdup(const char *s)
1293{
1294 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
1295 if ( dest )
1296 strcpy( dest , s ) ;
1297 return dest ;
1298}
1299#endif // wxNEED_STRDUP
1300
1301#if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
1302
1303void *calloc( size_t num, size_t size )
1304{
1305 void** ptr = (void **)malloc(num * size);
1306 memset( ptr, 0, num * size);
1307 return ptr;
1308}
1309
1310#endif // __WXWINCE__ <= 211
1311
1312#ifdef __WXWINCE__
52de37c7 1313int wxCRT_RemoveW(const wchar_t *path)
dd0ef332
VS
1314{
1315 return ::DeleteFile(path) == 0;
1316}
52de37c7
VS
1317#endif
1318
1319#ifndef wxCRT_TmpnamW
1320wchar_t *wxCRT_TmpnamW(wchar_t *s)
1321{
1322 // tmpnam_r() returns NULL if s=NULL, do the same
1323 wxCHECK_MSG( s, NULL, "wxTmpnam must be called with a buffer" );
dd0ef332 1324
52de37c7
VS
1325#ifndef L_tmpnam
1326 #define L_tmpnam 1024
dd0ef332 1327#endif
52de37c7
VS
1328 wxCharBuffer buf(L_tmpnam);
1329 tmpnam(buf.data());
1330
1331 wxConvLibc.ToWChar(s, L_tmpnam+1, buf.data());
1332 return s;
1333}
1334#endif // !wxCRT_TmpnamW
cb352236
VS
1335
1336
52de37c7 1337// ============================================================================
cb352236 1338// wxLocaleIsUtf8
52de37c7 1339// ============================================================================
cb352236
VS
1340
1341#if wxUSE_UNICODE_UTF8
1342
1343#if !wxUSE_UTF8_LOCALE_ONLY
1344bool wxLocaleIsUtf8 = false; // the safer setting if not known
1345#endif
1346
1347static bool wxIsLocaleUtf8()
1348{
1349 // NB: we intentionally don't use wxLocale::GetSystemEncodingName(),
1350 // because a) it may be unavailable in some builds and b) has slightly
1351 // different semantics (default locale instead of current)
1352
1353#if defined(HAVE_LANGINFO_H) && defined(CODESET)
1354 // GNU libc provides current character set this way (this conforms to
1355 // Unix98)
1356 const char *charset = nl_langinfo(CODESET);
1357 if ( charset )
1358 {
1359 // "UTF-8" is used by modern glibc versions, but test other variants
1360 // as well, just in case:
e40dfb3a
VS
1361 if ( strcmp(charset, "UTF-8") == 0 ||
1362 strcmp(charset, "utf-8") == 0 ||
1363 strcmp(charset, "UTF8") == 0 ||
1364 strcmp(charset, "utf8") == 0 )
1365 {
1366 return true;
1367 }
cb352236 1368 }
cb352236 1369#endif
e40dfb3a
VS
1370
1371 // check if we're running under the "C" locale: it is 7bit subset
1372 // of UTF-8, so it can be safely used with the UTF-8 build:
1373 const char *lc_ctype = setlocale(LC_CTYPE, NULL);
1374 if ( lc_ctype &&
1375 (strcmp(lc_ctype, "C") == 0 || strcmp(lc_ctype, "POSIX") == 0) )
cb352236 1376 {
e40dfb3a 1377 return true;
cb352236 1378 }
e40dfb3a
VS
1379
1380 // we don't know what charset libc is using, so assume the worst
1381 // to be safe:
1382 return false;
cb352236
VS
1383}
1384
1385void wxUpdateLocaleIsUtf8()
1386{
1387#if wxUSE_UTF8_LOCALE_ONLY
1388 if ( !wxIsLocaleUtf8() )
1389 {
1390 wxLogFatalError(_T("This program requires UTF-8 locale to run."));
1391 }
1392#else // !wxUSE_UTF8_LOCALE_ONLY
1393 wxLocaleIsUtf8 = wxIsLocaleUtf8();
1394#endif
1395}
1396
c49f8879
VS
1397#endif // wxUSE_UNICODE_UTF8
1398
1399// ============================================================================
1400// wx wrappers for CRT functions
1401// ============================================================================
1402
52de37c7 1403#if wxUSE_UNICODE_WCHAR
19984725 1404 #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callW
52de37c7 1405#elif wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY
19984725
VS
1406 #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) \
1407 return_kw wxLocaleIsUtf8 ? callA : callW
52de37c7 1408#else // ANSI or UTF8 only
19984725 1409 #define CALL_ANSI_OR_UNICODE(return_kw, callA, callW) return_kw callA
52de37c7
VS
1410#endif
1411
1412int wxPuts(const wxString& s)
1413{
19984725
VS
1414 CALL_ANSI_OR_UNICODE(return,
1415 wxCRT_PutsA(s.mb_str()),
52de37c7
VS
1416 wxCRT_PutsW(s.wc_str()));
1417}
1418
1419int wxFputs(const wxString& s, FILE *stream)
1420{
19984725
VS
1421 CALL_ANSI_OR_UNICODE(return,
1422 wxCRT_FputsA(s.mb_str(), stream),
52de37c7
VS
1423 wxCRT_FputsW(s.wc_str(), stream));
1424}
1425
1426int wxFputc(const wxUniChar& c, FILE *stream)
1427{
1428#if !wxUSE_UNICODE // FIXME-UTF8: temporary, remove this with ANSI build
1429 return wxCRT_FputcA((char)c, stream);
1430#else
19984725
VS
1431 CALL_ANSI_OR_UNICODE(return,
1432 wxCRT_FputsA(c.AsUTF8(), stream),
52de37c7
VS
1433 wxCRT_FputcW((wchar_t)c, stream));
1434#endif
1435}
1436
1437void wxPerror(const wxString& s)
1438{
1439#ifdef wxCRT_PerrorW
19984725
VS
1440 CALL_ANSI_OR_UNICODE(wxEMPTY_PARAMETER_VALUE,
1441 wxCRT_PerrorA(s.mb_str()),
1442 wxCRT_PerrorW(s.wc_str()));
52de37c7
VS
1443#else
1444 wxCRT_PerrorA(s.mb_str());
1445#endif
1446}
1447
1448wchar_t *wxFgets(wchar_t *s, int size, FILE *stream)
1449{
1450 wxCHECK_MSG( s, NULL, "empty buffer passed to wxFgets()" );
1451
1452 wxCharBuffer buf(size - 1);
1453 // FIXME: this reads too little data if wxConvLibc uses UTF-8 ('size' wide
1454 // characters may be encoded by up to 'size'*4 bytes), but what
1455 // else can we do?
1456 if ( wxFgets(buf.data(), size, stream) == NULL )
1457 return NULL;
1458
1459 if ( wxConvLibc.ToWChar(s, size, buf, wxNO_LEN) == wxCONV_FAILED )
1460 return NULL;
1461
1462 return s;
1463}
c49f8879
VS
1464
1465// ----------------------------------------------------------------------------
1466// wxScanf() and friends
1467// ----------------------------------------------------------------------------
1468
eb6cb207 1469#ifndef __VISUALC__
c49f8879
VS
1470int wxVsscanf(const char *str, const char *format, va_list ap)
1471 { return wxCRT_VsscanfA(str, format, ap); }
1472int wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap)
eb6cb207 1473 { return wxCRT_VsscanfW(str, format, ap); }
c49f8879
VS
1474int wxVsscanf(const wxCharBuffer& str, const char *format, va_list ap)
1475 { return wxCRT_VsscanfA(str, format, ap); }
1476int wxVsscanf(const wxWCharBuffer& str, const wchar_t *format, va_list ap)
eb6cb207 1477 { return wxCRT_VsscanfW(str, format, ap); }
c49f8879
VS
1478int wxVsscanf(const wxString& str, const char *format, va_list ap)
1479 { return wxCRT_VsscanfA(str.mb_str(), format, ap); }
1480int wxVsscanf(const wxString& str, const wchar_t *format, va_list ap)
eb6cb207 1481 { return wxCRT_VsscanfW(str.wc_str(), format, ap); }
c49f8879
VS
1482int wxVsscanf(const wxCStrData& str, const char *format, va_list ap)
1483 { return wxCRT_VsscanfA(str.AsCharBuf(), format, ap); }
1484int wxVsscanf(const wxCStrData& str, const wchar_t *format, va_list ap)
eb6cb207
VS
1485 { return wxCRT_VsscanfW(str.AsWCharBuf(), format, ap); }
1486#endif // !__VISUALC__