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