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