]> git.saurik.com Git - wxWidgets.git/blob - src/common/wxchar.cpp
Put various #ifdefs vsnprintf() back in, they were
[wxWidgets.git] / src / common / wxchar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wxchar.cpp
3 // Purpose: wxChar implementation
4 // Author: Ove Kåven
5 // Modified by:
6 // Created: 09/04/99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWindows copyright
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "wxchar.h"
14 #endif
15
16 // ===========================================================================
17 // headers, declarations, constants
18 // ===========================================================================
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #define _ISOC9X_SOURCE 1 // to get vsscanf()
28 #define _BSD_SOURCE 1 // to still get strdup()
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <locale.h>
34 #include <time.h>
35
36 #ifndef WX_PRECOMP
37 #include "wx/defs.h"
38 #include "wx/wxchar.h"
39 #include "wx/string.h"
40 #include "wx/hash.h"
41 #endif
42
43 #include "wx/msgdlg.h"
44
45 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
46 #include <windef.h>
47 #include <winbase.h>
48 #include <winnls.h>
49 #include <winnt.h>
50 #endif
51
52 #if wxUSE_WCHAR_T
53 size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
54 {
55 if (buf) {
56 if (!n || !*psz) {
57 if (n) *buf = wxT('\0');
58 return 0;
59 }
60 return mbstowcs(buf, psz, n);
61 }
62
63 // assume that we have mbsrtowcs() too if we have wcsrtombs()
64 #ifdef HAVE_WCSRTOMBS
65 mbstate_t mbstate;
66 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
67 #else // !GNU libc
68 return mbstowcs((wchar_t *) NULL, psz, 0);
69 #endif // GNU
70 }
71
72 size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
73 {
74 if (buf) {
75 if (!n || !*pwz) {
76 // glibc2.1 chokes on null input
77 if (n) *buf = '\0';
78 return 0;
79 }
80 return wcstombs(buf, pwz, n);
81 }
82
83 #if HAVE_WCSRTOMBS
84 mbstate_t mbstate;
85 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
86 #else // !GNU libc
87 return wcstombs((char *) NULL, pwz, 0);
88 #endif // GNU
89 }
90 #endif // wxUSE_WCHAR_T
91
92 bool WXDLLEXPORT wxOKlibc()
93 {
94 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__)
95 // glibc 2.0 uses UTF-8 even when it shouldn't
96 wchar_t res = 0;
97 if ((MB_CUR_MAX == 2) &&
98 (wxMB2WC(&res, "\xdd\xa5", 1) == 1) &&
99 (res==0x765)) {
100 // this is UTF-8 allright, check whether that's what we want
101 char *cur_locale = setlocale(LC_CTYPE, NULL);
102 if ((strlen(cur_locale) < 4) ||
103 (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
104 (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
105 // nope, don't use libc conversion
106 return FALSE;
107 }
108 }
109 #endif
110 return TRUE;
111 }
112
113 #ifndef HAVE_WCSLEN
114 size_t WXDLLEXPORT wcslen(const wchar_t *s)
115 {
116 size_t len = 0;
117 while (s[len]) len++;
118 return len;
119 }
120 #endif
121
122 #ifdef wxNEED_PRINTF_CONVERSION
123
124 #define CONVERT_FORMAT_1 \
125 wxChar *new_format = (wxChar*) format; \
126 size_t old_len = wxStrlen( format ); \
127 int n = 0; \
128 size_t i; \
129 for (i = 0; i < old_len; i++) \
130 { \
131 if ( (format[i] == L'%') && \
132 ((i < old_len) && ((format[i+1] == L's') || (format[i+1] == L'c'))) && \
133 ((i == 0) || (format[i-1] != L'%')) ) \
134 { \
135 n++; \
136 } \
137 } \
138 \
139 if (n > 0) \
140 { \
141 new_format = new wxChar[old_len+n+1]; \
142 wxChar *s = new_format; \
143 \
144 for (i = 0; i < old_len+1; i++) \
145 { \
146 if ( (format[i] == L'%') && \
147 ((i < old_len) && ((format[i+1] == L's') || (format[i+1] == L'c'))) && \
148 ((i == 0) || (format[i-1] != L'%')) ) \
149 { \
150 *s = L'%'; \
151 s++; \
152 *s = L'l'; \
153 s++; \
154 } \
155 else \
156 { \
157 *s = format[i]; \
158 s++; \
159 } \
160 } \
161 }
162
163 #define CONVERT_FORMAT_2 \
164 if (n > 0) \
165 delete [] new_format;
166
167
168 int wxScanf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
169 {
170 CONVERT_FORMAT_1
171
172 va_list argptr;
173 va_start(argptr, format);
174
175 int ret = vwscanf( new_format, argptr );
176
177 CONVERT_FORMAT_2
178
179 va_end(argptr);
180
181 return ret;
182 }
183
184 int wxSscanf( const wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
185 {
186 CONVERT_FORMAT_1
187
188 va_list argptr;
189 va_start(argptr, format);
190
191 int ret = vswscanf( str, new_format, argptr );
192
193 CONVERT_FORMAT_2
194
195 va_end(argptr);
196
197 return ret;
198 }
199
200 int wxFscanf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
201 {
202 CONVERT_FORMAT_1
203
204 va_list argptr;
205 va_start(argptr, format);
206
207 int ret = vfwscanf(stream, new_format, argptr);
208
209 CONVERT_FORMAT_2
210
211 va_end(argptr);
212
213 return ret;
214 }
215
216 int wxVsscanf( const wxChar *str, const wxChar *format, va_list ap )
217 {
218 CONVERT_FORMAT_1
219
220 int ret = vswscanf( str, new_format, ap );
221
222 CONVERT_FORMAT_2
223
224 return ret;
225 }
226
227 int wxPrintf( const wxChar *format, ... ) ATTRIBUTE_PRINTF_2
228 {
229 CONVERT_FORMAT_1
230
231 va_list argptr;
232 va_start(argptr, format);
233
234 int ret = vwprintf( new_format, argptr );
235
236 CONVERT_FORMAT_2
237
238 va_end(argptr);
239
240 return ret;
241 }
242
243 int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... ) ATTRIBUTE_PRINTF_4
244 {
245 CONVERT_FORMAT_1
246
247 va_list argptr;
248 va_start(argptr, format);
249
250 int ret = vswprintf( str, size, new_format, argptr );
251
252 CONVERT_FORMAT_2
253
254 va_end(argptr);
255
256 return ret;
257 }
258
259 int wxSprintf( wxChar *str, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
260 {
261 CONVERT_FORMAT_1
262
263 va_list argptr;
264 va_start(argptr, format);
265
266 // Ugly
267 int ret = vswprintf( str, 10000, new_format, argptr );
268
269 CONVERT_FORMAT_2
270
271 va_end(argptr);
272
273 return ret;
274 }
275
276 int wxFprintf( FILE *stream, const wxChar *format, ... ) ATTRIBUTE_PRINTF_3
277 {
278 CONVERT_FORMAT_1
279
280 va_list argptr;
281 va_start( argptr, format );
282
283 int ret = vfwprintf( stream, new_format, argptr );
284
285 CONVERT_FORMAT_2
286
287 va_end(argptr);
288
289 return ret;
290 }
291
292 int wxVfprint( FILE *stream, const wxChar *format, va_list ap )
293 {
294 CONVERT_FORMAT_1
295
296 int ret = vfwprintf( stream, new_format, ap );
297
298 CONVERT_FORMAT_2
299
300 return ret;
301 }
302
303 int wxVprintf( const wxChar *format, va_list ap )
304 {
305 CONVERT_FORMAT_1
306
307 int ret = vwprintf( new_format, ap );
308
309 CONVERT_FORMAT_2
310
311 return ret;
312 }
313
314 int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list ap )
315 {
316 CONVERT_FORMAT_1
317
318 int ret = vswprintf( str, size, new_format, ap );
319
320 CONVERT_FORMAT_2
321
322 return ret;
323 }
324
325 int wxVsprintf( wxChar *str, const wxChar *format, va_list ap )
326 {
327 CONVERT_FORMAT_1
328
329 // This is so ugly
330 int ret = vswprintf(str, 10000, new_format, ap);
331
332 CONVERT_FORMAT_2
333
334 return ret;
335 }
336 #endif
337
338 // we want to find out if the current platform supports vsnprintf()-like
339 // function: for Unix this is done with configure, for Windows we test the
340 // compiler explicitly.
341 //
342 // FIXME currently, this is only for ANSI (!Unicode) strings, so we call this
343 // function wxVsnprintfA (A for ANSI), should also find one for Unicode
344 // strings in Unicode build
345 #ifdef __WXMSW__
346 #if defined(__VISUALC__) || (defined(__MINGW32__) && wxUSE_NORLANDER_HEADERS)
347 #define wxVsnprintfA _vsnprintf
348 #endif
349 #elif defined(__WXMAC__)
350 #define wxVsnprintfA vsnprintf
351 #else // !Windows
352 #ifdef HAVE_VSNPRINTF
353 #define wxVsnprintfA vsnprintf
354 #endif
355 #endif // Windows/!Windows
356
357 #ifndef wxVsnprintfA
358 // in this case we'll use vsprintf() (which is ANSI and thus should be
359 // always available), but it's unsafe because it doesn't check for buffer
360 // size - so give a warning
361 #define wxVsnprintfA(buf, len, format, arg) vsprintf(buf, format, arg)
362
363 #if defined(__VISUALC__)
364 #pragma message("Using sprintf() because no snprintf()-like function defined")
365 #elif defined(__GNUG__)
366 #warning "Using sprintf() because no snprintf()-like function defined"
367 #endif //compiler
368 #endif // no vsnprintf
369
370 #if defined(_AIX)
371 // AIX has vsnprintf, but there's no prototype in the system headers.
372 extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap);
373 #endif
374
375 #if !defined(wxVsnprintf) && !defined(wxHAS_VSNPRINTF)
376 int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len,
377 const wxChar *format, va_list argptr)
378 {
379 #if wxUSE_UNICODE
380 wxString s;
381 int iLen = s.PrintfV(format, argptr);
382 if ( iLen != -1 )
383 {
384 wxStrncpy(buf, s.c_str(), len);
385 buf[len-1] = wxT('\0');
386 }
387
388 return iLen;
389 #else // ANSI
390 // vsnprintf() will not terminate the string with '\0' if there is not
391 // enough place, but we want the string to always be NUL terminated
392 int rc = wxVsnprintfA(buf, len - 1, format, argptr);
393 if ( rc == -1 )
394 {
395 buf[len] = 0;
396 }
397
398 return rc;
399 #endif // Unicode/ANSI
400 }
401 #endif
402
403 #if !defined(wxSnprintf) && !defined(wxHAS_SNPRINTF)
404 int WXDLLEXPORT wxSnprintf(wxChar *buf, size_t len,
405 const wxChar *format, ...)
406 {
407 va_list argptr;
408 va_start(argptr, format);
409
410 int iLen = wxVsnprintf(buf, len, format, argptr);
411
412 va_end(argptr);
413
414 return iLen;
415 }
416 #endif
417
418 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
419 inline WORD wxMSW_ctype(wxChar ch)
420 {
421 WORD ret;
422 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
423 return ret;
424 }
425
426 WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
427 WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
428 WXDLLEXPORT int wxIsctrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
429 WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
430 WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
431 WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
432 WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
433 WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
434 WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
435 WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
436 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
437 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
438 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
439 #endif
440
441 #ifndef wxStrdup
442 WXDLLEXPORT wxChar * wxStrdup(const wxChar *psz)
443 {
444 size_t size = (wxStrlen(psz) + 1) * sizeof(wxChar);
445 wxChar *ret = (wxChar *) malloc(size);
446 memcpy(ret, psz, size);
447 return ret;
448 }
449 #endif
450
451 #ifndef wxStricmp
452 int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
453 {
454 register wxChar c1, c2;
455 do {
456 c1 = wxTolower(*psz1++);
457 c2 = wxTolower(*psz2++);
458 } while ( c1 && (c1 == c2) );
459 return c1 - c2;
460 }
461 #endif
462
463 #ifndef wxStricmp
464 int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
465 {
466 register wxChar c1, c2;
467 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
468 if (n) {
469 if (c1 < c2) return -1;
470 if (c1 > c2) return 1;
471 }
472 return 0;
473 }
474 #endif
475
476 #ifndef wxStrtok
477 WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
478 {
479 if (!psz) psz = *save_ptr;
480 psz += wxStrspn(psz, delim);
481 if (!*psz) {
482 *save_ptr = (wxChar *)NULL;
483 return (wxChar *)NULL;
484 }
485 wxChar *ret = psz;
486 psz = wxStrpbrk(psz, delim);
487 if (!psz) *save_ptr = (wxChar*)NULL;
488 else {
489 *psz = wxT('\0');
490 *save_ptr = psz + 1;
491 }
492 return ret;
493 }
494 #endif
495
496 #ifndef wxSetlocale
497 WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
498 {
499 char *localeOld = setlocale(category, wxConvLocal.cWX2MB(locale));
500
501 return wxWCharBuffer(wxConvLocal.cMB2WC(localeOld));
502 }
503 #endif
504
505 #ifdef wxNEED_WX_STRING_H
506 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
507 {
508 wxChar *ret = dest;
509 while (*dest) dest++;
510 while ((*dest++ = *src++));
511 return ret;
512 }
513
514 WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
515 {
516 // be careful here as the terminating NUL makes part of the string
517 while ( *s != c )
518 {
519 if ( !*s++ )
520 return NULL;
521 }
522
523 return s;
524 }
525
526 WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
527 {
528 while ((*s1 == *s2) && *s1) s1++, s2++;
529 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
530 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
531 return 0;
532 }
533
534 WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
535 {
536 wxChar *ret = dest;
537 while ((*dest++ = *src++));
538 return ret;
539 }
540
541 WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
542 {
543 wxChar *ret = dest;
544 while (*dest) dest++;
545 while (n && (*dest++ = *src++)) n--;
546 return ret;
547 }
548
549 WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
550 {
551 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
552 if (n) {
553 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
554 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
555 }
556 return 0;
557 }
558
559 WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
560 {
561 wxChar *ret = dest;
562 while (n && (*dest++ = *src++)) n--;
563 while (n) *dest++=0, n--; // the docs specify padding with zeroes
564 return ret;
565 }
566
567 WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
568 {
569 while (*s && !wxStrchr(accept, *s))
570 s++;
571
572 return *s ? s : NULL;
573 }
574
575 WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
576 {
577 const wxChar *ret = NULL;
578 do
579 {
580 if ( *s == c )
581 ret = s;
582 s++;
583 }
584 while ( *s );
585
586 return ret;
587 }
588
589 WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
590 {
591 size_t len = 0;
592 while (wxStrchr(accept, *s++)) len++;
593 return len;
594 }
595
596 WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
597 {
598 wxCHECK_RET( needle, NULL, _T("NULL argument in wxStrstr") );
599
600 // VZ: this is not exactly the most efficient string search algorithm...
601
602 const size_t len = wxStrlen(needle);
603
604 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
605 {
606 if ( !wxStrncmp(fnd, needle, len) )
607 return fnd;
608
609 haystack = fnd + 1;
610 }
611
612 return NULL;
613 }
614
615 WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
616 {
617 const wxChar *start = nptr;
618
619 // FIXME: only correct for C locale
620 while (wxIsspace(*nptr)) nptr++;
621 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
622 while (wxIsdigit(*nptr)) nptr++;
623 if (*nptr == wxT('.')) {
624 nptr++;
625 while (wxIsdigit(*nptr)) nptr++;
626 }
627 if (*nptr == wxT('E') || *nptr == wxT('e')) {
628 nptr++;
629 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
630 while (wxIsdigit(*nptr)) nptr++;
631 }
632
633 wxString data(nptr, nptr-start);
634 wxWX2MBbuf dat = data.mb_str(wxConvLocal);
635 char *rdat = wxMBSTRINGCAST dat;
636 double ret = strtod(dat, &rdat);
637
638 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
639
640 return ret;
641 }
642
643 WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
644 {
645 const wxChar *start = nptr;
646
647 // FIXME: only correct for C locale
648 while (wxIsspace(*nptr)) nptr++;
649 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
650 if (((base == 0) || (base == 16)) &&
651 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
652 nptr += 2;
653 base = 16;
654 }
655 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
656 else if (base == 0) base = 10;
657
658 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
659 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
660
661 wxString data(nptr, nptr-start);
662 wxWX2MBbuf dat = data.mb_str(wxConvLocal);
663 char *rdat = wxMBSTRINGCAST dat;
664 long int ret = strtol(dat, &rdat, base);
665
666 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
667
668 return ret;
669 }
670 #endif
671
672 #ifdef wxNEED_WX_STDIO_H
673 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
674 {
675 char mode_buffer[10];
676 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
677 mode_buffer[i] = (char) mode[i];
678
679 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
680 }
681
682 WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
683 {
684 char mode_buffer[10];
685 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
686 mode_buffer[i] = (char) mode[i];
687
688 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
689 }
690
691 WXDLLEXPORT int wxRemove(const wxChar *path)
692 {
693 return remove( wxConvFile.cWX2MB(path) );
694 }
695
696 WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
697 {
698 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
699 }
700 #endif
701
702 #ifndef wxAtof
703 double WXDLLEXPORT wxAtof(const wxChar *psz)
704 {
705 return atof(wxConvLocal.cWX2MB(psz));
706 }
707 #endif
708
709 #ifdef wxNEED_WX_STDLIB_H
710 int WXDLLEXPORT wxAtoi(const wxChar *psz)
711 {
712 return atoi(wxConvLocal.cWX2MB(psz));
713 }
714
715 long WXDLLEXPORT wxAtol(const wxChar *psz)
716 {
717 return atol(wxConvLocal.cWX2MB(psz));
718 }
719
720 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
721 {
722 static wxHashTable env;
723
724 // check if we already have stored the converted env var
725 wxObject *data = env.Get(name);
726 if (!data)
727 {
728 // nope, retrieve it,
729 #if wxUSE_UNICODE
730 wxCharBuffer buffer = wxConvLocal.cWX2MB(name);
731 // printf( "buffer %s\n", (const char*) buffer );
732 const char *val = getenv( (const char *)buffer );
733 #else
734 const char *val = getenv( name );
735 #endif
736
737 if (!val) return (wxChar *)NULL;
738 // printf( "home %s\n", val );
739
740 // convert it,
741 #ifdef wxUSE_UNICODE
742 data = (wxObject *)new wxString(val, wxConvLocal);
743 #else
744 data = (wxObject *)new wxString(val);
745 #endif
746
747 // and store it
748 env.Put(name, data);
749 }
750 // return converted env var
751 return (wxChar *)((wxString *)data)->c_str();
752 }
753
754 int WXDLLEXPORT wxSystem(const wxChar *psz)
755 {
756 return system(wxConvLocal.cWX2MB(psz));
757 }
758
759 #endif
760
761 #ifdef wxNEED_WX_TIME_H
762 WXDLLEXPORT size_t wxStrftime(wxChar *s, size_t max, const wxChar *fmt, const struct tm *tm)
763 {
764 if (!max) return 0;
765
766 char *buf = (char *)malloc(max);
767 size_t ret = strftime(buf, max, wxConvLocal.cWX2MB(fmt), tm);
768 if (ret)
769 {
770 wxStrcpy(s, wxConvLocal.cMB2WX(buf));
771 free(buf);
772 return wxStrlen(s);
773 }
774 else
775 {
776 free(buf);
777 *s = 0;
778 return 0;
779 }
780 }
781 #endif