]> git.saurik.com Git - wxWidgets.git/blame - src/common/strconv.cpp
restore status bar text after a menu has been shown
[wxWidgets.git] / src / common / strconv.cpp
CommitLineData
6001e347
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: strconv.cpp
3// Purpose: Unicode conversion classes
3a0d76bc 4// Author: Ove Kaaven, Robert Roebling, Vadim Zeitlin, Vaclav Slavik
6001e347
RR
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
e95354ec
VZ
8// Copyright: (c) 1999 Ove Kaaven, Robert Roebling, Vaclav Slavik
9// (c) 2000-2003 Vadim Zeitlin
55d99c7a 10// Licence: wxWindows licence
6001e347
RR
11/////////////////////////////////////////////////////////////////////////////
12
f6bcfd97
BP
13// ============================================================================
14// declarations
15// ============================================================================
16
17// ----------------------------------------------------------------------------
18// headers
19// ----------------------------------------------------------------------------
20
14f355c2 21#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
6001e347
RR
22 #pragma implementation "strconv.h"
23#endif
24
25// For compilers that support precompilation, includes "wx.h".
26#include "wx/wxprec.h"
27
28#ifdef __BORLANDC__
29 #pragma hdrstop
30#endif
31
373658eb
VZ
32#ifndef WX_PRECOMP
33 #include "wx/intl.h"
34 #include "wx/log.h"
35#endif // WX_PRECOMP
36
bde4baac
VZ
37#include "wx/strconv.h"
38
39#if wxUSE_WCHAR_T
40
0a1c1e62 41#ifdef __WXMSW__
373658eb 42 #include "wx/msw/private.h"
0a1c1e62
GRG
43#endif
44
1c193821 45#ifndef __WXWINCE__
1cd52418 46#include <errno.h>
1c193821
JS
47#endif
48
6001e347
RR
49#include <ctype.h>
50#include <string.h>
51#include <stdlib.h>
52
e95354ec
VZ
53#if defined(__WIN32__) && !defined(__WXMICROWIN__)
54 #define wxHAVE_WIN32_MB2WC
55#endif // __WIN32__ but !__WXMICROWIN__
56
373658eb
VZ
57// ----------------------------------------------------------------------------
58// headers
59// ----------------------------------------------------------------------------
7af284fd 60
6001e347 61#ifdef __SALFORDC__
373658eb 62 #include <clib.h>
6001e347
RR
63#endif
64
b040e242 65#ifdef HAVE_ICONV
373658eb 66 #include <iconv.h>
1cd52418 67#endif
1cd52418 68
373658eb
VZ
69#include "wx/encconv.h"
70#include "wx/fontmap.h"
71
72// ----------------------------------------------------------------------------
73// macros
74// ----------------------------------------------------------------------------
3e61dfb0 75
1cd52418 76#define BSWAP_UCS4(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT32_SWAP_ALWAYS(str[_c]); }
3a0d76bc 77#define BSWAP_UTF16(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT16_SWAP_ALWAYS(str[_c]); }
1cd52418
OK
78
79#if SIZEOF_WCHAR_T == 4
3a0d76bc
VS
80 #define WC_NAME "UCS4"
81 #define WC_BSWAP BSWAP_UCS4
82 #ifdef WORDS_BIGENDIAN
83 #define WC_NAME_BEST "UCS-4BE"
84 #else
85 #define WC_NAME_BEST "UCS-4LE"
86 #endif
1cd52418 87#elif SIZEOF_WCHAR_T == 2
3a0d76bc
VS
88 #define WC_NAME "UTF16"
89 #define WC_BSWAP BSWAP_UTF16
a3f2769e 90 #define WC_UTF16
3a0d76bc
VS
91 #ifdef WORDS_BIGENDIAN
92 #define WC_NAME_BEST "UTF-16BE"
93 #else
94 #define WC_NAME_BEST "UTF-16LE"
95 #endif
bab1e722 96#else // sizeof(wchar_t) != 2 nor 4
bde4baac
VZ
97 // does this ever happen?
98 #error "Unknown sizeof(wchar_t): please report this to wx-dev@lists.wxwindows.org"
1cd52418
OK
99#endif
100
373658eb
VZ
101// ============================================================================
102// implementation
103// ============================================================================
104
105// ----------------------------------------------------------------------------
c91830cb 106// UTF-16 en/decoding to/from UCS-4
373658eb 107// ----------------------------------------------------------------------------
6001e347 108
b0a6bb75 109
c91830cb 110static size_t encode_utf16(wxUint32 input, wxUint16 *output)
1cd52418 111{
dccce9ea 112 if (input<=0xffff)
4def3b35 113 {
c91830cb 114 if (output) *output++ = (wxUint16) input;
4def3b35 115 return 1;
dccce9ea
VZ
116 }
117 else if (input>=0x110000)
4def3b35
VS
118 {
119 return (size_t)-1;
dccce9ea
VZ
120 }
121 else
4def3b35 122 {
dccce9ea 123 if (output)
4def3b35 124 {
c91830cb
VZ
125 *output++ = (wxUint16) ((input >> 10)+0xd7c0);
126 *output++ = (wxUint16) ((input&0x3ff)+0xdc00);
4def3b35
VS
127 }
128 return 2;
1cd52418 129 }
1cd52418
OK
130}
131
c91830cb 132static size_t decode_utf16(const wxUint16* input, wxUint32& output)
1cd52418 133{
dccce9ea 134 if ((*input<0xd800) || (*input>0xdfff))
4def3b35
VS
135 {
136 output = *input;
137 return 1;
dccce9ea
VZ
138 }
139 else if ((input[1]<0xdc00) || (input[1]>=0xdfff))
4def3b35
VS
140 {
141 output = *input;
142 return (size_t)-1;
dccce9ea
VZ
143 }
144 else
4def3b35
VS
145 {
146 output = ((input[0] - 0xd7c0) << 10) + (input[1] - 0xdc00);
147 return 2;
148 }
1cd52418
OK
149}
150
b0a6bb75 151
f6bcfd97 152// ----------------------------------------------------------------------------
6001e347 153// wxMBConv
f6bcfd97 154// ----------------------------------------------------------------------------
6001e347 155
2b5f62a0
VZ
156wxMBConv::~wxMBConv()
157{
158 // nothing to do here
159}
160
6001e347
RR
161const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const
162{
2b5f62a0 163 if ( psz )
6001e347 164 {
2b5f62a0
VZ
165 // calculate the length of the buffer needed first
166 size_t nLen = MB2WC(NULL, psz, 0);
167 if ( nLen != (size_t)-1 )
168 {
169 // now do the actual conversion
170 wxWCharBuffer buf(nLen);
171 MB2WC(buf.data(), psz, nLen + 1); // with the trailing NUL
172
173 return buf;
174 }
f6bcfd97 175 }
2b5f62a0
VZ
176
177 wxWCharBuffer buf((wchar_t *)NULL);
178
179 return buf;
6001e347
RR
180}
181
e5cceba0 182const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const
6001e347 183{
2b5f62a0
VZ
184 if ( pwz )
185 {
186 size_t nLen = WC2MB(NULL, pwz, 0);
187 if ( nLen != (size_t)-1 )
188 {
c91830cb
VZ
189 wxCharBuffer buf(nLen+3); // space for a wxUint32 trailing zero
190 WC2MB(buf.data(), pwz, nLen + 4);
2b5f62a0
VZ
191
192 return buf;
193 }
194 }
195
196 wxCharBuffer buf((char *)NULL);
e5cceba0 197
e5cceba0 198 return buf;
6001e347
RR
199}
200
6001e347 201// ----------------------------------------------------------------------------
bde4baac 202// wxMBConvLibc
6001e347
RR
203// ----------------------------------------------------------------------------
204
bde4baac
VZ
205size_t wxMBConvLibc::MB2WC(wchar_t *buf, const char *psz, size_t n) const
206{
207 return wxMB2WC(buf, psz, n);
208}
209
210size_t wxMBConvLibc::WC2MB(char *buf, const wchar_t *psz, size_t n) const
211{
212 return wxWC2MB(buf, psz, n);
213}
214
215// ----------------------------------------------------------------------------
216// UTF-7
217// ----------------------------------------------------------------------------
6001e347
RR
218
219#if 0
220static char utf7_setD[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
221 "abcdefghijklmnopqrstuvwxyz"
222 "0123456789'(),-./:?";
223static char utf7_setO[]="!\"#$%&*;<=>@[]^_`{|}";
224static char utf7_setB[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
225 "abcdefghijklmnopqrstuvwxyz"
226 "0123456789+/";
227#endif
228
229// TODO: write actual implementations of UTF-7 here
230size_t wxMBConvUTF7::MB2WC(wchar_t * WXUNUSED(buf),
231 const char * WXUNUSED(psz),
232 size_t WXUNUSED(n)) const
233{
234 return 0;
235}
236
237size_t wxMBConvUTF7::WC2MB(char * WXUNUSED(buf),
238 const wchar_t * WXUNUSED(psz),
239 size_t WXUNUSED(n)) const
240{
241 return 0;
242}
243
f6bcfd97 244// ----------------------------------------------------------------------------
6001e347 245// UTF-8
f6bcfd97 246// ----------------------------------------------------------------------------
6001e347 247
dccce9ea 248static wxUint32 utf8_max[]=
4def3b35 249 { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff };
6001e347
RR
250
251size_t wxMBConvUTF8::MB2WC(wchar_t *buf, const char *psz, size_t n) const
252{
4def3b35
VS
253 size_t len = 0;
254
dccce9ea 255 while (*psz && ((!buf) || (len < n)))
4def3b35
VS
256 {
257 unsigned char cc = *psz++, fc = cc;
258 unsigned cnt;
dccce9ea 259 for (cnt = 0; fc & 0x80; cnt++)
4def3b35 260 fc <<= 1;
dccce9ea 261 if (!cnt)
4def3b35
VS
262 {
263 // plain ASCII char
dccce9ea 264 if (buf)
4def3b35
VS
265 *buf++ = cc;
266 len++;
dccce9ea
VZ
267 }
268 else
4def3b35
VS
269 {
270 cnt--;
dccce9ea 271 if (!cnt)
4def3b35
VS
272 {
273 // invalid UTF-8 sequence
274 return (size_t)-1;
dccce9ea
VZ
275 }
276 else
4def3b35
VS
277 {
278 unsigned ocnt = cnt - 1;
279 wxUint32 res = cc & (0x3f >> cnt);
dccce9ea 280 while (cnt--)
4def3b35
VS
281 {
282 cc = *psz++;
dccce9ea 283 if ((cc & 0xC0) != 0x80)
4def3b35
VS
284 {
285 // invalid UTF-8 sequence
286 return (size_t)-1;
287 }
288 res = (res << 6) | (cc & 0x3f);
289 }
dccce9ea 290 if (res <= utf8_max[ocnt])
4def3b35
VS
291 {
292 // illegal UTF-8 encoding
293 return (size_t)-1;
294 }
1cd52418 295#ifdef WC_UTF16
b5153fd8
VZ
296 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
297 size_t pa = encode_utf16(res, (wxUint16 *)buf);
4def3b35
VS
298 if (pa == (size_t)-1)
299 return (size_t)-1;
dccce9ea 300 if (buf)
4def3b35
VS
301 buf += pa;
302 len += pa;
373658eb 303#else // !WC_UTF16
dccce9ea 304 if (buf)
4def3b35
VS
305 *buf++ = res;
306 len++;
373658eb 307#endif // WC_UTF16/!WC_UTF16
4def3b35
VS
308 }
309 }
6001e347 310 }
dccce9ea 311 if (buf && (len < n))
4def3b35
VS
312 *buf = 0;
313 return len;
6001e347
RR
314}
315
316size_t wxMBConvUTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const
317{
4def3b35 318 size_t len = 0;
6001e347 319
dccce9ea 320 while (*psz && ((!buf) || (len < n)))
4def3b35
VS
321 {
322 wxUint32 cc;
1cd52418 323#ifdef WC_UTF16
b5153fd8
VZ
324 // cast is ok for WC_UTF16
325 size_t pa = decode_utf16((const wxUint16 *)psz, cc);
4def3b35 326 psz += (pa == (size_t)-1) ? 1 : pa;
1cd52418 327#else
4def3b35
VS
328 cc=(*psz++) & 0x7fffffff;
329#endif
330 unsigned cnt;
331 for (cnt = 0; cc > utf8_max[cnt]; cnt++) {}
dccce9ea 332 if (!cnt)
4def3b35
VS
333 {
334 // plain ASCII char
dccce9ea 335 if (buf)
574c939e 336 *buf++ = (char) cc;
4def3b35 337 len++;
dccce9ea
VZ
338 }
339
340 else
4def3b35
VS
341 {
342 len += cnt + 1;
dccce9ea 343 if (buf)
4def3b35 344 {
574c939e 345 *buf++ = (char) ((-128 >> cnt) | ((cc >> (cnt * 6)) & (0x3f >> cnt)));
4def3b35 346 while (cnt--)
574c939e 347 *buf++ = (char) (0x80 | ((cc >> (cnt * 6)) & 0x3f));
4def3b35
VS
348 }
349 }
6001e347 350 }
4def3b35
VS
351
352 if (buf && (len<n)) *buf = 0;
adb45366 353
4def3b35 354 return len;
6001e347
RR
355}
356
c91830cb
VZ
357
358
359
360// ----------------------------------------------------------------------------
361// UTF-16
362// ----------------------------------------------------------------------------
363
364#ifdef WORDS_BIGENDIAN
bde4baac
VZ
365 #define wxMBConvUTF16straight wxMBConvUTF16BE
366 #define wxMBConvUTF16swap wxMBConvUTF16LE
c91830cb 367#else
bde4baac
VZ
368 #define wxMBConvUTF16swap wxMBConvUTF16BE
369 #define wxMBConvUTF16straight wxMBConvUTF16LE
c91830cb
VZ
370#endif
371
372
c91830cb
VZ
373#ifdef WC_UTF16
374
c91830cb
VZ
375// copy 16bit MB to 16bit String
376size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf, const char *psz, size_t n) const
377{
378 size_t len=0;
379
380 while (*(wxUint16*)psz && (!buf || len < n))
381 {
382 if (buf)
383 *buf++ = *(wxUint16*)psz;
384 len++;
385
386 psz += sizeof(wxUint16);
387 }
388 if (buf && len<n) *buf=0;
389
390 return len;
391}
392
393
394// copy 16bit String to 16bit MB
395size_t wxMBConvUTF16straight::WC2MB(char *buf, const wchar_t *psz, size_t n) const
396{
397 size_t len=0;
398
399 while (*psz && (!buf || len < n))
400 {
401 if (buf)
402 {
403 *(wxUint16*)buf = *psz;
404 buf += sizeof(wxUint16);
405 }
406 len += sizeof(wxUint16);
407 psz++;
408 }
409 if (buf && len<=n-sizeof(wxUint16)) *(wxUint16*)buf=0;
410
411 return len;
412}
413
414
415// swap 16bit MB to 16bit String
416size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf, const char *psz, size_t n) const
417{
418 size_t len=0;
419
420 while (*(wxUint16*)psz && (!buf || len < n))
421 {
422 if (buf)
423 {
424 ((char *)buf)[0] = psz[1];
425 ((char *)buf)[1] = psz[0];
426 buf++;
427 }
428 len++;
429 psz += sizeof(wxUint16);
430 }
431 if (buf && len<n) *buf=0;
432
433 return len;
434}
435
436
437// swap 16bit MB to 16bit String
438size_t wxMBConvUTF16swap::WC2MB(char *buf, const wchar_t *psz, size_t n) const
439{
440 size_t len=0;
441
442 while (*psz && (!buf || len < n))
443 {
444 if (buf)
445 {
446 *buf++ = ((char*)psz)[1];
447 *buf++ = ((char*)psz)[0];
448 }
449 len += sizeof(wxUint16);
450 psz++;
451 }
452 if (buf && len<=n-sizeof(wxUint16)) *(wxUint16*)buf=0;
453
454 return len;
455}
456
457
458#else // WC_UTF16
459
460
461// copy 16bit MB to 32bit String
462size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf, const char *psz, size_t n) const
463{
464 size_t len=0;
465
466 while (*(wxUint16*)psz && (!buf || len < n))
467 {
468 wxUint32 cc;
469 size_t pa=decode_utf16((wxUint16*)psz, cc);
470 if (pa == (size_t)-1)
471 return pa;
472
473 if (buf)
474 *buf++ = cc;
475 len++;
476 psz += pa * sizeof(wxUint16);
477 }
478 if (buf && len<n) *buf=0;
479
480 return len;
481}
482
483
484// copy 32bit String to 16bit MB
485size_t wxMBConvUTF16straight::WC2MB(char *buf, const wchar_t *psz, size_t n) const
486{
487 size_t len=0;
488
489 while (*psz && (!buf || len < n))
490 {
491 wxUint16 cc[2];
492 size_t pa=encode_utf16(*psz, cc);
493
494 if (pa == (size_t)-1)
495 return pa;
496
497 if (buf)
498 {
69b80d28 499 *(wxUint16*)buf = cc[0];
b5153fd8 500 buf += sizeof(wxUint16);
c91830cb 501 if (pa > 1)
69b80d28
VZ
502 {
503 *(wxUint16*)buf = cc[1];
504 buf += sizeof(wxUint16);
505 }
c91830cb
VZ
506 }
507
508 len += pa*sizeof(wxUint16);
509 psz++;
510 }
511 if (buf && len<=n-sizeof(wxUint16)) *(wxUint16*)buf=0;
512
513 return len;
514}
515
516
517// swap 16bit MB to 32bit String
518size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf, const char *psz, size_t n) const
519{
520 size_t len=0;
521
522 while (*(wxUint16*)psz && (!buf || len < n))
523 {
524 wxUint32 cc;
525 char tmp[4];
526 tmp[0]=psz[1]; tmp[1]=psz[0];
527 tmp[2]=psz[3]; tmp[3]=psz[2];
528
529 size_t pa=decode_utf16((wxUint16*)tmp, cc);
530 if (pa == (size_t)-1)
531 return pa;
532
533 if (buf)
534 *buf++ = cc;
535
536 len++;
537 psz += pa * sizeof(wxUint16);
538 }
539 if (buf && len<n) *buf=0;
540
541 return len;
542}
543
544
545// swap 32bit String to 16bit MB
546size_t wxMBConvUTF16swap::WC2MB(char *buf, const wchar_t *psz, size_t n) const
547{
548 size_t len=0;
549
550 while (*psz && (!buf || len < n))
551 {
552 wxUint16 cc[2];
553 size_t pa=encode_utf16(*psz, cc);
554
555 if (pa == (size_t)-1)
556 return pa;
557
558 if (buf)
559 {
560 *buf++ = ((char*)cc)[1];
561 *buf++ = ((char*)cc)[0];
562 if (pa > 1)
563 {
564 *buf++ = ((char*)cc)[3];
565 *buf++ = ((char*)cc)[2];
566 }
567 }
568
569 len += pa*sizeof(wxUint16);
570 psz++;
571 }
572 if (buf && len<=n-sizeof(wxUint16)) *(wxUint16*)buf=0;
573
574 return len;
575}
576
577#endif // WC_UTF16
578
579
580// ----------------------------------------------------------------------------
581// UTF-32
582// ----------------------------------------------------------------------------
583
584#ifdef WORDS_BIGENDIAN
585#define wxMBConvUTF32straight wxMBConvUTF32BE
586#define wxMBConvUTF32swap wxMBConvUTF32LE
587#else
588#define wxMBConvUTF32swap wxMBConvUTF32BE
589#define wxMBConvUTF32straight wxMBConvUTF32LE
590#endif
591
592
593WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32LE) wxConvUTF32LE;
594WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32BE) wxConvUTF32BE;
595
596
597#ifdef WC_UTF16
598
599// copy 32bit MB to 16bit String
600size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf, const char *psz, size_t n) const
601{
602 size_t len=0;
603
604 while (*(wxUint32*)psz && (!buf || len < n))
605 {
606 wxUint16 cc[2];
607
608 size_t pa=encode_utf16(*(wxUint32*)psz, cc);
609 if (pa == (size_t)-1)
610 return pa;
611
612 if (buf)
613 {
614 *buf++ = cc[0];
615 if (pa > 1)
616 *buf++ = cc[1];
617 }
618 len += pa;
619 psz += sizeof(wxUint32);
620 }
621 if (buf && len<n) *buf=0;
622
623 return len;
624}
625
626
627// copy 16bit String to 32bit MB
628size_t wxMBConvUTF32straight::WC2MB(char *buf, const wchar_t *psz, size_t n) const
629{
630 size_t len=0;
631
632 while (*psz && (!buf || len < n))
633 {
634 wxUint32 cc;
635
b5153fd8
VZ
636 // cast is ok for WC_UTF16
637 size_t pa = decode_utf16((const wxUint16 *)psz, cc);
c91830cb
VZ
638 if (pa == (size_t)-1)
639 return pa;
640
641 if (buf)
642 {
643 *(wxUint32*)buf = cc;
644 buf += sizeof(wxUint32);
645 }
646 len += sizeof(wxUint32);
647 psz += pa;
648 }
b5153fd8
VZ
649
650 if (buf && len<=n-sizeof(wxUint32))
651 *(wxUint32*)buf=0;
c91830cb
VZ
652
653 return len;
654}
655
656
657
658// swap 32bit MB to 16bit String
659size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf, const char *psz, size_t n) const
660{
661 size_t len=0;
662
663 while (*(wxUint32*)psz && (!buf || len < n))
664 {
665 char tmp[4];
666 tmp[0] = psz[3]; tmp[1] = psz[2];
667 tmp[2] = psz[1]; tmp[3] = psz[0];
668
669
670 wxUint16 cc[2];
671
672 size_t pa=encode_utf16(*(wxUint32*)tmp, cc);
673 if (pa == (size_t)-1)
674 return pa;
675
676 if (buf)
677 {
678 *buf++ = cc[0];
679 if (pa > 1)
680 *buf++ = cc[1];
681 }
682 len += pa;
683 psz += sizeof(wxUint32);
684 }
b5153fd8
VZ
685
686 if (buf && len<n)
687 *buf=0;
c91830cb
VZ
688
689 return len;
690}
691
692
693// swap 16bit String to 32bit MB
694size_t wxMBConvUTF32swap::WC2MB(char *buf, const wchar_t *psz, size_t n) const
695{
696 size_t len=0;
697
698 while (*psz && (!buf || len < n))
699 {
700 char cc[4];
701
b5153fd8
VZ
702 // cast is ok for WC_UTF16
703 size_t pa=decode_utf16((const wxUint16 *)psz, *(wxUint32*)cc);
c91830cb
VZ
704 if (pa == (size_t)-1)
705 return pa;
706
707 if (buf)
708 {
709 *buf++ = cc[3];
710 *buf++ = cc[2];
711 *buf++ = cc[1];
712 *buf++ = cc[0];
713 }
714 len += sizeof(wxUint32);
715 psz += pa;
716 }
b5153fd8
VZ
717
718 if (buf && len<=n-sizeof(wxUint32))
719 *(wxUint32*)buf=0;
c91830cb
VZ
720
721 return len;
722}
723
724#else // WC_UTF16
725
726
727// copy 32bit MB to 32bit String
728size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf, const char *psz, size_t n) const
729{
730 size_t len=0;
731
732 while (*(wxUint32*)psz && (!buf || len < n))
733 {
734 if (buf)
735 *buf++ = *(wxUint32*)psz;
736 len++;
737 psz += sizeof(wxUint32);
738 }
b5153fd8
VZ
739
740 if (buf && len<n)
741 *buf=0;
c91830cb
VZ
742
743 return len;
744}
745
746
747// copy 32bit String to 32bit MB
748size_t wxMBConvUTF32straight::WC2MB(char *buf, const wchar_t *psz, size_t n) const
749{
750 size_t len=0;
751
752 while (*psz && (!buf || len < n))
753 {
754 if (buf)
755 {
756 *(wxUint32*)buf = *psz;
757 buf += sizeof(wxUint32);
758 }
759
760 len += sizeof(wxUint32);
761 psz++;
762 }
763
b5153fd8
VZ
764 if (buf && len<=n-sizeof(wxUint32))
765 *(wxUint32*)buf=0;
c91830cb
VZ
766
767 return len;
768}
769
770
771// swap 32bit MB to 32bit String
772size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf, const char *psz, size_t n) const
773{
774 size_t len=0;
775
776 while (*(wxUint32*)psz && (!buf || len < n))
777 {
778 if (buf)
779 {
780 ((char *)buf)[0] = psz[3];
781 ((char *)buf)[1] = psz[2];
782 ((char *)buf)[2] = psz[1];
783 ((char *)buf)[3] = psz[0];
784 buf++;
785 }
786 len++;
787 psz += sizeof(wxUint32);
788 }
b5153fd8
VZ
789
790 if (buf && len<n)
791 *buf=0;
c91830cb
VZ
792
793 return len;
794}
795
796
797// swap 32bit String to 32bit MB
798size_t wxMBConvUTF32swap::WC2MB(char *buf, const wchar_t *psz, size_t n) const
799{
800 size_t len=0;
801
802 while (*psz && (!buf || len < n))
803 {
804 if (buf)
805 {
806 *buf++ = ((char *)psz)[3];
807 *buf++ = ((char *)psz)[2];
808 *buf++ = ((char *)psz)[1];
809 *buf++ = ((char *)psz)[0];
810 }
811 len += sizeof(wxUint32);
812 psz++;
813 }
b5153fd8
VZ
814
815 if (buf && len<=n-sizeof(wxUint32))
816 *(wxUint32*)buf=0;
c91830cb
VZ
817
818 return len;
819}
820
821
822#endif // WC_UTF16
823
824
36acb880
VZ
825// ============================================================================
826// The classes doing conversion using the iconv_xxx() functions
827// ============================================================================
3caec1bb 828
b040e242 829#ifdef HAVE_ICONV
3a0d76bc 830
3caec1bb
VS
831// VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with E2BIG
832// if output buffer is _exactly_ as big as needed. Such case is (unless there's
833// yet another bug in glibc) the only case when iconv() returns with (size_t)-1
834// (which means error) and says there are 0 bytes left in the input buffer --
835// when _real_ error occurs, bytes-left-in-input buffer is non-zero. Hence,
836// this alternative test for iconv() failure.
837// [This bug does not appear in glibc 2.2.]
838#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1
839#define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \
840 (errno != E2BIG || bufLeft != 0))
841#else
842#define ICONV_FAILED(cres, bufLeft) (cres == (size_t)-1)
843#endif
844
ab217dba 845#define ICONV_CHAR_CAST(x) ((ICONV_CONST char **)(x))
36acb880
VZ
846
847// ----------------------------------------------------------------------------
e95354ec 848// wxMBConv_iconv: encapsulates an iconv character set
36acb880
VZ
849// ----------------------------------------------------------------------------
850
e95354ec 851class wxMBConv_iconv : public wxMBConv
1cd52418
OK
852{
853public:
e95354ec
VZ
854 wxMBConv_iconv(const wxChar *name);
855 virtual ~wxMBConv_iconv();
36acb880 856
bde4baac
VZ
857 virtual size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const;
858 virtual size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const;
36acb880 859
e95354ec 860 bool IsOk() const
36acb880
VZ
861 { return (m2w != (iconv_t)-1) && (w2m != (iconv_t)-1); }
862
863protected:
864 // the iconv handlers used to translate from multibyte to wide char and in
865 // the other direction
866 iconv_t m2w,
867 w2m;
868
869private:
e95354ec 870 // the name (for iconv_open()) of a wide char charset -- if none is
36acb880
VZ
871 // available on this machine, it will remain NULL
872 static const char *ms_wcCharsetName;
873
874 // true if the wide char encoding we use (i.e. ms_wcCharsetName) has
875 // different endian-ness than the native one
405d8f46 876 static bool ms_wcNeedsSwap;
36acb880
VZ
877};
878
e95354ec
VZ
879const char *wxMBConv_iconv::ms_wcCharsetName = NULL;
880bool wxMBConv_iconv::ms_wcNeedsSwap = false;
36acb880 881
e95354ec 882wxMBConv_iconv::wxMBConv_iconv(const wxChar *name)
36acb880 883{
04c79127
RR
884 // Do it the hard way
885 char cname[100];
886 for (size_t i = 0; i < wxStrlen(name)+1; i++)
887 cname[i] = (char) name[i];
888
36acb880
VZ
889 // check for charset that represents wchar_t:
890 if (ms_wcCharsetName == NULL)
f1339c56 891 {
e95354ec 892 ms_wcNeedsSwap = false;
dccce9ea 893
36acb880
VZ
894 // try charset with explicit bytesex info (e.g. "UCS-4LE"):
895 ms_wcCharsetName = WC_NAME_BEST;
04c79127 896 m2w = iconv_open(ms_wcCharsetName, cname);
3a0d76bc 897
36acb880
VZ
898 if (m2w == (iconv_t)-1)
899 {
900 // try charset w/o bytesex info (e.g. "UCS4")
901 // and check for bytesex ourselves:
902 ms_wcCharsetName = WC_NAME;
04c79127 903 m2w = iconv_open(ms_wcCharsetName, cname);
36acb880
VZ
904
905 // last bet, try if it knows WCHAR_T pseudo-charset
3a0d76bc
VS
906 if (m2w == (iconv_t)-1)
907 {
36acb880 908 ms_wcCharsetName = "WCHAR_T";
04c79127 909 m2w = iconv_open(ms_wcCharsetName, cname);
36acb880 910 }
3a0d76bc 911
36acb880
VZ
912 if (m2w != (iconv_t)-1)
913 {
914 char buf[2], *bufPtr;
915 wchar_t wbuf[2], *wbufPtr;
916 size_t insz, outsz;
917 size_t res;
918
919 buf[0] = 'A';
920 buf[1] = 0;
921 wbuf[0] = 0;
922 insz = 2;
923 outsz = SIZEOF_WCHAR_T * 2;
924 wbufPtr = wbuf;
925 bufPtr = buf;
926
927 res = iconv(m2w, ICONV_CHAR_CAST(&bufPtr), &insz,
928 (char**)&wbufPtr, &outsz);
929
930 if (ICONV_FAILED(res, insz))
3a0d76bc 931 {
36acb880
VZ
932 ms_wcCharsetName = NULL;
933 wxLogLastError(wxT("iconv"));
2b5f62a0 934 wxLogError(_("Conversion to charset '%s' doesn't work."), name);
3a0d76bc
VS
935 }
936 else
937 {
36acb880 938 ms_wcNeedsSwap = wbuf[0] != (wchar_t)buf[0];
3a0d76bc
VS
939 }
940 }
36acb880
VZ
941 else
942 {
943 ms_wcCharsetName = NULL;
373658eb 944
957686c8
VS
945 // VS: we must not output an error here, since wxWindows will safely
946 // fall back to using wxEncodingConverter.
947 wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name);
948 //wxLogError(
36acb880 949 }
3a0d76bc 950 }
36acb880 951 wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName, ms_wcNeedsSwap);
3a0d76bc 952 }
36acb880 953 else // we already have ms_wcCharsetName
3caec1bb 954 {
04c79127 955 m2w = iconv_open(ms_wcCharsetName, cname);
f1339c56 956 }
dccce9ea 957
36acb880
VZ
958 // NB: don't ever pass NULL to iconv_open(), it may crash!
959 if ( ms_wcCharsetName )
f1339c56 960 {
04c79127 961 w2m = iconv_open( cname, ms_wcCharsetName);
36acb880 962 }
405d8f46
VZ
963 else
964 {
965 w2m = (iconv_t)-1;
966 }
36acb880 967}
3caec1bb 968
e95354ec 969wxMBConv_iconv::~wxMBConv_iconv()
36acb880
VZ
970{
971 if ( m2w != (iconv_t)-1 )
972 iconv_close(m2w);
973 if ( w2m != (iconv_t)-1 )
974 iconv_close(w2m);
975}
3a0d76bc 976
bde4baac 977size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
36acb880
VZ
978{
979 size_t inbuf = strlen(psz);
980 size_t outbuf = n * SIZEOF_WCHAR_T;
981 size_t res, cres;
982 // VS: Use these instead of psz, buf because iconv() modifies its arguments:
983 wchar_t *bufPtr = buf;
984 const char *pszPtr = psz;
985
986 if (buf)
987 {
988 // have destination buffer, convert there
989 cres = iconv(m2w,
990 ICONV_CHAR_CAST(&pszPtr), &inbuf,
991 (char**)&bufPtr, &outbuf);
992 res = n - (outbuf / SIZEOF_WCHAR_T);
dccce9ea 993
36acb880 994 if (ms_wcNeedsSwap)
3a0d76bc 995 {
36acb880
VZ
996 // convert to native endianness
997 WC_BSWAP(buf /* _not_ bufPtr */, res)
3a0d76bc 998 }
adb45366 999
49dd9820
VS
1000 // NB: iconv was given only strlen(psz) characters on input, and so
1001 // it couldn't convert the trailing zero. Let's do it ourselves
1002 // if there's some room left for it in the output buffer.
1003 if (res < n)
1004 buf[res] = 0;
36acb880
VZ
1005 }
1006 else
1007 {
1008 // no destination buffer... convert using temp buffer
1009 // to calculate destination buffer requirement
1010 wchar_t tbuf[8];
1011 res = 0;
1012 do {
1013 bufPtr = tbuf;
1014 outbuf = 8*SIZEOF_WCHAR_T;
1015
1016 cres = iconv(m2w,
1017 ICONV_CHAR_CAST(&pszPtr), &inbuf,
1018 (char**)&bufPtr, &outbuf );
1019
1020 res += 8-(outbuf/SIZEOF_WCHAR_T);
1021 } while ((cres==(size_t)-1) && (errno==E2BIG));
f1339c56 1022 }
dccce9ea 1023
36acb880 1024 if (ICONV_FAILED(cres, inbuf))
f1339c56 1025 {
36acb880
VZ
1026 //VS: it is ok if iconv fails, hence trace only
1027 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1028 return (size_t)-1;
1029 }
1030
1031 return res;
1032}
1033
bde4baac 1034size_t wxMBConv_iconv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
36acb880 1035{
f8d791e0 1036 size_t inbuf = wxWcslen(psz) * SIZEOF_WCHAR_T;
36acb880
VZ
1037 size_t outbuf = n;
1038 size_t res, cres;
3a0d76bc 1039
36acb880 1040 wchar_t *tmpbuf = 0;
3caec1bb 1041
36acb880
VZ
1042 if (ms_wcNeedsSwap)
1043 {
1044 // need to copy to temp buffer to switch endianness
1045 // this absolutely doesn't rock!
1046 // (no, doing WC_BSWAP twice on the original buffer won't help, as it
1047 // could be in read-only memory, or be accessed in some other thread)
1048 tmpbuf=(wchar_t*)malloc((inbuf+1)*SIZEOF_WCHAR_T);
1049 memcpy(tmpbuf,psz,(inbuf+1)*SIZEOF_WCHAR_T);
1050 WC_BSWAP(tmpbuf, inbuf)
1051 psz=tmpbuf;
1052 }
3a0d76bc 1053
36acb880
VZ
1054 if (buf)
1055 {
1056 // have destination buffer, convert there
1057 cres = iconv( w2m, ICONV_CHAR_CAST(&psz), &inbuf, &buf, &outbuf );
3a0d76bc 1058
36acb880 1059 res = n-outbuf;
adb45366 1060
49dd9820
VS
1061 // NB: iconv was given only wcslen(psz) characters on input, and so
1062 // it couldn't convert the trailing zero. Let's do it ourselves
1063 // if there's some room left for it in the output buffer.
1064 if (res < n)
1065 buf[0] = 0;
36acb880
VZ
1066 }
1067 else
1068 {
1069 // no destination buffer... convert using temp buffer
1070 // to calculate destination buffer requirement
1071 char tbuf[16];
1072 res = 0;
1073 do {
1074 buf = tbuf; outbuf = 16;
1075
1076 cres = iconv( w2m, ICONV_CHAR_CAST(&psz), &inbuf, &buf, &outbuf );
dccce9ea 1077
36acb880
VZ
1078 res += 16 - outbuf;
1079 } while ((cres==(size_t)-1) && (errno==E2BIG));
f1339c56 1080 }
dccce9ea 1081
36acb880
VZ
1082 if (ms_wcNeedsSwap)
1083 {
1084 free(tmpbuf);
1085 }
dccce9ea 1086
36acb880
VZ
1087 if (ICONV_FAILED(cres, inbuf))
1088 {
1089 //VS: it is ok if iconv fails, hence trace only
1090 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1091 return (size_t)-1;
1092 }
1093
1094 return res;
1095}
1096
b040e242 1097#endif // HAVE_ICONV
36acb880 1098
e95354ec 1099
36acb880
VZ
1100// ============================================================================
1101// Win32 conversion classes
1102// ============================================================================
1cd52418 1103
e95354ec 1104#ifdef wxHAVE_WIN32_MB2WC
373658eb 1105
8b04d4c4
VZ
1106// from utils.cpp
1107extern WXDLLIMPEXP_BASE long wxCharsetToCodepage(const wxChar *charset);
1108extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding);
373658eb 1109
e95354ec 1110class wxMBConv_win32 : public wxMBConv
1cd52418
OK
1111{
1112public:
bde4baac
VZ
1113 wxMBConv_win32()
1114 {
1115 m_CodePage = CP_ACP;
1116 }
1117
e95354ec 1118 wxMBConv_win32(const wxChar* name)
bde4baac
VZ
1119 {
1120 m_CodePage = wxCharsetToCodepage(name);
1121 }
dccce9ea 1122
e95354ec 1123 wxMBConv_win32(wxFontEncoding encoding)
bde4baac
VZ
1124 {
1125 m_CodePage = wxEncodingToCodepage(encoding);
1126 }
8b04d4c4 1127
bde4baac 1128 size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const
f1339c56 1129 {
2b5f62a0
VZ
1130 const size_t len = ::MultiByteToWideChar
1131 (
1132 m_CodePage, // code page
1133 0, // flags (none)
1134 psz, // input string
1135 -1, // its length (NUL-terminated)
b4da152e 1136 buf, // output string
2b5f62a0
VZ
1137 buf ? n : 0 // size of output buffer
1138 );
1139
03a991bc
VZ
1140 // note that it returns count of written chars for buf != NULL and size
1141 // of the needed buffer for buf == NULL so in either case the length of
1142 // the string (which never includes the terminating NUL) is one less
1143 return len ? len - 1 : (size_t)-1;
f1339c56 1144 }
dccce9ea 1145
bde4baac 1146 size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const
f1339c56 1147 {
2b5f62a0
VZ
1148 const size_t len = ::WideCharToMultiByte
1149 (
1150 m_CodePage, // code page
1151 0, // flags (none)
b4da152e 1152 psz, // input string
2b5f62a0
VZ
1153 -1, // it is (wide) NUL-terminated
1154 buf, // output buffer
1155 buf ? n : 0, // and its size
1156 NULL, // default "replacement" char
1157 NULL // [out] was it used?
1158 );
1159
03a991bc
VZ
1160 // see the comment above for the reason of "len - 1"
1161 return len ? len - 1 : (size_t)-1;
f1339c56 1162 }
dccce9ea 1163
e95354ec 1164 bool IsOk() const
b1d66b54 1165 { return m_CodePage != -1; }
f1339c56
RR
1166
1167public:
b1d66b54 1168 long m_CodePage;
1cd52418 1169};
e95354ec
VZ
1170
1171#endif // wxHAVE_WIN32_MB2WC
1172
1e6feb95 1173
36acb880
VZ
1174// ============================================================================
1175// wxEncodingConverter based conversion classes
1176// ============================================================================
1177
1e6feb95 1178#if wxUSE_FONTMAP
1cd52418 1179
e95354ec 1180class wxMBConv_wxwin : public wxMBConv
1cd52418 1181{
8b04d4c4
VZ
1182private:
1183 void Init()
1184 {
1185 m_ok = m2w.Init(m_enc, wxFONTENCODING_UNICODE) &&
1186 w2m.Init(wxFONTENCODING_UNICODE, m_enc);
1187 }
1188
6001e347 1189public:
f1339c56
RR
1190 // temporarily just use wxEncodingConverter stuff,
1191 // so that it works while a better implementation is built
e95354ec 1192 wxMBConv_wxwin(const wxChar* name)
f1339c56
RR
1193 {
1194 if (name)
e95354ec 1195 m_enc = wxFontMapper::Get()->CharsetToEncoding(name, false);
8b04d4c4
VZ
1196 else
1197 m_enc = wxFONTENCODING_SYSTEM;
cafbf6fb 1198
8b04d4c4
VZ
1199 Init();
1200 }
1201
e95354ec 1202 wxMBConv_wxwin(wxFontEncoding enc)
8b04d4c4
VZ
1203 {
1204 m_enc = enc;
1205
1206 Init();
f1339c56 1207 }
dccce9ea 1208
bde4baac 1209 size_t MB2WC(wchar_t *buf, const char *psz, size_t WXUNUSED(n)) const
f1339c56
RR
1210 {
1211 size_t inbuf = strlen(psz);
dccce9ea 1212 if (buf)
4def3b35 1213 m2w.Convert(psz,buf);
f1339c56
RR
1214 return inbuf;
1215 }
dccce9ea 1216
bde4baac 1217 size_t WC2MB(char *buf, const wchar_t *psz, size_t WXUNUSED(n)) const
f1339c56 1218 {
f8d791e0 1219 const size_t inbuf = wxWcslen(psz);
f1339c56
RR
1220 if (buf)
1221 w2m.Convert(psz,buf);
dccce9ea 1222
f1339c56
RR
1223 return inbuf;
1224 }
dccce9ea 1225
e95354ec 1226 bool IsOk() const { return m_ok; }
f1339c56
RR
1227
1228public:
8b04d4c4 1229 wxFontEncoding m_enc;
f1339c56 1230 wxEncodingConverter m2w, w2m;
cafbf6fb
VZ
1231
1232 // were we initialized successfully?
1233 bool m_ok;
fc7a2a60 1234
e95354ec 1235 DECLARE_NO_COPY_CLASS(wxMBConv_wxwin)
f6bcfd97 1236};
6001e347 1237
1e6feb95
VZ
1238#endif // wxUSE_FONTMAP
1239
36acb880
VZ
1240// ============================================================================
1241// wxCSConv implementation
1242// ============================================================================
1243
8b04d4c4 1244void wxCSConv::Init()
6001e347 1245{
e95354ec
VZ
1246 m_name = NULL;
1247 m_convReal = NULL;
1248 m_deferred = true;
1249}
1250
8b04d4c4
VZ
1251wxCSConv::wxCSConv(const wxChar *charset)
1252{
1253 Init();
82713003 1254
e95354ec
VZ
1255 if ( charset )
1256 {
e95354ec
VZ
1257 SetName(charset);
1258 }
bda3d86a
VZ
1259
1260 m_encoding = wxFONTENCODING_SYSTEM;
6001e347
RR
1261}
1262
8b04d4c4
VZ
1263wxCSConv::wxCSConv(wxFontEncoding encoding)
1264{
bda3d86a 1265 if ( encoding == wxFONTENCODING_MAX || encoding == wxFONTENCODING_DEFAULT )
e95354ec
VZ
1266 {
1267 wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
1268
1269 encoding = wxFONTENCODING_SYSTEM;
1270 }
1271
8b04d4c4
VZ
1272 Init();
1273
bda3d86a 1274 m_encoding = encoding;
8b04d4c4
VZ
1275}
1276
6001e347
RR
1277wxCSConv::~wxCSConv()
1278{
65e50848
JS
1279 Clear();
1280}
1281
54380f29 1282wxCSConv::wxCSConv(const wxCSConv& conv)
8b04d4c4 1283 : wxMBConv()
54380f29 1284{
8b04d4c4
VZ
1285 Init();
1286
54380f29 1287 SetName(conv.m_name);
8b04d4c4 1288 m_encoding = conv.m_encoding;
54380f29
GD
1289}
1290
1291wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
1292{
1293 Clear();
8b04d4c4 1294
54380f29 1295 SetName(conv.m_name);
8b04d4c4
VZ
1296 m_encoding = conv.m_encoding;
1297
54380f29
GD
1298 return *this;
1299}
1300
65e50848
JS
1301void wxCSConv::Clear()
1302{
8b04d4c4 1303 free(m_name);
e95354ec 1304 delete m_convReal;
8b04d4c4 1305
65e50848 1306 m_name = NULL;
e95354ec 1307 m_convReal = NULL;
6001e347
RR
1308}
1309
1310void wxCSConv::SetName(const wxChar *charset)
1311{
f1339c56
RR
1312 if (charset)
1313 {
1314 m_name = wxStrdup(charset);
e95354ec 1315 m_deferred = true;
f1339c56 1316 }
6001e347
RR
1317}
1318
e95354ec 1319static inline bool DoesntNeedConv(wxFontEncoding enc)
6001e347 1320{
e95354ec
VZ
1321 return enc == wxFONTENCODING_DEFAULT ||
1322 enc == wxFONTENCODING_SYSTEM ||
1323 enc == wxFONTENCODING_ISO8859_1;
1324}
1325
1326wxMBConv *wxCSConv::DoCreate() const
1327{
1328#if wxUSE_FONTMAP
1329 wxFontMapper * const fontMapper = wxFontMapper::Get();
1330
1331 wxFontEncoding encFromName = m_name ? fontMapper->CharsetToEncoding(m_name)
1332 : wxFONTENCODING_SYSTEM;
1333#endif // wxUSE_FONTMAP
1334
1335 // check for the special case of ASCII charset
1336 if ( (!m_name && DoesntNeedConv(m_encoding))
1337#if wxUSE_FONTMAP
1338 || (m_name && DoesntNeedConv(encFromName))
1339#endif // wxUSE_FONTMAP
1340 )
f1339c56 1341 {
e95354ec
VZ
1342 // don't convert at all
1343 return NULL;
1344 }
dccce9ea 1345
e95354ec
VZ
1346 // we trust OS to do conversion better than we can so try external
1347 // conversion methods first
1348 //
1349 // the full order is:
1350 // 1. OS conversion (iconv() under Unix or Win32 API)
1351 // 2. hard coded conversions for UTF
1352 // 3. wxEncodingConverter as fall back
1353
1354 // step (1)
1355#ifdef HAVE_ICONV
1356 if ( m_name )
1357 {
1358 wxMBConv_iconv *conv = new wxMBConv_iconv(m_name);
1359 if ( conv->IsOk() )
1360 return conv;
1361
1362 delete conv;
1363 }
1364#endif // HAVE_ICONV
1365
1366#ifdef wxHAVE_WIN32_MB2WC
1367 {
1368 wxMBConv_win32 *conv = m_name ? new wxMBConv_win32(m_name)
1369 : new wxMBConv_win32(m_encoding);
1370 if ( conv->IsOk() )
1371 return conv;
1372
1373 delete conv;
1374 }
1375#endif // wxHAVE_WIN32_MB2WC
1376
1377 // step (2)
1378 wxFontEncoding enc = m_encoding;
1379#if wxUSE_FONTMAP
1380 if ( enc == wxFONTENCODING_SYSTEM )
1381 enc = encFromName;
1382#endif // wxUSE_FONTMAP
1383
1384 switch ( enc )
1385 {
1386 case wxFONTENCODING_UTF7:
1387 return new wxMBConvUTF7;
1388
1389 case wxFONTENCODING_UTF8:
1390 return new wxMBConvUTF8;
1391
e95354ec
VZ
1392 case wxFONTENCODING_UTF16BE:
1393 return new wxMBConvUTF16BE;
1394
1395 case wxFONTENCODING_UTF16LE:
1396 return new wxMBConvUTF16LE;
1397
e95354ec
VZ
1398 case wxFONTENCODING_UTF32BE:
1399 return new wxMBConvUTF32BE;
1400
1401 case wxFONTENCODING_UTF32LE:
1402 return new wxMBConvUTF32LE;
1403
1404 default:
1405 // nothing to do but put here to suppress gcc warnings
1406 ;
1407 }
1408
1409 // step (3)
1410#if wxUSE_FONTMAP
1411 {
1412 wxMBConv_wxwin *conv = m_name ? new wxMBConv_wxwin(m_name)
1413 : new wxMBConv_wxwin(m_encoding);
1414 if ( conv->IsOk() )
1415 return conv;
1416
1417 delete conv;
1418 }
1419#endif // wxUSE_FONTMAP
1420
1421 wxLogError(_("Cannot convert from the charset '%s'!"),
1422 m_name ? m_name
1423 :
1424#if wxUSE_FONTMAP
1425 wxFontMapper::GetEncodingDescription(m_encoding).c_str()
1426#else // !wxUSE_FONTMAP
1427 wxString::Format(_("encoding %s"), m_encoding).c_str()
1428#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1429 );
1430
1431 return NULL;
1432}
1433
1434void wxCSConv::CreateConvIfNeeded() const
1435{
1436 if ( m_deferred )
1437 {
1438 wxCSConv *self = (wxCSConv *)this; // const_cast
bda3d86a
VZ
1439
1440#if wxUSE_INTL
1441 // if we don't have neither the name nor the encoding, use the default
1442 // encoding for this system
1443 if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM )
1444 {
1445 self->m_encoding = wxLocale::GetSystemEncoding();
1446 }
1447#endif // wxUSE_INTL
1448
e95354ec
VZ
1449 self->m_convReal = DoCreate();
1450 self->m_deferred = false;
6001e347 1451 }
6001e347
RR
1452}
1453
1454size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
1455{
e95354ec 1456 CreateConvIfNeeded();
dccce9ea 1457
e95354ec
VZ
1458 if (m_convReal)
1459 return m_convReal->MB2WC(buf, psz, n);
f1339c56
RR
1460
1461 // latin-1 (direct)
4def3b35 1462 size_t len = strlen(psz);
dccce9ea 1463
f1339c56
RR
1464 if (buf)
1465 {
4def3b35 1466 for (size_t c = 0; c <= len; c++)
f1339c56
RR
1467 buf[c] = (unsigned char)(psz[c]);
1468 }
dccce9ea 1469
f1339c56 1470 return len;
6001e347
RR
1471}
1472
1473size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
1474{
e95354ec 1475 CreateConvIfNeeded();
dccce9ea 1476
e95354ec
VZ
1477 if (m_convReal)
1478 return m_convReal->WC2MB(buf, psz, n);
1cd52418 1479
f1339c56 1480 // latin-1 (direct)
f8d791e0 1481 const size_t len = wxWcslen(psz);
f1339c56
RR
1482 if (buf)
1483 {
4def3b35
VS
1484 for (size_t c = 0; c <= len; c++)
1485 buf[c] = (psz[c] > 0xff) ? '?' : psz[c];
f1339c56 1486 }
dccce9ea 1487
f1339c56 1488 return len;
6001e347
RR
1489}
1490
bde4baac
VZ
1491// ----------------------------------------------------------------------------
1492// globals
1493// ----------------------------------------------------------------------------
1494
1495#ifdef __WINDOWS__
1496 static wxMBConv_win32 wxConvLibcObj;
1497#else
dcc8fac0 1498 static wxMBConvLibc wxConvLibcObj;
bde4baac
VZ
1499#endif
1500
1501static wxCSConv wxConvLocalObj(wxFONTENCODING_SYSTEM);
1502static wxCSConv wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1);
1503static wxMBConvUTF7 wxConvUTF7Obj;
1504static wxMBConvUTF8 wxConvUTF8Obj;
1505
1506
1507WXDLLIMPEXP_DATA_BASE(wxMBConv&) wxConvLibc = wxConvLibcObj;
1508WXDLLIMPEXP_DATA_BASE(wxCSConv&) wxConvLocal = wxConvLocalObj;
1509WXDLLIMPEXP_DATA_BASE(wxCSConv&) wxConvISO8859_1 = wxConvISO8859_1Obj;
1510WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7&) wxConvUTF7 = wxConvUTF7Obj;
1511WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8&) wxConvUTF8 = wxConvUTF8Obj;
1512WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = &wxConvLibcObj;
1513
1514#else // !wxUSE_WCHAR_T
1515
1516// stand-ins in absence of wchar_t
1517WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc,
1518 wxConvISO8859_1,
1519 wxConvLocal,
1520 wxConvUTF8;
1521
1522#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T
6001e347
RR
1523
1524