]> git.saurik.com Git - wxWidgets.git/blame - src/common/wxcrt.cpp
Fixed compile problem and warning
[wxWidgets.git] / src / common / wxcrt.cpp
CommitLineData
dd0ef332
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/wxcrt.cpp
3// Purpose: wxChar CRT wrappers implementation
4// Author: Ove Kaven
5// Modified by: Ron Lee, Francesco Montorsi
6// Created: 09/04/99
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets copyright
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// headers, declarations, constants
14// ===========================================================================
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23#include "wx/wxchar.h"
24
25#define _ISOC9X_SOURCE 1 // to get vsscanf()
26#define _BSD_SOURCE 1 // to still get strdup()
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#ifndef __WXWINCE__
33 #include <time.h>
34 #include <locale.h>
35#else
36 #include "wx/msw/wince/time.h"
37#endif
38
39#ifndef WX_PRECOMP
40 #include "wx/string.h"
41 #include "wx/hash.h"
42 #include "wx/utils.h" // for wxMin and wxMax
43 #include "wx/log.h"
44#endif
45
46#if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
47 #include <windef.h>
48 #include <winbase.h>
49 #include <winnls.h>
50 #include <winnt.h>
51#endif
52
53#if defined(__MWERKS__) && __MSL__ >= 0x6000
54namespace std {}
55using namespace std ;
56#endif
57
58#if wxUSE_WCHAR_T
59size_t WXDLLEXPORT wxMB2WC(wchar_t *buf, const char *psz, size_t n)
60{
61 // assume that we have mbsrtowcs() too if we have wcsrtombs()
62#ifdef HAVE_WCSRTOMBS
63 mbstate_t mbstate;
64 memset(&mbstate, 0, sizeof(mbstate_t));
65#endif
66
67 if (buf) {
68 if (!n || !*psz) {
69 if (n) *buf = wxT('\0');
70 return 0;
71 }
72#ifdef HAVE_WCSRTOMBS
73 return mbsrtowcs(buf, &psz, n, &mbstate);
74#else
75 return wxMbstowcs(buf, psz, n);
76#endif
77 }
78
79 // note that we rely on common (and required by Unix98 but unfortunately not
80 // C99) extension which allows to call mbs(r)towcs() with NULL output pointer
81 // to just get the size of the needed buffer -- this is needed as otherwise
82 // we have no idea about how much space we need and if the CRT doesn't
83 // support it (the only currently known example being Metrowerks, see
84 // wx/wxchar.h) we don't use its mbstowcs() at all
85#ifdef HAVE_WCSRTOMBS
86 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
87#else
88 return wxMbstowcs((wchar_t *) NULL, psz, 0);
89#endif
90}
91
92size_t WXDLLEXPORT wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
93{
94#ifdef HAVE_WCSRTOMBS
95 mbstate_t mbstate;
96 memset(&mbstate, 0, sizeof(mbstate_t));
97#endif
98
99 if (buf) {
100 if (!n || !*pwz) {
101 // glibc2.1 chokes on null input
102 if (n) *buf = '\0';
103 return 0;
104 }
105#ifdef HAVE_WCSRTOMBS
106 return wcsrtombs(buf, &pwz, n, &mbstate);
107#else
108 return wxWcstombs(buf, pwz, n);
109#endif
110 }
111
112#ifdef HAVE_WCSRTOMBS
113 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
114#else
115 return wxWcstombs((char *) NULL, pwz, 0);
116#endif
117}
118#endif // wxUSE_WCHAR_T
119
120bool WXDLLEXPORT wxOKlibc()
121{
122#if wxUSE_WCHAR_T && defined(__UNIX__) && defined(__GLIBC__) && !defined(__WINE__)
123 // glibc 2.0 uses UTF-8 even when it shouldn't
124 wchar_t res = 0;
125 if ((MB_CUR_MAX == 2) &&
126 (wxMB2WC(&res, "\xdd\xa5", 1) == 1) &&
127 (res==0x765)) {
128 // this is UTF-8 allright, check whether that's what we want
129 char *cur_locale = setlocale(LC_CTYPE, NULL);
130 if ((strlen(cur_locale) < 4) ||
131 (strcasecmp(cur_locale + strlen(cur_locale) - 4, "utf8")) ||
132 (strcasecmp(cur_locale + strlen(cur_locale) - 5, "utf-8"))) {
133 // nope, don't use libc conversion
134 return false;
135 }
136 }
137#endif
138 return true;
139}
140
141// ============================================================================
142// printf() functions business
143// ============================================================================
144
145// special test mode: define all functions below even if we don't really need
146// them to be able to test them
147#ifdef wxTEST_PRINTF
148 #undef wxFprintf
149 #undef wxPrintf
150 #undef wxSprintf
151 #undef wxVfprintf
152 #undef wxVsprintf
153 #undef wxVprintf
154 #undef wxVsnprintf_
155 #undef wxSnprintf_
156
157 #define wxNEED_WPRINTF
158
159 int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr );
160#endif
161
162#if !defined(wxSnprintf_)
163int WXDLLEXPORT wxDoSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...)
164{
165 va_list argptr;
166 va_start(argptr, format);
167
168 int iLen = wxVsnprintf_(buf, len, format, argptr);
169
170 va_end(argptr);
171
172 return iLen;
173}
174#endif // wxSnprintf_
175
176#if defined(__DMC__)
177 /* Digital Mars adds count to _stprintf (C99) so convert */
178 #if wxUSE_UNICODE
179 int wxDoSprintf (wchar_t * __RESTRICT s, const wchar_t * __RESTRICT format, ... )
180 {
181 va_list arglist;
182
183 va_start( arglist, format );
184 int iLen = swprintf ( s, -1, format, arglist );
185 va_end( arglist );
186 return iLen ;
187 }
188
189 #endif // wxUSE_UNICODE
190
191#endif //__DMC__
192
193// ----------------------------------------------------------------------------
194// implement the standard IO functions for wide char if libc doesn't have them
195// ----------------------------------------------------------------------------
196
197#ifdef wxNEED_FPUTS
198int wxFputs(const wchar_t *ws, FILE *stream)
199{
200 wxCharBuffer buf(wxConvLibc.cWC2MB(ws));
201 if ( !buf )
202 return -1;
203
204 // counting the number of wide characters written isn't worth the trouble,
205 // simply distinguish between ok and error
206 return fputs(buf, stream) == -1 ? -1 : 0;
207}
208#endif // wxNEED_FPUTS
209
210#ifdef wxNEED_PUTS
211int wxPuts(const wxChar *ws)
212{
213 int rc = wxFputs(ws, stdout);
214 if ( rc != -1 )
215 {
216 if ( wxFputs(L"\n", stdout) == -1 )
217 return -1;
218
219 rc++;
220 }
221
222 return rc;
223}
224#endif // wxNEED_PUTS
225
226#ifdef wxNEED_PUTC
227int /* not wint_t */ wxPutc(wchar_t wc, FILE *stream)
228{
229 wchar_t ws[2] = { wc, L'\0' };
230
231 return wxFputs(ws, stream);
232}
233#endif // wxNEED_PUTC
234
235// NB: we only implement va_list functions here, the ones taking ... are
236// defined below for wxNEED_PRINTF_CONVERSION case anyhow and we reuse
237// the definitions there to avoid duplicating them here
238#ifdef wxNEED_WPRINTF
239
240// TODO: implement the scanf() functions
241int vwscanf(const wxChar *format, va_list argptr)
242{
243 wxFAIL_MSG( _T("TODO") );
244
245 return -1;
246}
247
248int vswscanf(const wxChar *ws, const wxChar *format, va_list argptr)
249{
250 // The best we can do without proper Unicode support in glibc is to
251 // convert the strings into MB representation and run ANSI version
252 // of the function. This doesn't work with %c and %s because of difference
253 // in size of char and wchar_t, though.
254
255 wxCHECK_MSG( wxStrstr(format, _T("%s")) == NULL, -1,
256 _T("incomplete vswscanf implementation doesn't allow %s") );
257 wxCHECK_MSG( wxStrstr(format, _T("%c")) == NULL, -1,
258 _T("incomplete vswscanf implementation doesn't allow %c") );
259
260 va_list argcopy;
261 wxVaCopy(argcopy, argptr);
262 return vsscanf(wxConvLibc.cWX2MB(ws), wxConvLibc.cWX2MB(format), argcopy);
263}
264
265int vfwscanf(FILE *stream, const wxChar *format, va_list argptr)
266{
267 wxFAIL_MSG( _T("TODO") );
268
269 return -1;
270}
271
272#define vswprintf wxVsnprintf_
273
274int vfwprintf(FILE *stream, const wxChar *format, va_list argptr)
275{
276 wxString s;
277 int rc = s.PrintfV(format, argptr);
278
279 if ( rc != -1 )
280 {
281 // we can't do much better without Unicode support in libc...
282 if ( fprintf(stream, "%s", (const char*)s.mb_str() ) == -1 )
283 return -1;
284 }
285
286 return rc;
287}
288
289int vwprintf(const wxChar *format, va_list argptr)
290{
291 return wxVfprintf(stdout, format, argptr);
292}
293
294#endif // wxNEED_WPRINTF
295
296#ifdef wxNEED_PRINTF_CONVERSION
297
298// ----------------------------------------------------------------------------
299// wxFormatConverter: class doing the "%s" -> "%ls" conversion
300// ----------------------------------------------------------------------------
301
302/*
303 Here are the gory details. We want to follow the Windows/MS conventions,
304 that is to have
305
306 In ANSI mode:
307
308 format specifier results in
309 -----------------------------------
310 %c, %hc, %hC char
311 %lc, %C, %lC wchar_t
312
313 In Unicode mode:
314
315 format specifier results in
316 -----------------------------------
317 %hc, %C, %hC char
318 %c, %lc, %lC wchar_t
319
320
321 while on POSIX systems we have %C identical to %lc and %c always means char
322 (in any mode) while %lc always means wchar_t,
323
324 So to use native functions in order to get our semantics we must do the
325 following translations in Unicode mode (nothing to do in ANSI mode):
326
327 wxWidgets specifier POSIX specifier
328 ----------------------------------------
329
330 %hc, %C, %hC %c
331 %c %lc
332
333
334 And, of course, the same should be done for %s as well.
335*/
336
337class wxFormatConverter
338{
339public:
340 wxFormatConverter(const wxChar *format);
341
342 // notice that we only translated the string if m_fmtOrig == NULL (as set
343 // by CopyAllBefore()), otherwise we should simply use the original format
344 operator const wxChar *() const
345 { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
346
347private:
348 // copy another character to the translated format: this function does the
349 // copy if we are translating but doesn't do anything at all if we don't,
350 // so we don't create the translated format string at all unless we really
351 // need to (i.e. InsertFmtChar() is called)
352 wxChar CopyFmtChar(wxChar ch)
353 {
354 if ( !m_fmtOrig )
355 {
356 // we're translating, do copy
357 m_fmt += ch;
358 }
359 else
360 {
361 // simply increase the count which should be copied by
362 // CopyAllBefore() later if needed
363 m_nCopied++;
364 }
365
366 return ch;
367 }
368
369 // insert an extra character
370 void InsertFmtChar(wxChar ch)
371 {
372 if ( m_fmtOrig )
373 {
374 // so far we haven't translated anything yet
375 CopyAllBefore();
376 }
377
378 m_fmt += ch;
379 }
380
381 void CopyAllBefore()
382 {
383 wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
384
385 m_fmt = wxString(m_fmtOrig, m_nCopied);
386
387 // we won't need it any longer
388 m_fmtOrig = NULL;
389 }
390
391 static bool IsFlagChar(wxChar ch)
392 {
393 return ch == _T('-') || ch == _T('+') ||
394 ch == _T('0') || ch == _T(' ') || ch == _T('#');
395 }
396
397 void SkipDigits(const wxChar **ptpc)
398 {
399 while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
400 CopyFmtChar(*(*ptpc)++);
401 }
402
403 // the translated format
404 wxString m_fmt;
405
406 // the original format
407 const wxChar *m_fmtOrig;
408
409 // the number of characters already copied
410 size_t m_nCopied;
411};
412
413wxFormatConverter::wxFormatConverter(const wxChar *format)
414{
415 m_fmtOrig = format;
416 m_nCopied = 0;
417
418 while ( *format )
419 {
420 if ( CopyFmtChar(*format++) == _T('%') )
421 {
422 // skip any flags
423 while ( IsFlagChar(*format) )
424 CopyFmtChar(*format++);
425
426 // and possible width
427 if ( *format == _T('*') )
428 CopyFmtChar(*format++);
429 else
430 SkipDigits(&format);
431
432 // precision?
433 if ( *format == _T('.') )
434 {
435 CopyFmtChar(*format++);
436 if ( *format == _T('*') )
437 CopyFmtChar(*format++);
438 else
439 SkipDigits(&format);
440 }
441
442 // next we can have a size modifier
443 enum
444 {
445 Default,
446 Short,
447 Long
448 } size;
449
450 switch ( *format )
451 {
452 case _T('h'):
453 size = Short;
454 format++;
455 break;
456
457 case _T('l'):
458 // "ll" has a different meaning!
459 if ( format[1] != _T('l') )
460 {
461 size = Long;
462 format++;
463 break;
464 }
465 //else: fall through
466
467 default:
468 size = Default;
469 }
470
471 // and finally we should have the type
472 switch ( *format )
473 {
474 case _T('C'):
475 case _T('S'):
476 // %C and %hC -> %c and %lC -> %lc
477 if ( size == Long )
478 CopyFmtChar(_T('l'));
479
480 InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
481 break;
482
483 case _T('c'):
484 case _T('s'):
485 // %c -> %lc but %hc stays %hc and %lc is still %lc
486 if ( size == Default)
487 InsertFmtChar(_T('l'));
488 // fall through
489
490 default:
491 // nothing special to do
492 if ( size != Default )
493 CopyFmtChar(*(format - 1));
494 CopyFmtChar(*format++);
495 }
496 }
497 }
498}
499
500#else // !wxNEED_PRINTF_CONVERSION
501 // no conversion necessary
502 #define wxFormatConverter(x) (x)
503#endif // wxNEED_PRINTF_CONVERSION/!wxNEED_PRINTF_CONVERSION
504
505#ifdef __WXDEBUG__
506// For testing the format converter
507wxString wxConvertFormat(const wxChar *format)
508{
509 return wxString(wxFormatConverter(format));
510}
511#endif
512
513// ----------------------------------------------------------------------------
514// wxPrintf(), wxScanf() and relatives
515// ----------------------------------------------------------------------------
516
517#if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
518
519int wxDoScanf( const wxChar *format, ... )
520{
521 va_list argptr;
522 va_start(argptr, format);
523
524 int ret = vwscanf(wxFormatConverter(format), argptr );
525
526 va_end(argptr);
527
528 return ret;
529}
530
531int wxDoSscanf( const wxChar *str, const wxChar *format, ... )
532{
533 va_list argptr;
534 va_start(argptr, format);
535
536 int ret = vswscanf( str, wxFormatConverter(format), argptr );
537
538 va_end(argptr);
539
540 return ret;
541}
542
543int wxDoFscanf( FILE *stream, const wxChar *format, ... )
544{
545 va_list argptr;
546 va_start(argptr, format);
547 int ret = vfwscanf(stream, wxFormatConverter(format), argptr);
548
549 va_end(argptr);
550
551 return ret;
552}
553
554int wxDoPrintf( const wxChar *format, ... )
555{
556 va_list argptr;
557 va_start(argptr, format);
558
559 int ret = vwprintf( wxFormatConverter(format), argptr );
560
561 va_end(argptr);
562
563 return ret;
564}
565
566#ifndef wxSnprintf
567int wxDoSnprintf( wxChar *str, size_t size, const wxChar *format, ... )
568{
569 va_list argptr;
570 va_start(argptr, format);
571
572 int ret = vswprintf( str, size, wxFormatConverter(format), argptr );
573
574 // VsnprintfTestCase reveals that glibc's implementation of vswprintf
575 // doesn't nul terminate on truncation.
576 str[size - 1] = 0;
577
578 va_end(argptr);
579
580 return ret;
581}
582#endif // wxSnprintf
583
584int wxDoSprintf( wxChar *str, const wxChar *format, ... )
585{
586 va_list argptr;
587 va_start(argptr, format);
588
589 // note that wxString::FormatV() uses wxVsnprintf(), not wxSprintf(), so
590 // it's safe to implement this one in terms of it
591 wxString s(wxString::FormatV(format, argptr));
592 wxStrcpy(str, s);
593
594 va_end(argptr);
595
596 return s.length();
597}
598
599int wxDoFprintf( FILE *stream, const wxChar *format, ... )
600{
601 va_list argptr;
602 va_start( argptr, format );
603
604 int ret = vfwprintf( stream, wxFormatConverter(format), argptr );
605
606 va_end(argptr);
607
608 return ret;
609}
610
611int wxVsscanf( const wxChar *str, const wxChar *format, va_list argptr )
612{
613 return vswscanf( str, wxFormatConverter(format), argptr );
614}
615
616int wxVfprintf( FILE *stream, const wxChar *format, va_list argptr )
617{
618 return vfwprintf( stream, wxFormatConverter(format), argptr );
619}
620
621int wxVprintf( const wxChar *format, va_list argptr )
622{
623 return vwprintf( wxFormatConverter(format), argptr );
624}
625
626#ifndef wxVsnprintf
627int wxVsnprintf( wxChar *str, size_t size, const wxChar *format, va_list argptr )
628{
629 return vswprintf( str, size, wxFormatConverter(format), argptr );
630}
631#endif // wxVsnprintf
632
633int wxVsprintf( wxChar *str, const wxChar *format, va_list argptr )
634{
635 // same as for wxSprintf()
636 return vswprintf(str, INT_MAX / 4, wxFormatConverter(format), argptr);
637}
638
639#endif // wxNEED_PRINTF_CONVERSION
640
641#if wxUSE_WCHAR_T
642
643// ----------------------------------------------------------------------------
644// ctype.h stuff (currently unused)
645// ----------------------------------------------------------------------------
646
647#if defined(__WIN32__) && defined(wxNEED_WX_CTYPE_H)
648inline WORD wxMSW_ctype(wxChar ch)
649{
650 WORD ret;
651 GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &ch, 1, &ret);
652 return ret;
653}
654
655WXDLLEXPORT int wxIsalnum(wxChar ch) { return IsCharAlphaNumeric(ch); }
656WXDLLEXPORT int wxIsalpha(wxChar ch) { return IsCharAlpha(ch); }
657WXDLLEXPORT int wxIscntrl(wxChar ch) { return wxMSW_ctype(ch) & C1_CNTRL; }
658WXDLLEXPORT int wxIsdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_DIGIT; }
659WXDLLEXPORT int wxIsgraph(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_PUNCT|C1_ALPHA); }
660WXDLLEXPORT int wxIslower(wxChar ch) { return IsCharLower(ch); }
661WXDLLEXPORT int wxIsprint(wxChar ch) { return wxMSW_ctype(ch) & (C1_DIGIT|C1_SPACE|C1_PUNCT|C1_ALPHA); }
662WXDLLEXPORT int wxIspunct(wxChar ch) { return wxMSW_ctype(ch) & C1_PUNCT; }
663WXDLLEXPORT int wxIsspace(wxChar ch) { return wxMSW_ctype(ch) & C1_SPACE; }
664WXDLLEXPORT int wxIsupper(wxChar ch) { return IsCharUpper(ch); }
665WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxMSW_ctype(ch) & C1_XDIGIT; }
666WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)CharLower((LPTSTR)(ch)); }
667WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)CharUpper((LPTSTR)(ch)); }
668#endif
669
670#ifdef wxNEED_WX_MBSTOWCS
671
672WXDLLEXPORT size_t wxMbstowcs (wchar_t * out, const char * in, size_t outlen)
673{
674 if (!out)
675 {
676 size_t outsize = 0;
677 while(*in++)
678 outsize++;
679 return outsize;
680 }
681
682 const char* origin = in;
683
684 while (outlen-- && *in)
685 {
686 *out++ = (wchar_t) *in++;
687 }
688
689 *out = '\0';
690
691 return in - origin;
692}
693
694WXDLLEXPORT size_t wxWcstombs (char * out, const wchar_t * in, size_t outlen)
695{
696 if (!out)
697 {
698 size_t outsize = 0;
699 while(*in++)
700 outsize++;
701 return outsize;
702 }
703
704 const wchar_t* origin = in;
705
706 while (outlen-- && *in)
707 {
708 *out++ = (char) *in++;
709 }
710
711 *out = '\0';
712
713 return in - origin;
714}
715
716#endif // wxNEED_WX_MBSTOWCS
717
718#if defined(wxNEED_WX_CTYPE_H)
719
720#include <CoreFoundation/CoreFoundation.h>
721
722#define cfalnumset CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric)
723#define cfalphaset CFCharacterSetGetPredefined(kCFCharacterSetLetter)
724#define cfcntrlset CFCharacterSetGetPredefined(kCFCharacterSetControl)
725#define cfdigitset CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit)
726//CFCharacterSetRef cfgraphset = kCFCharacterSetControl && !' '
727#define cflowerset CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter)
728//CFCharacterSetRef cfprintset = !kCFCharacterSetControl
729#define cfpunctset CFCharacterSetGetPredefined(kCFCharacterSetPunctuation)
730#define cfspaceset CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline)
731#define cfupperset CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter)
732
733WXDLLEXPORT int wxIsalnum(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalnumset, ch); }
734WXDLLEXPORT int wxIsalpha(wxChar ch) { return CFCharacterSetIsCharacterMember(cfalphaset, ch); }
735WXDLLEXPORT int wxIscntrl(wxChar ch) { return CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
736WXDLLEXPORT int wxIsdigit(wxChar ch) { return CFCharacterSetIsCharacterMember(cfdigitset, ch); }
737WXDLLEXPORT int wxIsgraph(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch) && ch != ' '; }
738WXDLLEXPORT int wxIslower(wxChar ch) { return CFCharacterSetIsCharacterMember(cflowerset, ch); }
739WXDLLEXPORT int wxIsprint(wxChar ch) { return !CFCharacterSetIsCharacterMember(cfcntrlset, ch); }
740WXDLLEXPORT int wxIspunct(wxChar ch) { return CFCharacterSetIsCharacterMember(cfpunctset, ch); }
741WXDLLEXPORT int wxIsspace(wxChar ch) { return CFCharacterSetIsCharacterMember(cfspaceset, ch); }
742WXDLLEXPORT int wxIsupper(wxChar ch) { return CFCharacterSetIsCharacterMember(cfupperset, ch); }
743WXDLLEXPORT int wxIsxdigit(wxChar ch) { return wxIsdigit(ch) || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); }
744WXDLLEXPORT int wxTolower(wxChar ch) { return (wxChar)tolower((char)(ch)); }
745WXDLLEXPORT int wxToupper(wxChar ch) { return (wxChar)toupper((char)(ch)); }
746
747#endif // wxNEED_WX_CTYPE_H
748
749#ifndef wxStrdupA
750
751WXDLLEXPORT char *wxStrdupA(const char *s)
752{
753 return strcpy((char *)malloc(strlen(s) + 1), s);
754}
755
756#endif // wxStrdupA
757
758#ifndef wxStrdupW
759
760WXDLLEXPORT wchar_t * wxStrdupW(const wchar_t *pwz)
761{
762 size_t size = (wxWcslen(pwz) + 1) * sizeof(wchar_t);
763 wchar_t *ret = (wchar_t *) malloc(size);
764 memcpy(ret, pwz, size);
765 return ret;
766}
767
768#endif // wxStrdupW
769
770#ifndef wxStricmp
771int WXDLLEXPORT wxStricmp(const wxChar *psz1, const wxChar *psz2)
772{
773 register wxChar c1, c2;
774 do {
775 c1 = wxTolower(*psz1++);
776 c2 = wxTolower(*psz2++);
777 } while ( c1 && (c1 == c2) );
778 return c1 - c2;
779}
780#endif
781
782#ifndef wxStricmp
783int WXDLLEXPORT wxStrnicmp(const wxChar *s1, const wxChar *s2, size_t n)
784{
785 // initialize the variables just to suppress stupid gcc warning
786 register wxChar c1 = 0, c2 = 0;
787 while (n && ((c1 = wxTolower(*s1)) == (c2 = wxTolower(*s2)) ) && c1) n--, s1++, s2++;
788 if (n) {
789 if (c1 < c2) return -1;
790 if (c1 > c2) return 1;
791 }
792 return 0;
793}
794#endif
795
796#ifndef wxSetlocale
797WXDLLEXPORT wxWCharBuffer wxSetlocale(int category, const wxChar *locale)
798{
799 char *localeOld = setlocale(category, wxConvLibc.cWX2MB(locale));
800
801 return wxWCharBuffer(wxConvLibc.cMB2WC(localeOld));
802}
803#endif
804
805#if wxUSE_WCHAR_T && !defined(HAVE_WCSLEN)
806WXDLLEXPORT size_t wxWcslen(const wchar_t *s)
807{
808 size_t n = 0;
809 while ( *s++ )
810 n++;
811
812 return n;
813}
814#endif
815
816// ----------------------------------------------------------------------------
817// string.h functions
818// ----------------------------------------------------------------------------
819
820#ifdef wxNEED_WX_STRING_H
821
822// RN: These need to be c externed for the regex lib
823#ifdef __cplusplus
824extern "C" {
825#endif
826
827WXDLLEXPORT wxChar * wxStrcat(wxChar *dest, const wxChar *src)
828{
829 wxChar *ret = dest;
830 while (*dest) dest++;
831 while ((*dest++ = *src++));
832 return ret;
833}
834
835WXDLLEXPORT const wxChar * wxStrchr(const wxChar *s, wxChar c)
836{
837 // be careful here as the terminating NUL makes part of the string
838 while ( *s != c )
839 {
840 if ( !*s++ )
841 return NULL;
842 }
843
844 return s;
845}
846
847WXDLLEXPORT int wxStrcmp(const wxChar *s1, const wxChar *s2)
848{
849 while ((*s1 == *s2) && *s1) s1++, s2++;
850 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
851 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
852 return 0;
853}
854
855WXDLLEXPORT wxChar * wxStrcpy(wxChar *dest, const wxChar *src)
856{
857 wxChar *ret = dest;
858 while ((*dest++ = *src++));
859 return ret;
860}
861
862WXDLLEXPORT size_t wxStrlen_(const wxChar *s)
863{
864 size_t n = 0;
865 while ( *s++ )
866 n++;
867
868 return n;
869}
870
871
872WXDLLEXPORT wxChar * wxStrncat(wxChar *dest, const wxChar *src, size_t n)
873{
874 wxChar *ret = dest;
875 while (*dest) dest++;
876 while (n && (*dest++ = *src++)) n--;
877 return ret;
878}
879
880WXDLLEXPORT int wxStrncmp(const wxChar *s1, const wxChar *s2, size_t n)
881{
882 while (n && (*s1 == *s2) && *s1) n--, s1++, s2++;
883 if (n) {
884 if ((wxUChar)*s1 < (wxUChar)*s2) return -1;
885 if ((wxUChar)*s1 > (wxUChar)*s2) return 1;
886 }
887 return 0;
888}
889
890WXDLLEXPORT wxChar * wxStrncpy(wxChar *dest, const wxChar *src, size_t n)
891{
892 wxChar *ret = dest;
893 while (n && (*dest++ = *src++)) n--;
894 while (n) *dest++=0, n--; // the docs specify padding with zeroes
895 return ret;
896}
897
898WXDLLEXPORT const wxChar * wxStrpbrk(const wxChar *s, const wxChar *accept)
899{
900 while (*s && !wxStrchr(accept, *s))
901 s++;
902
903 return *s ? s : NULL;
904}
905
906WXDLLEXPORT const wxChar * wxStrrchr(const wxChar *s, wxChar c)
907{
908 const wxChar *ret = NULL;
909 do
910 {
911 if ( *s == c )
912 ret = s;
913 s++;
914 }
915 while ( *s );
916
917 return ret;
918}
919
920WXDLLEXPORT size_t wxStrspn(const wxChar *s, const wxChar *accept)
921{
922 size_t len = 0;
923 while (wxStrchr(accept, *s++)) len++;
924 return len;
925}
926
927WXDLLEXPORT const wxChar *wxStrstr(const wxChar *haystack, const wxChar *needle)
928{
929 wxASSERT_MSG( needle != NULL, _T("NULL argument in wxStrstr") );
930
931 // VZ: this is not exactly the most efficient string search algorithm...
932
933 const size_t len = wxStrlen(needle);
934
935 while ( const wxChar *fnd = wxStrchr(haystack, *needle) )
936 {
937 if ( !wxStrncmp(fnd, needle, len) )
938 return fnd;
939
940 haystack = fnd + 1;
941 }
942
943 return NULL;
944}
945
946#ifdef __cplusplus
947}
948#endif
949
950WXDLLEXPORT double wxStrtod(const wxChar *nptr, wxChar **endptr)
951{
952 const wxChar *start = nptr;
953
954 // FIXME: only correct for C locale
955 while (wxIsspace(*nptr)) nptr++;
956 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
957 while (wxIsdigit(*nptr)) nptr++;
958 if (*nptr == wxT('.')) {
959 nptr++;
960 while (wxIsdigit(*nptr)) nptr++;
961 }
962 if (*nptr == wxT('E') || *nptr == wxT('e')) {
963 nptr++;
964 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
965 while (wxIsdigit(*nptr)) nptr++;
966 }
967
968 wxString data(nptr, nptr-start);
969 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
970 char *rdat = wxMBSTRINGCAST dat;
971 double ret = strtod(dat, &rdat);
972
973 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
974
975 return ret;
976}
977
978WXDLLEXPORT long int wxStrtol(const wxChar *nptr, wxChar **endptr, int base)
979{
980 const wxChar *start = nptr;
981
982 // FIXME: only correct for C locale
983 while (wxIsspace(*nptr)) nptr++;
984 if (*nptr == wxT('+') || *nptr == wxT('-')) nptr++;
985 if (((base == 0) || (base == 16)) &&
986 (nptr[0] == wxT('0') && nptr[1] == wxT('x'))) {
987 nptr += 2;
988 base = 16;
989 }
990 else if ((base == 0) && (nptr[0] == wxT('0'))) base = 8;
991 else if (base == 0) base = 10;
992
993 while ((wxIsdigit(*nptr) && (*nptr - wxT('0') < base)) ||
994 (wxIsalpha(*nptr) && (wxToupper(*nptr) - wxT('A') + 10 < base))) nptr++;
995
996 wxString data(start, nptr-start);
997 wxWX2MBbuf dat = data.mb_str(wxConvLibc);
998 char *rdat = wxMBSTRINGCAST dat;
999 long int ret = strtol(dat, &rdat, base);
1000
1001 if (endptr) *endptr = (wxChar *)(start + (rdat - (const char *)dat));
1002
1003 return ret;
1004}
1005
1006WXDLLEXPORT unsigned long int wxStrtoul(const wxChar *nptr, wxChar **endptr, int base)
1007{
1008 return (unsigned long int) wxStrtol(nptr, endptr, base);
1009}
1010
1011#endif // wxNEED_WX_STRING_H
1012
1013#ifdef wxNEED_WX_STDIO_H
1014WXDLLEXPORT FILE * wxFopen(const wxChar *path, const wxChar *mode)
1015{
1016 char mode_buffer[10];
1017 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1018 mode_buffer[i] = (char) mode[i];
1019
1020 return fopen( wxConvFile.cWX2MB(path), mode_buffer );
1021}
1022
1023WXDLLEXPORT FILE * wxFreopen(const wxChar *path, const wxChar *mode, FILE *stream)
1024{
1025 char mode_buffer[10];
1026 for (size_t i = 0; i < wxStrlen(mode)+1; i++)
1027 mode_buffer[i] = (char) mode[i];
1028
1029 return freopen( wxConvFile.cWX2MB(path), mode_buffer, stream );
1030}
1031
1032WXDLLEXPORT int wxRemove(const wxChar *path)
1033{
1034 return remove( wxConvFile.cWX2MB(path) );
1035}
1036
1037WXDLLEXPORT int wxRename(const wxChar *oldpath, const wxChar *newpath)
1038{
1039 return rename( wxConvFile.cWX2MB(oldpath), wxConvFile.cWX2MB(newpath) );
1040}
1041#endif
1042
1043#ifndef wxAtof
1044double WXDLLEXPORT wxAtof(const wxChar *psz)
1045{
1046#ifdef __WXWINCE__
1047 double d;
1048 wxString str(psz);
1049 if (str.ToDouble(& d))
1050 return d;
1051
1052 return 0.0;
1053#else
1054 return atof(wxConvLibc.cWX2MB(psz));
1055#endif
1056}
1057#endif
1058
1059#ifdef wxNEED_WX_STDLIB_H
1060int WXDLLEXPORT wxAtoi(const wxChar *psz)
1061{
1062 return atoi(wxConvLibc.cWX2MB(psz));
1063}
1064
1065long WXDLLEXPORT wxAtol(const wxChar *psz)
1066{
1067 return atol(wxConvLibc.cWX2MB(psz));
1068}
1069
1070wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
1071{
1072#if wxUSE_UNICODE
1073 // NB: buffer returned by getenv() is allowed to be overwritten next
1074 // time getenv() is called, so it is OK to use static string
1075 // buffer to hold the data.
1076 static wxWCharBuffer value((wxChar*)NULL);
1077 value = wxConvLibc.cMB2WX(getenv(wxConvLibc.cWX2MB(name)));
1078 return value.data();
1079#else
1080 return getenv(name);
1081#endif
1082}
1083
1084int WXDLLEXPORT wxSystem(const wxChar *psz)
1085{
1086 return system(wxConvLibc.cWX2MB(psz));
1087}
1088
1089#endif // wxNEED_WX_STDLIB_H
1090
1091#ifdef wxNEED_WX_TIME_H
1092WXDLLEXPORT size_t
1093wxStrftime(wxChar *s, size_t maxsize, const wxChar *fmt, const struct tm *tm)
1094{
1095 if ( !maxsize )
1096 return 0;
1097
1098 wxCharBuffer buf(maxsize);
1099
1100 wxCharBuffer bufFmt(wxConvLibc.cWX2MB(fmt));
1101 if ( !bufFmt )
1102 return 0;
1103
1104 size_t ret = strftime(buf.data(), maxsize, bufFmt, tm);
1105 if ( !ret )
1106 return 0;
1107
1108 wxWCharBuffer wbuf = wxConvLibc.cMB2WX(buf);
1109 if ( !wbuf )
1110 return 0;
1111
1112 wxStrncpy(s, wbuf, maxsize);
1113 return wxStrlen(s);
1114}
1115#endif // wxNEED_WX_TIME_H
1116
1117#ifndef wxCtime
1118WXDLLEXPORT wxChar *wxCtime(const time_t *timep)
1119{
1120 // normally the string is 26 chars but give one more in case some broken
1121 // DOS compiler decides to use "\r\n" instead of "\n" at the end
1122 static wxChar buf[27];
1123
1124 // ctime() is guaranteed to return a string containing only ASCII
1125 // characters, as its format is always the same for any locale
1126 wxStrncpy(buf, wxString::FromAscii(ctime(timep)), WXSIZEOF(buf));
1127 buf[WXSIZEOF(buf) - 1] = _T('\0');
1128
1129 return buf;
1130}
1131#endif // wxCtime
1132
1133#endif // wxUSE_WCHAR_T
1134
1135// ----------------------------------------------------------------------------
1136// functions which we may need even if !wxUSE_WCHAR_T
1137// ----------------------------------------------------------------------------
1138
1139#ifndef wxStrtok
1140
1141WXDLLEXPORT wxChar * wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
1142{
1143 if (!psz)
1144 {
1145 psz = *save_ptr;
1146 if ( !psz )
1147 return NULL;
1148 }
1149
1150 psz += wxStrspn(psz, delim);
1151 if (!*psz)
1152 {
1153 *save_ptr = (wxChar *)NULL;
1154 return (wxChar *)NULL;
1155 }
1156
1157 wxChar *ret = psz;
1158 psz = wxStrpbrk(psz, delim);
1159 if (!psz)
1160 {
1161 *save_ptr = (wxChar*)NULL;
1162 }
1163 else
1164 {
1165 *psz = wxT('\0');
1166 *save_ptr = psz + 1;
1167 }
1168
1169 return ret;
1170}
1171
1172#endif // wxStrtok
1173
1174// ----------------------------------------------------------------------------
1175// missing C RTL functions
1176// ----------------------------------------------------------------------------
1177
1178#ifdef wxNEED_STRDUP
1179
1180char *strdup(const char *s)
1181{
1182 char *dest = (char*) malloc( strlen( s ) + 1 ) ;
1183 if ( dest )
1184 strcpy( dest , s ) ;
1185 return dest ;
1186}
1187#endif // wxNEED_STRDUP
1188
1189#if defined(__WXWINCE__) && (_WIN32_WCE <= 211)
1190
1191void *calloc( size_t num, size_t size )
1192{
1193 void** ptr = (void **)malloc(num * size);
1194 memset( ptr, 0, num * size);
1195 return ptr;
1196}
1197
1198#endif // __WXWINCE__ <= 211
1199
1200#ifdef __WXWINCE__
1201
1202int wxRemove(const wxChar *path)
1203{
1204 return ::DeleteFile(path) == 0;
1205}
1206
1207#endif