]> git.saurik.com Git - wxWidgets.git/blob - src/common/wxchar.cpp
Commited FRM's stockitem patch (empty stock items).
[wxWidgets.git] / src / common / wxchar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/wxchar.cpp
3 // Purpose: wxChar 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 #define _ISOC9X_SOURCE 1 // to get vsscanf()
24 #define _BSD_SOURCE 1 // to still get strdup()
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifndef __WXWINCE__
31 #include <time.h>
32 #include <locale.h>
33 #else
34 #include "wx/msw/wince/time.h"
35 #endif
36
37 #ifndef WX_PRECOMP
38 #include "wx/wxchar.h"
39 #include "wx/string.h"
40 #include "wx/hash.h"
41 #endif
42 #include "wx/utils.h" // for wxMin and wxMax
43
44 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
45 #include <windef.h>
46 #include <winbase.h>
47 #include <winnls.h>
48 #include <winnt.h>
49 #endif
50
51 #if defined(__MWERKS__) && __MSL__ >= 0x6000
52 namespace std {}
53 using namespace std ;
54 #endif
55
56 #if wxUSE_WCHAR_T
57 size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
58 {
59 // assume that we have mbsrtowcs() too if we have wcsrtombs()
60 #ifdef HAVE_WCSRTOMBS
61 mbstate_t mbstate;
62 memset(&mbstate, 0, sizeof(mbstate_t));
63 #endif
64
65 if (buf) {
66 if (!n || !*psz) {
67 if (n) *buf = wxT('\0');
68 return 0;
69 }
70 #ifdef HAVE_WCSRTOMBS
71 return mbsrtowcs(buf, &psz, n, &mbstate);
72 #else
73 return wxMbstowcs(buf, psz, n);
74 #endif
75 }
76
77 // note that we rely on common (and required by Unix98 but unfortunately not
78 // C99) extension which allows to call mbs(r)towcs() with NULL output pointer
79 // to just get the size of the needed buffer -- this is needed as otherwise
80 // we have no idea about how much space we need and if the CRT doesn't
81 // support it (the only currently known example being Metrowerks, see
82 // wx/wxchar.h) we don't use its mbstowcs() at all
83 #ifdef HAVE_WCSRTOMBS
84 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
85 #else
86 return wxMbstowcs((wchar_t *) NULL, psz, 0);
87 #endif
88 }
89
90 size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
91 {
92 #ifdef HAVE_WCSRTOMBS
93 mbstate_t mbstate;
94 memset(&mbstate, 0, sizeof(mbstate_t));
95 #endif
96
97 if (buf) {
98 if (!n || !*pwz) {
99 // glibc2.1 chokes on null input
100 if (n) *buf = '\0';
101 return 0;
102 }
103 #ifdef HAVE_WCSRTOMBS
104 return wcsrtombs(buf, &pwz, n, &mbstate);
105 #else
106 return wxWcstombs(buf, pwz, n);
107 #endif
108 }
109
110 #ifdef HAVE_WCSRTOMBS
111 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
112 #else
113 return wxWcstombs((char *) NULL, pwz, 0);
114 #endif
115 }
116 #endif // wxUSE_WCHAR_T
117
118 bool WXDLLEXPORT wxOKlibc()
119 {
120 #if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__)
121 // glibc 2.0 uses UTF-8 even when it shouldn't
122 wchar_t res = 0;
123 if ((MB_CUR_MAX == 2) &&
124 (wxMB2WC(&res, "\xdd\xa5", 1) == 1) &&
125 (res==0x765)) {
126 // this is UTF-8 allright, check whether that's what we want
127 char *cur_locale = setlocale(LC_CTYPE, NULL);
128 if ((strlen(cur_locale) < 4) ||
129 (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
130 (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
131 // nope, don't use libc conversion
132 return false;
133 }
134 }
135 #endif
136 return true;
137 }
138
139 // ============================================================================
140 // printf() functions business
141 // ============================================================================
142
143 // special test mode: define all functions below even if we don't really need
144 // them to be able to test them
145 #ifdef wxTEST_PRINTF
146 #undef wxFprintf
147 #undef wxPrintf
148 #undef wxSprintf
149 #undef wxVfprintf
150 #undef wxVsprintf
151 #undef wxVprintf
152 #undef wxVsnprintf_
153 #undef wxSnprintf_
154
155 #define wxNEED_WPRINTF
156
157 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr );
158 #endif
159
160 // ----------------------------------------------------------------------------
161 // implement [v]snprintf() if the system doesn't provide a safe one
162 // or if the system's one does not support positional parameters
163 // (very useful for i18n purposes)
164 // ----------------------------------------------------------------------------
165
166 #if !defined(wxVsnprintf_)
167
168 // wxUSE_STRUTILS says our wxVsnprintf_ implementation to use or not to
169 // use wxStrlen and wxStrncpy functions over one-char processing loops.
170 //
171 // Some benchmarking revealed that wxUSE_STRUTILS == 1 has the following
172 // effects:
173 // -> on Windows:
174 // when in ANSI mode, this setting does not change almost anything
175 // when in Unicode mode, it gives ~ 50% of slowdown !
176 // -> on Linux:
177 // both in ANSI and Unicode mode it gives ~ 60% of speedup !
178 //
179 #if defined(WIN32) && wxUSE_UNICODE
180 #define wxUSE_STRUTILS 0
181 #else
182 #define wxUSE_STRUTILS 1
183 #endif
184
185 // some limits of our implementation
186 #define wxMAX_SVNPRINTF_ARGUMENTS 64
187 #define wxMAX_SVNPRINTF_FLAGBUFFER_LEN 32
188
189 // the conversion specifiers accepted by wxVsnprintf_
190 enum wxPrintfArgType {
191 wxPAT_INVALID = -1,
192
193 wxPAT_INT, // %d, %i, %o, %u, %x, %X
194 wxPAT_LONGINT, // %ld, etc
195 #if SIZEOF_LONG_LONG
196 wxPAT_LONGLONGINT, // %Ld, etc
197 #endif
198 wxPAT_SIZET, // %Zd, etc
199
200 wxPAT_DOUBLE, // %e, %E, %f, %g, %G
201 wxPAT_LONGDOUBLE, // %le, etc
202
203 wxPAT_POINTER, // %p
204
205 wxPAT_CHAR, // %hc (in ANSI mode: %c, too)
206 wxPAT_WCHAR, // %lc (in Unicode mode: %c, too)
207
208 wxPAT_PCHAR, // %s (related to a char *)
209 wxPAT_PWCHAR, // %s (related to a wchar_t *)
210
211 wxPAT_NINT, // %n
212 wxPAT_NSHORTINT, // %hn
213 wxPAT_NLONGINT // %ln
214 };
215
216 // an argument passed to wxVsnprintf_
217 typedef union {
218 int pad_int; // %d, %i, %o, %u, %x, %X
219 long int pad_longint; // %ld, etc
220 #if SIZEOF_LONG_LONG
221 long long int pad_longlongint; // %Ld, etc
222 #endif
223 size_t pad_sizet; // %Zd, etc
224
225 double pad_double; // %e, %E, %f, %g, %G
226 long double pad_longdouble; // %le, etc
227
228 void *pad_pointer; // %p
229
230 char pad_char; // %hc (in ANSI mode: %c, too)
231 wchar_t pad_wchar; // %lc (in Unicode mode: %c, too)
232
233 char *pad_pchar; // %s (related to a char *)
234 wchar_t *pad_pwchar; // %s (related to a wchar_t *)
235
236 int *pad_nint; // %n
237 short int *pad_nshortint; // %hn
238 long int *pad_nlongint; // %ln
239 } wxPrintfArg;
240
241
242 // Contains parsed data relative to a conversion specifier given to
243 // wxVsnprintf_ and parsed from the format string
244 // NOTE: in C++ there is almost no difference between struct & classes thus
245 // there is no performance gain by using a struct here...
246 class wxPrintfConvSpec
247 {
248 public:
249
250 // the position of the argument relative to this conversion specifier
251 size_t pos;
252
253 // the type of this conversion specifier
254 wxPrintfArgType type;
255
256 // the minimum and maximum width
257 // when one of this var is set to -1 it means: use the following argument
258 // in the stack as minimum/maximum width for this conversion specifier
259 int min_width, max_width;
260
261 // does the argument need to the be aligned to left ?
262 bool adj_left;
263
264 // pointer to the '%' of this conversion specifier in the format string
265 // NOTE: this points somewhere in the string given to the Parse() function -
266 // it's task of the caller ensure that memory is still valid !
267 const wxChar *argpos;
268
269 // pointer to the last character of this conversion specifier in the
270 // format string
271 // NOTE: this points somewhere in the string given to the Parse() function -
272 // it's task of the caller ensure that memory is still valid !
273 const wxChar *argend;
274
275 // a little buffer where formatting flags like #+\.hlqLZ are stored by Parse()
276 // for use in Process()
277 // NB: this buffer can be safely a char buffer instead of a wchar_t buffer
278 // since it's used only for numeric conversion specifier and always
279 // with sprintf().
280 char szFlags[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
281
282
283 public:
284
285 // we don't declare this as a constructor otherwise it would be called
286 // automatically and we don't want this: to be optimized, wxVsnprintf_
287 // calls this function only on really-used instances of this class.
288 void Init();
289
290 // Parses the first conversion specifier in the given string, which must
291 // begin with a '%'. Returns false if the first '%' does not introduce a
292 // (valid) conversion specifier and thus should be ignored.
293 bool Parse(const wxChar *format);
294
295 // Process this conversion specifier and puts the result in the given
296 // buffer. Returns the number of characters written in 'buf' or -1 if
297 // there's not enough space.
298 int Process(wxChar *buf, size_t lenMax, wxPrintfArg *p);
299
300 // Loads the argument of this conversion specifier from given va_list.
301 bool LoadArg(wxPrintfArg *p, va_list &argptr);
302
303 private:
304 // An helper function of LoadArg() which is used to handle the '*' flag
305 void ReplaceAsteriskWith(int w);
306 };
307
308 void wxPrintfConvSpec::Init()
309 {
310 min_width = 0;
311 max_width = 0xFFFF;
312 pos = 0;
313 adj_left = false;
314 argpos = argend = NULL;
315 type = wxPAT_INVALID;
316
317 // this character will never be removed from szFlags array and
318 // is important when calling sprintf() in wxPrintfConvSpec::Process() !
319 szFlags[0] = '%';
320 }
321
322 bool wxPrintfConvSpec::Parse(const wxChar *format)
323 {
324 bool done = false;
325
326 // temporary parse data
327 size_t flagofs = 1;
328 bool in_prec, prec_dot;
329 int ilen = 0;
330
331 adj_left = in_prec = prec_dot = false;
332 argpos = argend = format;
333 do
334 {
335 #define CHECK_PREC \
336 if (in_prec && !prec_dot) \
337 { \
338 szFlags[flagofs++] = (char)'.'; \
339 prec_dot = true; \
340 }
341
342 // what follows '%'?
343 const wxChar ch = *(++argend);
344 switch ( ch )
345 {
346 case wxT('\0'):
347 return false; // not really an argument
348
349 case wxT('%'):
350 return false; // not really an argument
351
352 case wxT('#'):
353 case wxT('0'):
354 case wxT(' '):
355 case wxT('+'):
356 case wxT('\''):
357 CHECK_PREC
358 szFlags[flagofs++] = (char)ch;
359 break;
360
361 case wxT('-'):
362 CHECK_PREC
363 adj_left = true;
364 szFlags[flagofs++] = (char)ch;
365 break;
366
367 case wxT('.'):
368 CHECK_PREC
369 in_prec = true;
370 prec_dot = false;
371 max_width = 0;
372 // dot will be auto-added to szFlags if non-negative
373 // number follows
374 break;
375
376 case wxT('h'):
377 ilen = -1;
378 CHECK_PREC
379 szFlags[flagofs++] = (char)ch;
380 break;
381
382 case wxT('l'):
383 ilen = 1;
384 CHECK_PREC
385 szFlags[flagofs++] = (char)ch;
386 break;
387
388 case wxT('q'):
389 case wxT('L'):
390 ilen = 2;
391 CHECK_PREC
392 szFlags[flagofs++] = (char)ch;
393 break;
394
395 case wxT('Z'):
396 ilen = 3;
397 CHECK_PREC
398 szFlags[flagofs++] = (char)ch;
399 break;
400
401 case wxT('*'):
402 if (in_prec)
403 {
404 CHECK_PREC
405
406 // tell Process() to use the next argument
407 // in the stack as maxwidth...
408 max_width = -1;
409 }
410 else
411 {
412 // tell Process() to use the next argument
413 // in the stack as minwidth...
414 min_width = -1;
415 }
416
417 // save the * in our formatting buffer...
418 // will be replaced later by Process()
419 szFlags[flagofs++] = (char)ch;
420 break;
421
422 case wxT('1'): case wxT('2'): case wxT('3'):
423 case wxT('4'): case wxT('5'): case wxT('6'):
424 case wxT('7'): case wxT('8'): case wxT('9'):
425 {
426 int len = 0;
427 CHECK_PREC
428 while ( (*argend >= wxT('0')) &&
429 (*argend <= wxT('9')) )
430 {
431 szFlags[flagofs++] = (char)(*argend);
432 len = len*10 + (*argend - wxT('0'));
433 argend++;
434 }
435
436 if (in_prec)
437 max_width = len;
438 else
439 min_width = len;
440
441 argend--; // the main loop pre-increments n again
442 }
443 break;
444
445 case wxT('$'): // a positional parameter (e.g. %2$s) ?
446 {
447 if (min_width <= 0)
448 break; // ignore this formatting flag as no
449 // numbers are preceding it
450
451 // remove from szFlags all digits previously added
452 do {
453 flagofs--;
454 } while (szFlags[flagofs] >= '1' &&
455 szFlags[flagofs] <= '9');
456
457 // re-adjust the offset making it point to the
458 // next free char of szFlags
459 flagofs++;
460
461 pos = min_width;
462 min_width = 0;
463 }
464 break;
465
466 case wxT('d'):
467 case wxT('i'):
468 case wxT('o'):
469 case wxT('u'):
470 case wxT('x'):
471 case wxT('X'):
472 CHECK_PREC
473 szFlags[flagofs++] = (char)ch;
474 szFlags[flagofs] = (char)'\0';
475 if (ilen == 0)
476 type = wxPAT_INT;
477 else if (ilen == -1)
478 // NB: 'short int' value passed through '...'
479 // is promoted to 'int', so we have to get
480 // an int from stack even if we need a short
481 type = wxPAT_INT;
482 else if (ilen == 1)
483 type = wxPAT_LONGINT;
484 else if (ilen == 2)
485 #if SIZEOF_LONG_LONG
486 type = wxPAT_LONGLONGINT;
487 #else // !long long
488 type = wxPAT_LONGINT;
489 #endif // long long/!long long
490 else if (ilen == 3)
491 type = wxPAT_SIZET;
492 done = true;
493 break;
494
495 case wxT('e'):
496 case wxT('E'):
497 case wxT('f'):
498 case wxT('g'):
499 case wxT('G'):
500 CHECK_PREC
501 szFlags[flagofs++] = (char)ch;
502 szFlags[flagofs] = (char)'\0';
503 if (ilen == 2)
504 type = wxPAT_LONGDOUBLE;
505 else
506 type = wxPAT_DOUBLE;
507 done = true;
508 break;
509
510 case wxT('p'):
511 type = wxPAT_POINTER;
512 done = true;
513 break;
514
515 case wxT('c'):
516 if (ilen == -1)
517 {
518 // in Unicode mode %hc == ANSI character
519 // and in ANSI mode, %hc == %c == ANSI...
520 type = wxPAT_CHAR;
521 }
522 else if (ilen == 1)
523 {
524 // in ANSI mode %lc == Unicode character
525 // and in Unicode mode, %lc == %c == Unicode...
526 type = wxPAT_WCHAR;
527 }
528 else
529 {
530 #if wxUSE_UNICODE
531 // in Unicode mode, %c == Unicode character
532 type = wxPAT_WCHAR;
533 #else
534 // in ANSI mode, %c == ANSI character
535 type = wxPAT_CHAR;
536 #endif
537 }
538 done = true;
539 break;
540
541 case wxT('s'):
542 if (ilen == -1)
543 {
544 // Unicode mode wx extension: we'll let %hs mean non-Unicode
545 // strings (when in ANSI mode, %s == %hs == ANSI string)
546 type = wxPAT_PCHAR;
547 }
548 else if (ilen == 1)
549 {
550 // in Unicode mode, %ls == %s == Unicode string
551 // in ANSI mode, %ls == Unicode string
552 type = wxPAT_PWCHAR;
553 }
554 else
555 {
556 #if wxUSE_UNICODE
557 type = wxPAT_PWCHAR;
558 #else
559 type = wxPAT_PCHAR;
560 #endif
561 }
562 done = true;
563 break;
564
565 case wxT('n'):
566 if (ilen == 0)
567 type = wxPAT_NINT;
568 else if (ilen == -1)
569 type = wxPAT_NSHORTINT;
570 else if (ilen >= 1)
571 type = wxPAT_NLONGINT;
572 done = true;
573 break;
574
575 default:
576 // bad format, don't consider this an argument;
577 // leave it unchanged
578 return false;
579 }
580 }
581 while (!done);
582
583 return true; // parsing was successful
584 }
585
586
587 void wxPrintfConvSpec::ReplaceAsteriskWith(int w)
588 {
589 char temp[wxMAX_SVNPRINTF_FLAGBUFFER_LEN];
590
591 // find the first * in our flag buffer
592 char *pwidth = strchr(szFlags, '*');
593 wxASSERT(pwidth);
594
595 // save what follows the * (the +1 is to skip it!)
596 strcpy(temp, pwidth+1);
597 if (w < 0) {
598 pwidth[0] = '-';
599 pwidth++;
600 }
601
602 // replace * with the actual integer given as width
603 int offset = ::sprintf(pwidth,"%d",abs(w));
604
605 // restore after the expanded * what was following it
606 strcpy(pwidth+offset, temp);
607 }
608
609 bool wxPrintfConvSpec::LoadArg(wxPrintfArg *p, va_list &argptr)
610 {
611 // did the '*' width/precision specifier was used ?
612 if (max_width == -1)
613 {
614 // take the maxwidth specifier from the stack
615 max_width = va_arg(argptr, int);
616 if (max_width < 0)
617 max_width = 0;
618 else
619 ReplaceAsteriskWith(max_width);
620 }
621
622 if (min_width == -1)
623 {
624 // take the minwidth specifier from the stack
625 min_width = va_arg(argptr, int);
626
627 ReplaceAsteriskWith(min_width);
628 if (min_width < 0)
629 {
630 adj_left = !adj_left;
631 min_width = -min_width;
632 }
633 }
634
635 switch (type) {
636 case wxPAT_INT:
637 p->pad_int = va_arg(argptr, int);
638 break;
639 case wxPAT_LONGINT:
640 p->pad_longint = va_arg(argptr, long int);
641 break;
642 #if SIZEOF_LONG_LONG
643 case wxPAT_LONGLONGINT:
644 p->pad_longlongint = va_arg(argptr, long long int);
645 break;
646 #endif
647 case wxPAT_SIZET:
648 p->pad_sizet = va_arg(argptr, size_t);
649 break;
650 case wxPAT_DOUBLE:
651 p->pad_double = va_arg(argptr, double);
652 break;
653 case wxPAT_LONGDOUBLE:
654 p->pad_longdouble = va_arg(argptr, long double);
655 break;
656 case wxPAT_POINTER:
657 p->pad_pointer = va_arg(argptr, void *);
658 break;
659
660 case wxPAT_CHAR:
661 p->pad_char = (char)va_arg(argptr, int); // char is promoted to int when passed through '...'
662 break;
663 case wxPAT_WCHAR:
664 p->pad_wchar = (wchar_t)va_arg(argptr, int); // char is promoted to int when passed through '...'
665 break;
666
667 case wxPAT_PCHAR:
668 p->pad_pchar = va_arg(argptr, char *);
669 break;
670 case wxPAT_PWCHAR:
671 p->pad_pwchar = va_arg(argptr, wchar_t *);
672 break;
673
674 case wxPAT_NINT:
675 p->pad_nint = va_arg(argptr, int *);
676 break;
677 case wxPAT_NSHORTINT:
678 p->pad_nshortint = va_arg(argptr, short int *);
679 break;
680 case wxPAT_NLONGINT:
681 p->pad_nlongint = va_arg(argptr, long int *);
682 break;
683
684 case wxPAT_INVALID:
685 default:
686 return false;
687 }
688
689 return true; // loading was successful
690 }
691
692 int wxPrintfConvSpec::Process(wxChar *buf, size_t lenMax, wxPrintfArg *p)
693 {
694 // buffer to avoid dynamic memory allocation each time for small strings
695 static char szScratch[1024];
696 size_t lenCur = 0;
697
698 #define APPEND_CH(ch) \
699 { \
700 if ( lenCur == lenMax ) \
701 return -1; \
702 \
703 buf[lenCur++] = ch; \
704 }
705
706 #define APPEND_STR(s) \
707 { \
708 for ( const wxChar *p = s; *p; p++ ) \
709 { \
710 APPEND_CH(*p); \
711 } \
712 }
713
714 switch ( type )
715 {
716 case wxPAT_INT:
717 ::sprintf(szScratch, szFlags, p->pad_int);
718 break;
719
720 case wxPAT_LONGINT:
721 ::sprintf(szScratch, szFlags, p->pad_longint);
722 break;
723
724 #if SIZEOF_LONG_LONG
725 case wxPAT_LONGLONGINT:
726 ::sprintf(szScratch, szFlags, p->pad_longlongint);
727 break;
728 #endif // SIZEOF_LONG_LONG
729
730 case wxPAT_SIZET:
731 ::sprintf(szScratch, szFlags, p->pad_sizet);
732 break;
733
734 case wxPAT_LONGDOUBLE:
735 ::sprintf(szScratch, szFlags, p->pad_longdouble);
736 break;
737
738 case wxPAT_DOUBLE:
739 ::sprintf(szScratch, szFlags, p->pad_double);
740 break;
741
742 case wxPAT_POINTER:
743 ::sprintf(szScratch, szFlags, p->pad_pointer);
744 break;
745
746 case wxPAT_CHAR:
747 case wxPAT_WCHAR:
748 {
749 wxChar val =
750 #if wxUSE_UNICODE
751 p->pad_wchar;
752
753 if (type == wxPAT_CHAR) {
754 // user passed a character explicitely indicated as ANSI...
755 const char buf[2] = { p->pad_char, 0 };
756 val = wxString(buf, wxConvLibc)[0u];
757 }
758 #else
759 p->pad_char;
760
761 #if wxUSE_WCHAR_T
762 if (type == wxPAT_WCHAR) {
763 // user passed a character explicitely indicated as Unicode...
764 const wchar_t buf[2] = { p->pad_wchar, 0 };
765 val = wxString(buf, wxConvLibc)[0u];
766 }
767 #endif
768 #endif
769
770 size_t i;
771
772 if (!adj_left)
773 for (i = 1; i < (size_t)min_width; i++)
774 APPEND_CH(_T(' '));
775
776 APPEND_CH(val);
777
778 if (adj_left)
779 for (i = 1; i < (size_t)min_width; i++)
780 APPEND_CH(_T(' '));
781 }
782 break;
783
784 case wxPAT_PCHAR:
785 case wxPAT_PWCHAR:
786 {
787 wxString s;
788 const wxChar *val =
789 #if wxUSE_UNICODE
790 p->pad_pwchar;
791
792 if (type == wxPAT_PCHAR) {
793 // user passed a string explicitely indicated as ANSI...
794 val = s = wxString(p->pad_pchar, wxConvLibc);
795 }
796 #else
797 p->pad_pchar;
798
799 #if wxUSE_WCHAR_T
800 if (type == wxPAT_PWCHAR) {
801 // user passed a string explicitely indicated as Unicode...
802 val = s = wxString(p->pad_pwchar, wxConvLibc);
803 }
804 #endif
805 #endif
806 int len;
807
808 if (val)
809 {
810 #if wxUSE_STRUTILS
811 // at this point we are sure that max_width is positive or null
812 // (see top of wxPrintfConvSpec::LoadArg)
813 len = wxMin((unsigned int)max_width, wxStrlen(val));
814 #else
815 for ( len = 0; val[len] && (len < max_width); len++ )
816 ;
817 #endif
818 }
819 else if (max_width >= 6)
820 {
821 val = wxT("(null)");
822 len = 6;
823 }
824 else
825 {
826 val = wxEmptyString;
827 len = 0;
828 }
829
830 int i;
831
832 if (!adj_left)
833 {
834 for (i = len; i < min_width; i++)
835 APPEND_CH(_T(' '));
836 }
837
838 #if wxUSE_STRUTILS
839 // at this point we are sure that max_width is positive or null
840 // (see top of wxPrintfConvSpec::LoadArg)
841 len = wxMin((unsigned int)len, lenMax-lenCur);
842 wxStrncpy(buf+lenCur, val, len);
843 lenCur += len;
844 #else
845 for (i = 0; i < len; i++)
846 APPEND_CH(val[i]);
847 #endif
848
849 if (adj_left)
850 {
851 for (i = len; i < min_width; i++)
852 APPEND_CH(_T(' '));
853 }
854 }
855 break;
856
857 case wxPAT_NINT:
858 *p->pad_nint = lenCur;
859 break;
860
861 case wxPAT_NSHORTINT:
862 *p->pad_nshortint = (short int)lenCur;
863 break;
864
865 case wxPAT_NLONGINT:
866 *p->pad_nlongint = lenCur;
867 break;
868
869 case wxPAT_INVALID:
870 default:
871 return -1;
872 }
873
874 // if we used system's sprintf() then we now need to append the s_szScratch
875 // buffer to the given one...
876 switch (type)
877 {
878 case wxPAT_INT:
879 case wxPAT_LONGINT:
880 #if SIZEOF_LONG_LONG
881 case wxPAT_LONGLONGINT:
882 #endif
883 case wxPAT_SIZET:
884 case wxPAT_LONGDOUBLE:
885 case wxPAT_DOUBLE:
886 case wxPAT_POINTER:
887 #if wxUSE_STRUTILS
888 {
889 const wxMB2WXbuf tmp = wxConvLibc.cMB2WX(szScratch);
890 size_t len = wxMin(lenMax, wxStrlen(tmp));
891 wxStrncpy(buf, tmp, len);
892 lenCur += len;
893 }
894 #else
895 {
896 const wxMB2WXbuf tmp =
897 wxConvLibc.cMB2WX(szScratch);
898 APPEND_STR(tmp);
899 }
900 #endif
901 break;
902
903 default:
904 break; // all other cases were completed previously
905 }
906
907 return lenCur;
908 }
909
910 // differences from standard strncpy:
911 // 1) copies everything from 'source' except for '%%' sequence which is copied as '%'
912 // 2) returns the number of written characters in 'dest' as it could differ from given 'n'
913 // 3) much less optimized, unfortunately...
914 static int wxCopyStrWithPercents(wxChar *dest, const wxChar *source, size_t n)
915 {
916 size_t written = 0;
917
918 if (n == 0)
919 return 0;
920
921 size_t i;
922 for ( i = 0; i < n-1; source++, i++)
923 {
924 dest[written++] = *source;
925 if (*(source+1) == wxT('%'))
926 {
927 // skip this additional '%' character
928 source++;
929 i++;
930 }
931 }
932
933 if (i < n)
934 // copy last character inconditionally
935 dest[written++] = *source;
936
937 return written;
938 }
939
940 int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
941 const wxChar *format, va_list argptr)
942 {
943 // cached data
944 static wxPrintfConvSpec arg[wxMAX_SVNPRINTF_ARGUMENTS];
945 static wxPrintfArg argdata[wxMAX_SVNPRINTF_ARGUMENTS];
946 static wxPrintfConvSpec *pspec[wxMAX_SVNPRINTF_ARGUMENTS] = { NULL };
947
948 size_t i;
949
950 // number of characters in the buffer so far, must be less than lenMax
951 size_t lenCur = 0;
952
953 size_t nargs = 0;
954 const wxChar *toparse = format;
955
956 // parse the format string
957 bool posarg_present = false, nonposarg_present = false;
958 for (; *toparse != wxT('\0'); toparse++)
959 {
960 if (*toparse == wxT('%') )
961 {
962 arg[nargs].Init();
963
964 // let's see if this is a (valid) conversion specifier...
965 if (arg[nargs].Parse(toparse))
966 {
967 // ...yes it is
968 wxPrintfConvSpec *current = &arg[nargs];
969
970 // make toparse point to the end of this specifier
971 toparse = current->argend;
972
973 if (current->pos > 0) {
974 // the positionals start from number 1... adjust the index
975 current->pos--;
976 posarg_present = true;
977 } else {
978 // not a positional argument...
979 current->pos = nargs;
980 nonposarg_present = true;
981 }
982
983 // this conversion specifier is tied to the pos-th argument...
984 pspec[current->pos] = current;
985 nargs++;
986
987 if (nargs == wxMAX_SVNPRINTF_ARGUMENTS)
988 break; // cannot handle any additional conv spec
989 }
990 }
991 }
992
993 if (posarg_present && nonposarg_present)
994 return -1; // format strings with both positional and
995 // non-positional conversion specifier are unsupported !!
996
997 // on platforms where va_list is an array type, it is necessary to make a
998 // copy to be able to pass it to LoadArg as a reference.
999 bool ok = true;
1000 va_list ap;
1001 wxVaCopy(ap, argptr);
1002
1003 // now load arguments from stack
1004 for (i=0; i < nargs && ok; i++) {
1005 // !pspec[i] if user forgot a positional parameter (e.g. %$1s %$3s) ?
1006 // or LoadArg false if wxPrintfConvSpec::Parse failed to set its 'type'
1007 // to a valid value...
1008 ok = pspec[i] && pspec[i]->LoadArg(&argdata[i], ap);
1009 }
1010
1011 va_end(ap);
1012
1013 // something failed while loading arguments from the variable list...
1014 if (!ok)
1015 return -1;
1016
1017 // finally, process each conversion specifier with its own argument
1018 toparse = format;
1019 for (i=0; i < nargs; i++)
1020 {
1021 // copy in the output buffer the portion of the format string between
1022 // last specifier and the current one
1023 size_t tocopy = ( arg[i].argpos - toparse );
1024 if (lenCur+tocopy >= lenMax)
1025 return -1; // not enough space in the output buffer !
1026
1027 lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy);
1028
1029 // process this specifier directly in the output buffer
1030 int n = arg[i].Process(buf+lenCur, lenMax - lenCur, &argdata[arg[i].pos]);
1031 if (n == -1)
1032 return -1; // not enough space in the output buffer !
1033 lenCur += n;
1034
1035 // the +1 is because wxPrintfConvSpec::argend points to the last character
1036 // of the format specifier, but we are not interested to it...
1037 toparse = arg[i].argend + 1;
1038 }
1039
1040 // copy portion of the format string after last specifier
1041 // NOTE: toparse is pointing to the character just after the last processed
1042 // conversion specifier
1043 // NOTE2: the +1 is because we want to copy also the '\0'
1044 size_t tocopy = wxStrlen(format) + 1 - ( toparse - format ) ;
1045 if (lenCur+tocopy >= lenMax)
1046 return -1; // not enough space in the output buffer !
1047
1048 // the -1 is because of the '\0'
1049 lenCur += wxCopyStrWithPercents(buf+lenCur, toparse, tocopy) - 1;
1050
1051 // clean the static array portion used...
1052 // NOTE: other arrays do not need cleanup!
1053 memset(pspec, 0, sizeof(wxPrintfConvSpec*)*nargs);
1054
1055 wxASSERT(lenCur == wxStrlen(buf));
1056 return lenCur;
1057 }
1058
1059 #undef APPEND_CH
1060 #undef APPEND_STR
1061 #undef CHECK_PREC
1062
1063 #endif // !wxVsnprintfA
1064
1065 #if !defined(wxSnprintf_)
1066 int WXDLLEXPORT wxSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...)
1067 {
1068 va_list argptr;
1069 va_start(argptr, format);
1070
1071 int iLen = wxVsnprintf_(buf, len, format, argptr);
1072
1073 va_end(argptr);
1074
1075 return iLen;
1076 }
1077 #endif // wxSnprintf_
1078
1079 #if defined(__DMC__)
1080 /* Digital Mars adds count to _stprintf (C99) so convert */
1081 #if wxUSE_UNICODE
1082 int wxSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
1083 {
1084 va_list arglist;
1085
1086 va_start( arglist, format );
1087 int iLen = swprintf ( s, -1, format, arglist );
1088 va_end( arglist );
1089 return iLen ;
1090 }
1091
1092 #endif // wxUSE_UNICODE
1093
1094 #endif //__DMC__
1095
1096 // ----------------------------------------------------------------------------
1097 // implement the standard IO functions for wide char if libc doesn't have them
1098 // ----------------------------------------------------------------------------
1099
1100 #ifdef wxNEED_FPUTS
1101 int wxFputs(const wchar_t *ws, FILE *stream)
1102 {
1103 // counting the number of wide characters written isn't worth the trouble,
1104 // simply distinguish between ok and error
1105 return fputs(wxConvLibc.cWC2MB(ws), stream) == -1 ? -1 : 0;
1106 }
1107 #endif // wxNEED_FPUTS
1108
1109 #ifdef wxNEED_PUTS
1110 int wxPuts(const wxChar *ws)
1111 {
1112 int rc = wxFputs(ws, stdout);
1113 if ( rc != -1 )
1114 {
1115 if ( wxFputs(L"\n", stdout) == -1 )
1116 return -1;
1117
1118 rc++;
1119 }
1120
1121 return rc;
1122 }
1123 #endif // wxNEED_PUTS
1124
1125 #ifdef wxNEED_PUTC
1126 int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
1127 {
1128 wchar_t ws[2] = { wc, L'\0' };
1129
1130 return wxFputs(ws, stream);
1131 }
1132 #endif // wxNEED_PUTC
1133
1134 // NB: we only implement va_list functions here, the ones taking ... are
1135 // defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
1136 // the definitions there to avoid duplicating them here
1137 #ifdef wxNEED_WPRINTF
1138
1139 // TODO: implement the scanf() functions
1140 int vwscanf(const wxChar *format, va_list argptr)
1141 {
1142 wxFAIL_MSG( _T("TODO") );
1143
1144 return -1;
1145 }
1146
1147 int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr)
1148 {
1149 // The best we can do without proper Unicode support in glibc is to
1150 // convert the strings into MB representation and run ANSI version
1151 // of the function. This doesn't work with %c and %s because of difference
1152 // in size of char and wchar_t, though.
1153
1154 wxCHECK_MSG( wxStrstr(format, _T("%s")) == NULL, -1,
1155 _T("incomplete vswscanf implementation doesn't allow %s") );
1156 wxCHECK_MSG( wxStrstr(format, _T("%c")) == NULL, -1,
1157 _T("incomplete vswscanf implementation doesn't allow %c") );
1158
1159 va_list argcopy;
1160 wxVaCopy(argcopy, argptr);
1161 return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argcopy);
1162 }
1163
1164 int vfwscanf(FILE *stream, const wxChar *format, va_list argptr)
1165 {
1166 wxFAIL_MSG( _T("TODO") );
1167
1168 return -1;
1169 }
1170
1171 #define vswprintf wxVsnprintf_
1172
1173 int vfwprintf(FILE *stream, const wxChar *format, va_list argptr)
1174 {
1175 wxString s;
1176 int rc = s.PrintfV(format, argptr);
1177
1178 if ( rc != -1 )
1179 {
1180 // we can't do much better without Unicode support in libc...
1181 if ( fprintf(stream, "%s", (const char*)s.mb_str() ) == -1 )
1182 return -1;
1183 }
1184
1185 return rc;
1186 }
1187
1188 int vwprintf(const wxChar *format, va_list argptr)
1189 {
1190 return wxVfprintf(stdout, format, argptr);
1191 }
1192
1193 #endif // wxNEED_WPRINTF
1194
1195 #ifdef wxNEED_PRINTF_CONVERSION
1196
1197 // ----------------------------------------------------------------------------
1198 // wxFormatConverter: class doing the "%s" -> "%ls" conversion
1199 // ----------------------------------------------------------------------------
1200
1201 /*
1202 Here are the gory details. We want to follow the Windows/MS conventions,
1203 that is to have
1204
1205 In ANSI mode:
1206
1207 format specifier results in
1208 -----------------------------------
1209 %c, %hc, %hC char
1210 %lc, %C, %lC wchar_t
1211
1212 In Unicode mode:
1213
1214 format specifier results in
1215 -----------------------------------
1216 %hc, %C, %hC char
1217 %c, %lc, %lC wchar_t
1218
1219
1220 while on POSIX systems we have %C identical to %lc and %c always means char
1221 (in any mode) while %lc always means wchar_t,
1222
1223 So to use native functions in order to get our semantics we must do the
1224 following translations in Unicode mode (nothing to do in ANSI mode):
1225
1226 wxWidgets specifier POSIX specifier
1227 ----------------------------------------
1228
1229 %hc, %C, %hC %c
1230 %c %lc
1231
1232
1233 And, of course, the same should be done for %s as well.
1234 */
1235
1236 class wxFormatConverter
1237 {
1238 public:
1239 wxFormatConverter(const wxChar *format);
1240
1241 // notice that we only translated the string if m_fmtOrig == NULL (as set
1242 // by CopyAllBefore()), otherwise we should simply use the original format
1243 operator const wxChar *() const
1244 { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
1245
1246 private:
1247 // copy another character to the translated format: this function does the
1248 // copy if we are translating but doesn't do anything at all if we don't,
1249 // so we don't create the translated format string at all unless we really
1250 // need to (i.e. InsertFmtChar() is called)
1251 wxChar CopyFmtChar(wxChar ch)
1252 {
1253 if ( !m_fmtOrig )
1254 {
1255 // we're translating, do copy
1256 m_fmt += ch;
1257 }
1258 else
1259 {
1260 // simply increase the count which should be copied by
1261 // CopyAllBefore() later if needed
1262 m_nCopied++;
1263 }
1264
1265 return ch;
1266 }
1267
1268 // insert an extra character
1269 void InsertFmtChar(wxChar ch)
1270 {
1271 if ( m_fmtOrig )
1272 {
1273 // so far we haven't translated anything yet
1274 CopyAllBefore();
1275 }
1276
1277 m_fmt += ch;
1278 }
1279
1280 void CopyAllBefore()
1281 {
1282 wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
1283
1284 m_fmt = wxString(m_fmtOrig, m_nCopied);
1285
1286 // we won't need it any longer
1287 m_fmtOrig = NULL;
1288 }
1289
1290 static bool IsFlagChar(wxChar ch)
1291 {
1292 return ch == _T('-') || ch == _T('+') ||
1293 ch == _T('0') || ch == _T(' ') || ch == _T('#');
1294 }
1295
1296 void SkipDigits(const wxChar **ptpc)
1297 {
1298 while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
1299 CopyFmtChar(*(*ptpc)++);
1300 }
1301
1302 // the translated format
1303 wxString m_fmt;
1304
1305 // the original format
1306 const wxChar *m_fmtOrig;
1307
1308 // the number of characters already copied
1309 size_t m_nCopied;
1310 };
1311
1312 wxFormatConverter::wxFormatConverter(const wxChar *format)
1313 {
1314 m_fmtOrig = format;
1315 m_nCopied = 0;
1316
1317 while ( *format )
1318 {
1319 if ( CopyFmtChar(*format++) == _T('%') )
1320 {
1321 // skip any flags
1322 while ( IsFlagChar(*format) )
1323 CopyFmtChar(*format++);
1324
1325 // and possible width
1326 if ( *format == _T('*') )
1327 CopyFmtChar(*format++);
1328 else
1329 SkipDigits(&format);
1330
1331 // precision?
1332 if ( *format == _T('.') )
1333 {
1334 CopyFmtChar(*format++);
1335 if ( *format == _T('*') )
1336 CopyFmtChar(*format++);
1337 else
1338 SkipDigits(&format);
1339 }
1340
1341 // next we can have a size modifier
1342 enum
1343 {
1344 Default,
1345 Short,
1346 Long
1347 } size;
1348
1349 switch ( *format )
1350 {
1351 case _T('h'):
1352 size = Short;
1353 format++;
1354 break;
1355
1356 case _T('l'):
1357 // "ll" has a different meaning!
1358 if ( format[1] != _T('l') )
1359 {
1360 size = Long;
1361 format++;
1362 break;
1363 }
1364 //else: fall through
1365
1366 default:
1367 size = Default;
1368 }
1369
1370 // and finally we should have the type
1371 switch ( *format )
1372 {
1373 case _T('C'):
1374 case _T('S'):
1375 // %C and %hC -> %c and %lC -> %lc
1376 if ( size == Long )
1377 CopyFmtChar(_T('l'));
1378
1379 InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
1380 break;
1381
1382 case _T('c'):
1383 case _T('s'):
1384 // %c -> %lc but %hc stays %hc and %lc is still %lc
1385 if ( size == Default)
1386 InsertFmtChar(_T('l'));
1387 // fall through
1388
1389 default:
1390 // nothing special to do
1391 if ( size != Default )
1392 CopyFmtChar(*(format - 1));
1393 CopyFmtChar(*format++);
1394 }
1395 }
1396 }
1397 }
1398
1399 #else // !wxNEED_PRINTF_CONVERSION
1400 // no conversion necessary
1401 #define wxFormatConverter(x) (x)
1402 #endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION
1403
1404 #ifdef __WXDEBUG__
1405 // For testing the format converter
1406 wxString wxConvertFormat(const wxChar *format)
1407 {
1408 return wxString(wxFormatConverter(format));
1409 }
1410 #endif
1411
1412 // ----------------------------------------------------------------------------
1413 // wxPrintf(), wxScanf() and relatives
1414 // ----------------------------------------------------------------------------
1415
1416 #if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
1417
1418 int wxScanf( const wxChar *format, ... )
1419 {
1420 va_list argptr;
1421 va_start(argptr, format);
1422
1423 int ret = vwscanf(wxFormatConverter(format), argptr );
1424
1425 va_end(argptr);
1426
1427 return ret;
1428 }
1429
1430 int wxSscanf( const wxChar *str, const wxChar *format, ... )
1431 {
1432 va_list argptr;
1433 va_start(argptr, format);
1434
1435 int ret = vswscanf( str, wxFormatConverter(format), argptr );
1436
1437 va_end(argptr);
1438
1439 return ret;
1440 }
1441
1442 int wxFscanf( FILE *stream, const wxChar *format, ... )
1443 {
1444 va_list argptr;
1445 va_start(argptr, format);
1446 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
1447
1448 va_end(argptr);
1449
1450 return ret;
1451 }
1452
1453 int wxPrintf( const wxChar *format, ... )
1454 {
1455 va_list argptr;
1456 va_start(argptr, format);
1457
1458 int ret = vwprintf( wxFormatConverter(format), argptr );
1459
1460 va_end(argptr);
1461
1462 return ret;
1463 }
1464
1465 #ifndef wxSnprintf
1466 int wxSnprintf( wxChar *str, size_t size, const wxChar *format, ... )
1467 {
1468 va_list argptr;
1469 va_start(argptr, format);
1470
1471 int ret = vswprintf( str, size, wxFormatConverter(format), argptr );
1472
1473 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
1474 // doesn't nul terminate on truncation.
1475 str[size - 1] = 0;
1476
1477 va_end(argptr);
1478
1479 return ret;
1480 }
1481 #endif // wxSnprintf
1482
1483 int wxSprintf( wxChar *str, const wxChar *format, ... )
1484 {
1485 va_list argptr;
1486 va_start(argptr, format);
1487
1488 // note that wxString::FormatV() uses wxVsnprintf(), not wxSprintf(), so
1489 // it's safe to implement this one in terms of it
1490 wxString s(wxString::FormatV(format, argptr));
1491 wxStrcpy(str, s);
1492
1493 va_end(argptr);
1494
1495 return s.length();
1496 }
1497
1498 int wxFprintf( FILE *stream, const wxChar *format, ... )
1499 {
1500 va_list argptr;
1501 va_start( argptr, format );
1502
1503 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
1504
1505 va_end(argptr);
1506
1507 return ret;
1508 }
1509
1510 int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr )
1511 {
1512 return vswscanf( str, wxFormatConverter(format), argptr );
1513 }
1514
1515 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr )
1516 {
1517 return vfwprintf( stream, wxFormatConverter(format), argptr );
1518 }
1519
1520 int wxVprintf( const wxChar *format, va_list argptr )
1521 {
1522 return vwprintf( wxFormatConverter(format), argptr );
1523 }
1524
1525 #ifndef wxVsnprintf
1526 int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
1527 {
1528 return vswprintf( str, size, wxFormatConverter(format), argptr );
1529 }
1530 #endif // wxVsnprintf
1531
1532 int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr )
1533 {
1534 // same as for wxSprintf()
1535 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
1536 }
1537
1538 #endif // wxNEED_PRINTF_CONVERSION
1539
1540 #if wxUSE_WCHAR_T
1541
1542 // ----------------------------------------------------------------------------
1543 // ctype.h stuff (currently unused)
1544 // ----------------------------------------------------------------------------
1545
1546 #if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
1547 inline WORD wxMSW_ctype(wxChar ch)
1548 {
1549 WORD ret;
1550 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
1551 return ret;
1552 }
1553
1554 WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
1555 WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
1556 WXDLLEXPORT int wxIscntrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
1557 WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
1558 WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
1559 WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
1560 WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
1561 WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
1562 WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
1563 WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
1564 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
1565 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
1566 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
1567 #endif
1568
1569 #ifdef wxNEED_WX_MBSTOWCS
1570
1571 WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
1572 {
1573 if (!out)
1574 {
1575 size_t outsize = 0;
1576 while(*in++)
1577 outsize++;
1578 return outsize;
1579 }
1580
1581 const char* origin = in;
1582
1583 while (outlen-- && *in)
1584 {
1585 *out++ = (wchar_t) *in++;
1586 }
1587
1588 *out = '\0';
1589
1590 return in - origin;
1591 }
1592
1593 WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
1594 {
1595 if (!out)
1596 {
1597 size_t outsize = 0;
1598 while(*in++)
1599 outsize++;
1600 return outsize;
1601 }
1602
1603 const wchar_t* origin = in;
1604
1605 while (outlen-- && *in)
1606 {
1607 *out++ = (char) *in++;
1608 }
1609
1610 *out = '\0';
1611
1612 return in - origin;
1613 }
1614
1615 #endif // wxNEED_WX_MBSTOWCS
1616
1617 #if defined(wxNEED_WX_CTYPE_H)
1618
1619 #include <CoreFoundation/CoreFoundation.h>
1620
1621 #define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
1622 #define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
1623 #define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
1624 #define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
1625 //CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
1626 #define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
1627 //CFCharacterSetRef cfprintset = !kCFCharacterSetControl
1628 #define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
1629 #define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
1630 #define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
1631
1632 WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
1633 WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
1634 WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
1635 WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
1636 WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
1637 WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
1638 WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
1639 WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
1640 WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
1641 WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
1642 WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
1643 WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
1644 WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
1645
1646 #endif // wxNEED_WX_CTYPE_H
1647
1648 #ifndef wxStrdupA
1649
1650 WXDLLEXPORT char *wxStrdupA(const char *s)
1651 {
1652 return strcpy((char *)malloc(strlen(s) + 1), s);
1653 }
1654
1655 #endif // wxStrdupA
1656
1657 #ifndef wxStrdupW
1658
1659 WXDLLEXPORT wchar_t * wxStrdupW(const wchar_t *pwz)
1660 {
1661 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
1662 wchar_t *ret = (wchar_t *) malloc(size);
1663 memcpy(ret, pwz, size);
1664 return ret;
1665 }
1666
1667 #endif // wxStrdupW
1668
1669 #ifndef wxStricmp
1670 int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
1671 {
1672 register wxChar c1, c2;
1673 do {
1674 c1 = wxTolower(*psz1++);
1675 c2 = wxTolower(*psz2++);
1676 } while ( c1 && (c1 == c2) );
1677 return c1 - c2;
1678 }
1679 #endif
1680
1681 #ifndef wxStricmp
1682 int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
1683 {
1684 // initialize the variables just to suppress stupid gcc warning
1685 register wxChar c1 = 0, c2 = 0;
1686 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
1687 if (n) {
1688 if (c1 < c2) return -1;
1689 if (c1 > c2) return 1;
1690 }
1691 return 0;
1692 }
1693 #endif
1694
1695 #ifndef wxSetlocale
1696 WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
1697 {
1698 char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
1699
1700 return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
1701 }
1702 #endif
1703
1704 #if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
1705 WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
1706 {
1707 size_t n = 0;
1708 while ( *s++ )
1709 n++;
1710
1711 return n;
1712 }
1713 #endif
1714
1715 // ----------------------------------------------------------------------------
1716 // string.h functions
1717 // ----------------------------------------------------------------------------
1718
1719 #ifdef wxNEED_WX_STRING_H
1720
1721 // RN: These need to be c externed for the regex lib
1722 #ifdef __cplusplus
1723 extern "C" {
1724 #endif
1725
1726 WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
1727 {
1728 wxChar *ret = dest;
1729 while (*dest) dest++;
1730 while ((*dest++ = *src++));
1731 return ret;
1732 }
1733
1734 WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
1735 {
1736 // be careful here as the terminating NUL makes part of the string
1737 while ( *s != c )
1738 {
1739 if ( !*s++ )
1740 return NULL;
1741 }
1742
1743 return s;
1744 }
1745
1746 WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
1747 {
1748 while ((*s1 == *s2) && *s1) s1++, s2++;
1749 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1750 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1751 return 0;
1752 }
1753
1754 WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
1755 {
1756 wxChar *ret = dest;
1757 while ((*dest++ = *src++));
1758 return ret;
1759 }
1760
1761 WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
1762 {
1763 size_t n = 0;
1764 while ( *s++ )
1765 n++;
1766
1767 return n;
1768 }
1769
1770
1771 WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
1772 {
1773 wxChar *ret = dest;
1774 while (*dest) dest++;
1775 while (n && (*dest++ = *src++)) n--;
1776 return ret;
1777 }
1778
1779 WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
1780 {
1781 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
1782 if (n) {
1783 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
1784 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
1785 }
1786 return 0;
1787 }
1788
1789 WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
1790 {
1791 wxChar *ret = dest;
1792 while (n && (*dest++ = *src++)) n--;
1793 while (n) *dest++=0, n--; // the docs specify padding with zeroes
1794 return ret;
1795 }
1796
1797 WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
1798 {
1799 while (*s && !wxStrchr(accept, *s))
1800 s++;
1801
1802 return *s ? s : NULL;
1803 }
1804
1805 WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
1806 {
1807 const wxChar *ret = NULL;
1808 do
1809 {
1810 if ( *s == c )
1811 ret = s;
1812 s++;
1813 }
1814 while ( *s );
1815
1816 return ret;
1817 }
1818
1819 WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
1820 {
1821 size_t len = 0;
1822 while (wxStrchr(accept, *s++)) len++;
1823 return len;
1824 }
1825
1826 WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
1827 {
1828 wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
1829
1830 // VZ: this is not exactly the most efficient string search algorithm...
1831
1832 const size_t len = wxStrlen(needle);
1833
1834 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
1835 {
1836 if ( !wxStrncmp(fnd, needle, len) )
1837 return fnd;
1838
1839 haystack = fnd + 1;
1840 }
1841
1842 return NULL;
1843 }
1844
1845 #ifdef __cplusplus
1846 }
1847 #endif
1848
1849 WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
1850 {
1851 const wxChar *start = nptr;
1852
1853 // FIXME: only correct for C locale
1854 while (wxIsspace(*nptr)) nptr++;
1855 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1856 while (wxIsdigit(*nptr)) nptr++;
1857 if (*nptr == wxT('.')) {
1858 nptr++;
1859 while (wxIsdigit(*nptr)) nptr++;
1860 }
1861 if (*nptr == wxT('E') || *nptr == wxT('e')) {
1862 nptr++;
1863 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1864 while (wxIsdigit(*nptr)) nptr++;
1865 }
1866
1867 wxString data(nptr, nptr-start);
1868 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1869 char *rdat = wxMBSTRINGCAST dat;
1870 double ret = strtod(dat, &rdat);
1871
1872 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1873
1874 return ret;
1875 }
1876
1877 WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
1878 {
1879 const wxChar *start = nptr;
1880
1881 // FIXME: only correct for C locale
1882 while (wxIsspace(*nptr)) nptr++;
1883 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
1884 if (((base == 0) || (base == 16)) &&
1885 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
1886 nptr += 2;
1887 base = 16;
1888 }
1889 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
1890 else if (base == 0) base = 10;
1891
1892 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
1893 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
1894
1895 wxString data(start, nptr-start);
1896 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
1897 char *rdat = wxMBSTRINGCAST dat;
1898 long int ret = strtol(dat, &rdat, base);
1899
1900 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1901
1902 return ret;
1903 }
1904
1905 WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
1906 {
1907 return (unsigned long int) wxStrtol(nptr, endptr, base);
1908 }
1909
1910 #endif // wxNEED_WX_STRING_H
1911
1912 #ifdef wxNEED_WX_STDIO_H
1913 WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
1914 {
1915 char mode_buffer[10];
1916 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1917 mode_buffer[i] = (char) mode[i];
1918
1919 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
1920 }
1921
1922 WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
1923 {
1924 char mode_buffer[10];
1925 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1926 mode_buffer[i] = (char) mode[i];
1927
1928 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
1929 }
1930
1931 WXDLLEXPORT int wxRemove(const wxChar *path)
1932 {
1933 return remove( wxConvFile.cWX2MB(path) );
1934 }
1935
1936 WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
1937 {
1938 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
1939 }
1940 #endif
1941
1942 #ifndef wxAtof
1943 double WXDLLEXPORT wxAtof(const wxChar *psz)
1944 {
1945 #ifdef __WXWINCE__
1946 double d;
1947 wxString str(psz);
1948 if (str.ToDouble(& d))
1949 return d;
1950
1951 return 0.0;
1952 #else
1953 return atof(wxConvLibc.cWX2MB(psz));
1954 #endif
1955 }
1956 #endif
1957
1958 #ifdef wxNEED_WX_STDLIB_H
1959 int WXDLLEXPORT wxAtoi(const wxChar *psz)
1960 {
1961 return atoi(wxConvLibc.cWX2MB(psz));
1962 }
1963
1964 long WXDLLEXPORT wxAtol(const wxChar *psz)
1965 {
1966 return atol(wxConvLibc.cWX2MB(psz));
1967 }
1968
1969 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
1970 {
1971 #if wxUSE_UNICODE
1972 // NB: buffer returned by getenv() is allowed to be overwritten next
1973 // time getenv() is called, so it is OK to use static string
1974 // buffer to hold the data.
1975 static wxWCharBuffer value((wxChar*)NULL);
1976 value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
1977 return value.data();
1978 #else
1979 return getenv(name);
1980 #endif
1981 }
1982
1983 int WXDLLEXPORT wxSystem(const wxChar *psz)
1984 {
1985 return system(wxConvLibc.cWX2MB(psz));
1986 }
1987
1988 #endif // wxNEED_WX_STDLIB_H
1989
1990 #ifdef wxNEED_WX_TIME_H
1991 WXDLLEXPORT size_t
1992 wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
1993 {
1994 if ( !maxsize )
1995 return 0;
1996
1997 wxCharBuffer buf(maxsize);
1998
1999 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
2000 if ( !bufFmt )
2001 return 0;
2002
2003 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
2004 if ( !ret )
2005 return 0;
2006
2007 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
2008 if ( !wbuf )
2009 return 0;
2010
2011 wxStrncpy(s, wbuf, maxsize);
2012 return wxStrlen(s);
2013 }
2014 #endif // wxNEED_WX_TIME_H
2015
2016 #ifndef wxCtime
2017 WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
2018 {
2019 // normally the string is 26 chars but give one more in case some broken
2020 // DOS compiler decides to use "\r\n" instead of "\n" at the end
2021 static wxChar buf[27];
2022
2023 // ctime() is guaranteed to return a string containing only ASCII
2024 // characters, as its format is always the same for any locale
2025 wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
2026 buf[WXSIZEOF(buf) - 1] = _T('\0');
2027
2028 return buf;
2029 }
2030 #endif // wxCtime
2031
2032 #endif // wxUSE_WCHAR_T
2033
2034 // ----------------------------------------------------------------------------
2035 // functions which we may need even if !wxUSE_WCHAR_T
2036 // ----------------------------------------------------------------------------
2037
2038 #ifndef wxStrtok
2039
2040 WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
2041 {
2042 if (!psz)
2043 {
2044 psz = *save_ptr;
2045 if ( !psz )
2046 return NULL;
2047 }
2048
2049 psz += wxStrspn(psz, delim);
2050 if (!*psz)
2051 {
2052 *save_ptr = (wxChar *)NULL;
2053 return (wxChar *)NULL;
2054 }
2055
2056 wxChar *ret = psz;
2057 psz = wxStrpbrk(psz, delim);
2058 if (!psz)
2059 {
2060 *save_ptr = (wxChar*)NULL;
2061 }
2062 else
2063 {
2064 *psz = wxT('\0');
2065 *save_ptr = psz + 1;
2066 }
2067
2068 return ret;
2069 }
2070
2071 #endif // wxStrtok
2072
2073 // ----------------------------------------------------------------------------
2074 // missing C RTL functions
2075 // ----------------------------------------------------------------------------
2076
2077 #ifdef wxNEED_STRDUP
2078
2079 char *strdup(const char *s)
2080 {
2081 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
2082 if ( dest )
2083 strcpy( dest , s ) ;
2084 return dest ;
2085 }
2086 #endif // wxNEED_STRDUP
2087
2088 #if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
2089
2090 void *calloc( size_t num, size_t size )
2091 {
2092 void** ptr = (void **)malloc(num * size);
2093 memset( ptr, 0, num * size);
2094 return ptr;
2095 }
2096
2097 #endif // __WXWINCE__ <= 211
2098
2099 #ifdef __WXWINCE__
2100
2101 int wxRemove(const wxChar *path)
2102 {
2103 return ::DeleteFile(path) == 0;
2104 }
2105
2106 #endif