1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Unicode conversion classes
4 // Author: Ove Kaaven, Robert Roebling, Vadim Zeitlin, Vaclav Slavik,
5 // Ryan Norton, Fredrik Roubert (UTF7)
9 // Copyright: (c) 1999 Ove Kaaven, Robert Roebling, Vaclav Slavik
10 // (c) 2000-2003 Vadim Zeitlin
11 // (c) 2004 Ryan Norton, Fredrik Roubert
12 // Licence: wxWindows licence
13 /////////////////////////////////////////////////////////////////////////////
15 // ============================================================================
17 // ============================================================================
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
23 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
24 #pragma implementation "strconv.h"
27 // For compilers that support precompilation, includes "wx.h".
28 #include "wx/wxprec.h"
39 #include "wx/strconv.h"
44 #include "wx/msw/private.h"
48 #include "wx/msw/missing.h"
58 #ifdef HAVE_LANGINFO_H
62 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
63 #define wxHAVE_WIN32_MB2WC
64 #endif // __WIN32__ but !__WXMICROWIN__
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
76 #include "wx/thread.h"
79 #include "wx/encconv.h"
80 #include "wx/fontmap.h"
84 #include <ATSUnicode.h>
85 #include <TextCommon.h>
86 #include <TextEncodingConverter.h>
88 #include "wx/mac/private.h" // includes mac headers
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 #define BSWAP_UCS4(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT32_SWAP_ALWAYS(str[_c]); }
95 #define BSWAP_UTF16(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT16_SWAP_ALWAYS(str[_c]); }
97 #if SIZEOF_WCHAR_T == 4
98 #define WC_NAME "UCS4"
99 #define WC_BSWAP BSWAP_UCS4
100 #ifdef WORDS_BIGENDIAN
101 #define WC_NAME_BEST "UCS-4BE"
103 #define WC_NAME_BEST "UCS-4LE"
105 #elif SIZEOF_WCHAR_T == 2
106 #define WC_NAME "UTF16"
107 #define WC_BSWAP BSWAP_UTF16
109 #ifdef WORDS_BIGENDIAN
110 #define WC_NAME_BEST "UTF-16BE"
112 #define WC_NAME_BEST "UTF-16LE"
114 #else // sizeof(wchar_t) != 2 nor 4
115 // does this ever happen?
116 #error "Unknown sizeof(wchar_t): please report this to wx-dev@lists.wxwindows.org"
119 // ============================================================================
121 // ============================================================================
123 // ----------------------------------------------------------------------------
124 // UTF-16 en/decoding to/from UCS-4
125 // ----------------------------------------------------------------------------
128 static size_t encode_utf16(wxUint32 input
, wxUint16
*output
)
133 *output
= (wxUint16
) input
;
136 else if (input
>=0x110000)
144 *output
++ = (wxUint16
) ((input
>> 10)+0xd7c0);
145 *output
= (wxUint16
) ((input
&0x3ff)+0xdc00);
151 static size_t decode_utf16(const wxUint16
* input
, wxUint32
& output
)
153 if ((*input
<0xd800) || (*input
>0xdfff))
158 else if ((input
[1]<0xdc00) || (input
[1]>=0xdfff))
165 output
= ((input
[0] - 0xd7c0) << 10) + (input
[1] - 0xdc00);
171 // ----------------------------------------------------------------------------
173 // ----------------------------------------------------------------------------
175 wxMBConv::~wxMBConv()
177 // nothing to do here (necessary for Darwin linking probably)
180 const wxWCharBuffer
wxMBConv::cMB2WC(const char *psz
) const
184 // calculate the length of the buffer needed first
185 size_t nLen
= MB2WC(NULL
, psz
, 0);
186 if ( nLen
!= (size_t)-1 )
188 // now do the actual conversion
189 wxWCharBuffer
buf(nLen
);
190 nLen
= MB2WC(buf
.data(), psz
, nLen
+ 1); // with the trailing NULL
191 if ( nLen
!= (size_t)-1 )
198 wxWCharBuffer
buf((wchar_t *)NULL
);
203 const wxCharBuffer
wxMBConv::cWC2MB(const wchar_t *pwz
) const
207 size_t nLen
= WC2MB(NULL
, pwz
, 0);
208 if ( nLen
!= (size_t)-1 )
210 wxCharBuffer
buf(nLen
+3); // space for a wxUint32 trailing zero
211 nLen
= WC2MB(buf
.data(), pwz
, nLen
+ 4);
212 if ( nLen
!= (size_t)-1 )
219 wxCharBuffer
buf((char *)NULL
);
224 const wxWCharBuffer
wxMBConv::cMB2WC(const char *szString
, size_t nStringLen
, size_t* pOutSize
) const
226 wxASSERT(pOutSize
!= NULL
);
228 const char* szEnd
= szString
+ nStringLen
+ 1;
229 const char* szPos
= szString
;
230 const char* szStart
= szPos
;
232 size_t nActualLength
= 0;
233 size_t nCurrentSize
= nStringLen
; //try normal size first (should never resize?)
235 wxWCharBuffer
theBuffer(nCurrentSize
);
237 //Convert the string until the length() is reached, continuing the
238 //loop every time a null character is reached
239 while(szPos
!= szEnd
)
241 wxASSERT(szPos
< szEnd
); //something is _really_ screwed up if this rings true
243 //Get the length of the current (sub)string
244 size_t nLen
= MB2WC(NULL
, szPos
, 0);
246 //Invalid conversion?
247 if( nLen
== (size_t)-1 )
250 theBuffer
.data()[0u] = wxT('\0');
255 //Increase the actual length (+1 for current null character)
256 nActualLength
+= nLen
+ 1;
258 //if buffer too big, realloc the buffer
259 if (nActualLength
> (nCurrentSize
+1))
261 wxWCharBuffer
theNewBuffer(nCurrentSize
<< 1);
262 memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize
* sizeof(wchar_t));
263 theBuffer
= theNewBuffer
;
267 //Convert the current (sub)string
268 if ( MB2WC(&theBuffer
.data()[szPos
- szStart
], szPos
, nLen
+ 1) == (size_t)-1 )
271 theBuffer
.data()[0u] = wxT('\0');
275 //Increment to next (sub)string
276 //Note that we have to use strlen here instead of nLen
277 //here because XX2XX gives us the size of the output buffer,
278 //not neccessarly the length of the string
279 szPos
+= strlen(szPos
) + 1;
282 //success - return actual length and the buffer
283 *pOutSize
= nActualLength
;
287 const wxCharBuffer
wxMBConv::cWC2MB(const wchar_t *szString
, size_t nStringLen
, size_t* pOutSize
) const
289 wxASSERT(pOutSize
!= NULL
);
291 const wchar_t* szEnd
= szString
+ nStringLen
+ 1;
292 const wchar_t* szPos
= szString
;
293 const wchar_t* szStart
= szPos
;
295 size_t nActualLength
= 0;
296 size_t nCurrentSize
= nStringLen
<< 2; //try * 4 first
298 wxCharBuffer
theBuffer(nCurrentSize
);
300 //Convert the string until the length() is reached, continuing the
301 //loop every time a null character is reached
302 while(szPos
!= szEnd
)
304 wxASSERT(szPos
< szEnd
); //something is _really_ screwed up if this rings true
306 //Get the length of the current (sub)string
307 size_t nLen
= WC2MB(NULL
, szPos
, 0);
309 //Invalid conversion?
310 if( nLen
== (size_t)-1 )
313 theBuffer
.data()[0u] = wxT('\0');
317 //Increase the actual length (+1 for current null character)
318 nActualLength
+= nLen
+ 1;
320 //if buffer too big, realloc the buffer
321 if (nActualLength
> (nCurrentSize
+1))
323 wxCharBuffer
theNewBuffer(nCurrentSize
<< 1);
324 memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize
);
325 theBuffer
= theNewBuffer
;
329 //Convert the current (sub)string
330 if(WC2MB(&theBuffer
.data()[szPos
- szStart
], szPos
, nLen
+ 1) == (size_t)-1 )
333 theBuffer
.data()[0u] = wxT('\0');
337 //Increment to next (sub)string
338 //Note that we have to use wxWcslen here instead of nLen
339 //here because XX2XX gives us the size of the output buffer,
340 //not neccessarly the length of the string
341 szPos
+= wxWcslen(szPos
) + 1;
344 //success - return actual length and the buffer
345 *pOutSize
= nActualLength
;
349 // ----------------------------------------------------------------------------
351 // ----------------------------------------------------------------------------
353 size_t wxMBConvLibc::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
355 return wxMB2WC(buf
, psz
, n
);
358 size_t wxMBConvLibc::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
360 return wxWC2MB(buf
, psz
, n
);
365 // ----------------------------------------------------------------------------
366 // wxConvBrokenFileNames
367 // ----------------------------------------------------------------------------
369 wxConvBrokenFileNames::wxConvBrokenFileNames()
371 // decide which conversion to use for the file names
373 // (1) this variable exists for the sole purpose of specifying the encoding
374 // of the filenames for GTK+ programs, so use it if it is set
375 const wxChar
*encName
= wxGetenv(_T("G_FILENAME_ENCODING"));
378 m_conv
= new wxCSConv(encName
);
380 else // no G_FILENAME_ENCODING
382 // (2) if a non default locale is set, assume that the user wants his
383 // filenames in this locale too
384 switch ( wxLocale::GetSystemEncoding() )
387 m_conv
= new wxMBConvLibc
;
390 // (3) finally use UTF-8 by default
391 case wxFONTENCODING_SYSTEM
:
392 case wxFONTENCODING_UTF8
:
393 m_conv
= new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL
);
400 wxConvBrokenFileNames::MB2WC(wchar_t *outputBuf
,
402 size_t outputSize
) const
404 return m_conv
->MB2WC( outputBuf
, psz
, outputSize
);
408 wxConvBrokenFileNames::WC2MB(char *outputBuf
,
410 size_t outputSize
) const
412 return m_conv
->WC2MB( outputBuf
, psz
, outputSize
);
417 // ----------------------------------------------------------------------------
419 // ----------------------------------------------------------------------------
421 // Implementation (C) 2004 Fredrik Roubert
424 // BASE64 decoding table
426 static const unsigned char utf7unb64
[] =
428 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
429 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
430 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
431 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
432 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
433 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
434 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
435 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
436 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
437 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
438 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
439 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
440 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
441 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
442 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
443 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
444 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
446 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
447 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
448 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
449 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
452 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
454 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
457 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
458 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
459 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
462 size_t wxMBConvUTF7::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
466 while (*psz
&& ((!buf
) || (len
< n
)))
468 unsigned char cc
= *psz
++;
476 else if (*psz
== '-')
486 // BASE64 encoded string
490 for (lsb
= false, d
= 0, l
= 0;
491 (cc
= utf7unb64
[(unsigned char)*psz
]) != 0xff; psz
++)
495 for (l
+= 6; l
>= 8; lsb
= !lsb
)
497 c
= (unsigned char)((d
>> (l
-= 8)) % 256);
506 *buf
= (wchar_t)(c
<< 8);
513 if (buf
&& (len
< n
))
519 // BASE64 encoding table
521 static const unsigned char utf7enb64
[] =
523 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
524 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
525 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
526 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
527 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
528 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
529 'w', 'x', 'y', 'z', '0', '1', '2', '3',
530 '4', '5', '6', '7', '8', '9', '+', '/'
534 // UTF-7 encoding table
536 // 0 - Set D (directly encoded characters)
537 // 1 - Set O (optional direct characters)
538 // 2 - whitespace characters (optional)
539 // 3 - special characters
541 static const unsigned char utf7encode
[128] =
543 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,
544 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
545 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 3,
546 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
547 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
548 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1,
549 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
550 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3
553 size_t wxMBConvUTF7::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
559 while (*psz
&& ((!buf
) || (len
< n
)))
562 if (cc
< 0x80 && utf7encode
[cc
] < 1)
570 else if (((wxUint32
)cc
) > 0xffff)
572 // no surrogate pair generation (yet?)
583 // BASE64 encode string
584 unsigned int lsb
, d
, l
;
585 for (d
= 0, l
= 0;; psz
++)
587 for (lsb
= 0; lsb
< 2; lsb
++)
590 d
+= lsb
? cc
& 0xff : (cc
& 0xff00) >> 8;
592 for (l
+= 8; l
>= 6; )
596 *buf
++ = utf7enb64
[(d
>> l
) % 64];
601 if (!(cc
) || (cc
< 0x80 && utf7encode
[cc
] < 1))
607 *buf
++ = utf7enb64
[((d
% 16) << (6 - l
)) % 64];
616 if (buf
&& (len
< n
))
621 // ----------------------------------------------------------------------------
623 // ----------------------------------------------------------------------------
625 static wxUint32 utf8_max
[]=
626 { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff };
628 // boundaries of the private use area we use to (temporarily) remap invalid
629 // characters invalid in a UTF-8 encoded string
630 const wxUint32 wxUnicodePUA
= 0x100000;
631 const wxUint32 wxUnicodePUAEnd
= wxUnicodePUA
+ 256;
633 size_t wxMBConvUTF8::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
637 while (*psz
&& ((!buf
) || (len
< n
)))
639 const char *opsz
= psz
;
640 bool invalid
= false;
641 unsigned char cc
= *psz
++, fc
= cc
;
643 for (cnt
= 0; fc
& 0x80; cnt
++)
657 // invalid UTF-8 sequence
662 unsigned ocnt
= cnt
- 1;
663 wxUint32 res
= cc
& (0x3f >> cnt
);
667 if ((cc
& 0xC0) != 0x80)
669 // invalid UTF-8 sequence
674 res
= (res
<< 6) | (cc
& 0x3f);
676 if (invalid
|| res
<= utf8_max
[ocnt
])
678 // illegal UTF-8 encoding
681 else if ((m_options
& MAP_INVALID_UTF8_TO_PUA
) &&
682 res
>= wxUnicodePUA
&& res
< wxUnicodePUAEnd
)
684 // if one of our PUA characters turns up externally
685 // it must also be treated as an illegal sequence
686 // (a bit like you have to escape an escape character)
692 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
693 size_t pa
= encode_utf16(res
, (wxUint16
*)buf
);
694 if (pa
== (size_t)-1)
708 #endif // WC_UTF16/!WC_UTF16
713 if (m_options
& MAP_INVALID_UTF8_TO_PUA
)
715 while (opsz
< psz
&& (!buf
|| len
< n
))
718 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
719 size_t pa
= encode_utf16((unsigned char)*opsz
+ wxUnicodePUA
, (wxUint16
*)buf
);
720 wxASSERT(pa
!= (size_t)-1);
727 *buf
++ = wxUnicodePUA
+ (unsigned char)*opsz
;
733 else if (m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
735 while (opsz
< psz
&& (!buf
|| len
< n
))
737 if ( buf
&& len
+ 3 < n
)
739 unsigned char n
= *opsz
;
741 *buf
++ = (wchar_t)( L
'0' + n
/ 0100 );
742 *buf
++ = (wchar_t)( L
'0' + (n
% 0100) / 010 );
743 *buf
++ = (wchar_t)( L
'0' + n
% 010 );
749 else // MAP_INVALID_UTF8_NOT
756 if (buf
&& (len
< n
))
761 static inline bool isoctal(wchar_t wch
)
763 return L
'0' <= wch
&& wch
<= L
'7';
766 size_t wxMBConvUTF8::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
770 while (*psz
&& ((!buf
) || (len
< n
)))
774 // cast is ok for WC_UTF16
775 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
776 psz
+= (pa
== (size_t)-1) ? 1 : pa
;
778 cc
=(*psz
++) & 0x7fffffff;
781 if ( (m_options
& MAP_INVALID_UTF8_TO_PUA
)
782 && cc
>= wxUnicodePUA
&& cc
< wxUnicodePUAEnd
)
785 *buf
++ = (char)(cc
- wxUnicodePUA
);
788 else if ( (m_options
& MAP_INVALID_UTF8_TO_OCTAL
) &&
790 isoctal(psz
[0]) && isoctal(psz
[1]) && isoctal(psz
[2]) )
794 *buf
++ = (char) ((psz
[0] - L
'0')*0100 +
795 (psz
[1] - L
'0')*010 +
805 for (cnt
= 0; cc
> utf8_max
[cnt
]; cnt
++) {}
819 *buf
++ = (char) ((-128 >> cnt
) | ((cc
>> (cnt
* 6)) & (0x3f >> cnt
)));
821 *buf
++ = (char) (0x80 | ((cc
>> (cnt
* 6)) & 0x3f));
833 // ----------------------------------------------------------------------------
835 // ----------------------------------------------------------------------------
837 #ifdef WORDS_BIGENDIAN
838 #define wxMBConvUTF16straight wxMBConvUTF16BE
839 #define wxMBConvUTF16swap wxMBConvUTF16LE
841 #define wxMBConvUTF16swap wxMBConvUTF16BE
842 #define wxMBConvUTF16straight wxMBConvUTF16LE
848 // copy 16bit MB to 16bit String
849 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
853 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
856 *buf
++ = *(wxUint16
*)psz
;
859 psz
+= sizeof(wxUint16
);
861 if (buf
&& len
<n
) *buf
=0;
867 // copy 16bit String to 16bit MB
868 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
872 while (*psz
&& (!buf
|| len
< n
))
876 *(wxUint16
*)buf
= *psz
;
877 buf
+= sizeof(wxUint16
);
879 len
+= sizeof(wxUint16
);
882 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
888 // swap 16bit MB to 16bit String
889 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
893 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
897 ((char *)buf
)[0] = psz
[1];
898 ((char *)buf
)[1] = psz
[0];
902 psz
+= sizeof(wxUint16
);
904 if (buf
&& len
<n
) *buf
=0;
910 // swap 16bit MB to 16bit String
911 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
915 while (*psz
&& (!buf
|| len
< n
))
919 *buf
++ = ((char*)psz
)[1];
920 *buf
++ = ((char*)psz
)[0];
922 len
+= sizeof(wxUint16
);
925 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
934 // copy 16bit MB to 32bit String
935 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
939 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
942 size_t pa
=decode_utf16((wxUint16
*)psz
, cc
);
943 if (pa
== (size_t)-1)
949 psz
+= pa
* sizeof(wxUint16
);
951 if (buf
&& len
<n
) *buf
=0;
957 // copy 32bit String to 16bit MB
958 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
962 while (*psz
&& (!buf
|| len
< n
))
965 size_t pa
=encode_utf16(*psz
, cc
);
967 if (pa
== (size_t)-1)
972 *(wxUint16
*)buf
= cc
[0];
973 buf
+= sizeof(wxUint16
);
976 *(wxUint16
*)buf
= cc
[1];
977 buf
+= sizeof(wxUint16
);
981 len
+= pa
*sizeof(wxUint16
);
984 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
990 // swap 16bit MB to 32bit String
991 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
995 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
999 tmp
[0]=psz
[1]; tmp
[1]=psz
[0];
1000 tmp
[2]=psz
[3]; tmp
[3]=psz
[2];
1002 size_t pa
=decode_utf16((wxUint16
*)tmp
, cc
);
1003 if (pa
== (size_t)-1)
1010 psz
+= pa
* sizeof(wxUint16
);
1012 if (buf
&& len
<n
) *buf
=0;
1018 // swap 32bit String to 16bit MB
1019 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1023 while (*psz
&& (!buf
|| len
< n
))
1026 size_t pa
=encode_utf16(*psz
, cc
);
1028 if (pa
== (size_t)-1)
1033 *buf
++ = ((char*)cc
)[1];
1034 *buf
++ = ((char*)cc
)[0];
1037 *buf
++ = ((char*)cc
)[3];
1038 *buf
++ = ((char*)cc
)[2];
1042 len
+= pa
*sizeof(wxUint16
);
1045 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
1053 // ----------------------------------------------------------------------------
1055 // ----------------------------------------------------------------------------
1057 #ifdef WORDS_BIGENDIAN
1058 #define wxMBConvUTF32straight wxMBConvUTF32BE
1059 #define wxMBConvUTF32swap wxMBConvUTF32LE
1061 #define wxMBConvUTF32swap wxMBConvUTF32BE
1062 #define wxMBConvUTF32straight wxMBConvUTF32LE
1066 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32LE
) wxConvUTF32LE
;
1067 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32BE
) wxConvUTF32BE
;
1072 // copy 32bit MB to 16bit String
1073 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1077 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1081 size_t pa
=encode_utf16(*(wxUint32
*)psz
, cc
);
1082 if (pa
== (size_t)-1)
1092 psz
+= sizeof(wxUint32
);
1094 if (buf
&& len
<n
) *buf
=0;
1100 // copy 16bit String to 32bit MB
1101 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1105 while (*psz
&& (!buf
|| len
< n
))
1109 // cast is ok for WC_UTF16
1110 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
1111 if (pa
== (size_t)-1)
1116 *(wxUint32
*)buf
= cc
;
1117 buf
+= sizeof(wxUint32
);
1119 len
+= sizeof(wxUint32
);
1123 if (buf
&& len
<=n
-sizeof(wxUint32
))
1131 // swap 32bit MB to 16bit String
1132 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1136 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1139 tmp
[0] = psz
[3]; tmp
[1] = psz
[2];
1140 tmp
[2] = psz
[1]; tmp
[3] = psz
[0];
1145 size_t pa
=encode_utf16(*(wxUint32
*)tmp
, cc
);
1146 if (pa
== (size_t)-1)
1156 psz
+= sizeof(wxUint32
);
1166 // swap 16bit String to 32bit MB
1167 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1171 while (*psz
&& (!buf
|| len
< n
))
1175 // cast is ok for WC_UTF16
1176 size_t pa
=decode_utf16((const wxUint16
*)psz
, *(wxUint32
*)cc
);
1177 if (pa
== (size_t)-1)
1187 len
+= sizeof(wxUint32
);
1191 if (buf
&& len
<=n
-sizeof(wxUint32
))
1200 // copy 32bit MB to 32bit String
1201 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1205 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1208 *buf
++ = *(wxUint32
*)psz
;
1210 psz
+= sizeof(wxUint32
);
1220 // copy 32bit String to 32bit MB
1221 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1225 while (*psz
&& (!buf
|| len
< n
))
1229 *(wxUint32
*)buf
= *psz
;
1230 buf
+= sizeof(wxUint32
);
1233 len
+= sizeof(wxUint32
);
1237 if (buf
&& len
<=n
-sizeof(wxUint32
))
1244 // swap 32bit MB to 32bit String
1245 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1249 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1253 ((char *)buf
)[0] = psz
[3];
1254 ((char *)buf
)[1] = psz
[2];
1255 ((char *)buf
)[2] = psz
[1];
1256 ((char *)buf
)[3] = psz
[0];
1260 psz
+= sizeof(wxUint32
);
1270 // swap 32bit String to 32bit MB
1271 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1275 while (*psz
&& (!buf
|| len
< n
))
1279 *buf
++ = ((char *)psz
)[3];
1280 *buf
++ = ((char *)psz
)[2];
1281 *buf
++ = ((char *)psz
)[1];
1282 *buf
++ = ((char *)psz
)[0];
1284 len
+= sizeof(wxUint32
);
1288 if (buf
&& len
<=n
-sizeof(wxUint32
))
1298 // ============================================================================
1299 // The classes doing conversion using the iconv_xxx() functions
1300 // ============================================================================
1304 // VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with
1305 // E2BIG if output buffer is _exactly_ as big as needed. Such case is
1306 // (unless there's yet another bug in glibc) the only case when iconv()
1307 // returns with (size_t)-1 (which means error) and says there are 0 bytes
1308 // left in the input buffer -- when _real_ error occurs,
1309 // bytes-left-in-input buffer is non-zero. Hence, this alternative test for
1311 // [This bug does not appear in glibc 2.2.]
1312 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1
1313 #define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \
1314 (errno != E2BIG || bufLeft != 0))
1316 #define ICONV_FAILED(cres, bufLeft) (cres == (size_t)-1)
1319 #define ICONV_CHAR_CAST(x) ((ICONV_CONST char **)(x))
1321 // ----------------------------------------------------------------------------
1322 // wxMBConv_iconv: encapsulates an iconv character set
1323 // ----------------------------------------------------------------------------
1325 class wxMBConv_iconv
: public wxMBConv
1328 wxMBConv_iconv(const wxChar
*name
);
1329 virtual ~wxMBConv_iconv();
1331 virtual size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const;
1332 virtual size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const;
1335 { return (m2w
!= (iconv_t
)-1) && (w2m
!= (iconv_t
)-1); }
1338 // the iconv handlers used to translate from multibyte to wide char and in
1339 // the other direction
1343 // guards access to m2w and w2m objects
1344 wxMutex m_iconvMutex
;
1348 // the name (for iconv_open()) of a wide char charset -- if none is
1349 // available on this machine, it will remain NULL
1350 static const char *ms_wcCharsetName
;
1352 // true if the wide char encoding we use (i.e. ms_wcCharsetName) has
1353 // different endian-ness than the native one
1354 static bool ms_wcNeedsSwap
;
1357 const char *wxMBConv_iconv::ms_wcCharsetName
= NULL
;
1358 bool wxMBConv_iconv::ms_wcNeedsSwap
= false;
1360 wxMBConv_iconv::wxMBConv_iconv(const wxChar
*name
)
1362 // Do it the hard way
1364 for (size_t i
= 0; i
< wxStrlen(name
)+1; i
++)
1365 cname
[i
] = (char) name
[i
];
1367 // check for charset that represents wchar_t:
1368 if (ms_wcCharsetName
== NULL
)
1370 ms_wcNeedsSwap
= false;
1372 // try charset with explicit bytesex info (e.g. "UCS-4LE"):
1373 ms_wcCharsetName
= WC_NAME_BEST
;
1374 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1376 if (m2w
== (iconv_t
)-1)
1378 // try charset w/o bytesex info (e.g. "UCS4")
1379 // and check for bytesex ourselves:
1380 ms_wcCharsetName
= WC_NAME
;
1381 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1383 // last bet, try if it knows WCHAR_T pseudo-charset
1384 if (m2w
== (iconv_t
)-1)
1386 ms_wcCharsetName
= "WCHAR_T";
1387 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1390 if (m2w
!= (iconv_t
)-1)
1392 char buf
[2], *bufPtr
;
1393 wchar_t wbuf
[2], *wbufPtr
;
1401 outsz
= SIZEOF_WCHAR_T
* 2;
1405 res
= iconv(m2w
, ICONV_CHAR_CAST(&bufPtr
), &insz
,
1406 (char**)&wbufPtr
, &outsz
);
1408 if (ICONV_FAILED(res
, insz
))
1410 ms_wcCharsetName
= NULL
;
1411 wxLogLastError(wxT("iconv"));
1412 wxLogError(_("Conversion to charset '%s' doesn't work."), name
);
1416 ms_wcNeedsSwap
= wbuf
[0] != (wchar_t)buf
[0];
1421 ms_wcCharsetName
= NULL
;
1423 // VS: we must not output an error here, since wxWidgets will safely
1424 // fall back to using wxEncodingConverter.
1425 wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name
);
1429 wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName
, ms_wcNeedsSwap
);
1431 else // we already have ms_wcCharsetName
1433 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1436 // NB: don't ever pass NULL to iconv_open(), it may crash!
1437 if ( ms_wcCharsetName
)
1439 w2m
= iconv_open( cname
, ms_wcCharsetName
);
1447 wxMBConv_iconv::~wxMBConv_iconv()
1449 if ( m2w
!= (iconv_t
)-1 )
1451 if ( w2m
!= (iconv_t
)-1 )
1455 size_t wxMBConv_iconv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1458 // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle.
1459 // Unfortunately there is a couple of global wxCSConv objects such as
1460 // wxConvLocal that are used all over wx code, so we have to make sure
1461 // the handle is used by at most one thread at the time. Otherwise
1462 // only a few wx classes would be safe to use from non-main threads
1463 // as MB<->WC conversion would fail "randomly".
1464 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1467 size_t inbuf
= strlen(psz
);
1468 size_t outbuf
= n
* SIZEOF_WCHAR_T
;
1470 // VS: Use these instead of psz, buf because iconv() modifies its arguments:
1471 wchar_t *bufPtr
= buf
;
1472 const char *pszPtr
= psz
;
1476 // have destination buffer, convert there
1478 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1479 (char**)&bufPtr
, &outbuf
);
1480 res
= n
- (outbuf
/ SIZEOF_WCHAR_T
);
1484 // convert to native endianness
1485 WC_BSWAP(buf
/* _not_ bufPtr */, res
)
1488 // NB: iconv was given only strlen(psz) characters on input, and so
1489 // it couldn't convert the trailing zero. Let's do it ourselves
1490 // if there's some room left for it in the output buffer.
1496 // no destination buffer... convert using temp buffer
1497 // to calculate destination buffer requirement
1502 outbuf
= 8*SIZEOF_WCHAR_T
;
1505 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1506 (char**)&bufPtr
, &outbuf
);
1508 res
+= 8-(outbuf
/SIZEOF_WCHAR_T
);
1509 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1512 if (ICONV_FAILED(cres
, inbuf
))
1514 //VS: it is ok if iconv fails, hence trace only
1515 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1522 size_t wxMBConv_iconv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1525 // NB: explained in MB2WC
1526 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1529 size_t inbuf
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
1533 wchar_t *tmpbuf
= 0;
1537 // need to copy to temp buffer to switch endianness
1538 // this absolutely doesn't rock!
1539 // (no, doing WC_BSWAP twice on the original buffer won't help, as it
1540 // could be in read-only memory, or be accessed in some other thread)
1541 tmpbuf
=(wchar_t*)malloc((inbuf
+1)*SIZEOF_WCHAR_T
);
1542 memcpy(tmpbuf
,psz
,(inbuf
+1)*SIZEOF_WCHAR_T
);
1543 WC_BSWAP(tmpbuf
, inbuf
)
1549 // have destination buffer, convert there
1550 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1554 // NB: iconv was given only wcslen(psz) characters on input, and so
1555 // it couldn't convert the trailing zero. Let's do it ourselves
1556 // if there's some room left for it in the output buffer.
1562 // no destination buffer... convert using temp buffer
1563 // to calculate destination buffer requirement
1567 buf
= tbuf
; outbuf
= 16;
1569 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1572 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1580 if (ICONV_FAILED(cres
, inbuf
))
1582 //VS: it is ok if iconv fails, hence trace only
1583 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1590 #endif // HAVE_ICONV
1593 // ============================================================================
1594 // Win32 conversion classes
1595 // ============================================================================
1597 #ifdef wxHAVE_WIN32_MB2WC
1601 extern WXDLLIMPEXP_BASE
long wxCharsetToCodepage(const wxChar
*charset
);
1602 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
);
1605 class wxMBConv_win32
: public wxMBConv
1610 m_CodePage
= CP_ACP
;
1614 wxMBConv_win32(const wxChar
* name
)
1616 m_CodePage
= wxCharsetToCodepage(name
);
1619 wxMBConv_win32(wxFontEncoding encoding
)
1621 m_CodePage
= wxEncodingToCodepage(encoding
);
1625 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1627 // note that we have to use MB_ERR_INVALID_CHARS flag as it without it
1628 // the behaviour is not compatible with the Unix version (using iconv)
1629 // and break the library itself, e.g. wxTextInputStream::NextChar()
1630 // wouldn't work if reading an incomplete MB char didn't result in an
1633 // note however that using MB_ERR_INVALID_CHARS with CP_UTF7 results in
1634 // an error (tested under Windows Server 2003) and apparently it is
1635 // done on purpose, i.e. the function accepts any input in this case
1636 // and although I'd prefer to return error on ill-formed output, our
1637 // own wxMBConvUTF7 doesn't detect errors (e.g. lone "+" which is
1638 // explicitly ill-formed according to RFC 2152) neither so we don't
1639 // even have any fallback here...
1640 int flags
= m_CodePage
== CP_UTF7
? 0 : MB_ERR_INVALID_CHARS
;
1642 const size_t len
= ::MultiByteToWideChar
1644 m_CodePage
, // code page
1645 flags
, // flags: fall on error
1646 psz
, // input string
1647 -1, // its length (NUL-terminated)
1648 buf
, // output string
1649 buf
? n
: 0 // size of output buffer
1652 // note that it returns count of written chars for buf != NULL and size
1653 // of the needed buffer for buf == NULL so in either case the length of
1654 // the string (which never includes the terminating NUL) is one less
1655 return len
? len
- 1 : (size_t)-1;
1658 size_t WC2MB(char *buf
, const wchar_t *pwz
, size_t n
) const
1661 we have a problem here: by default, WideCharToMultiByte() may
1662 replace characters unrepresentable in the target code page with bad
1663 quality approximations such as turning "1/2" symbol (U+00BD) into
1664 "1" for the code pages which don't have it and we, obviously, want
1665 to avoid this at any price
1667 the trouble is that this function does it _silently_, i.e. it won't
1668 even tell us whether it did or not... Win98/2000 and higher provide
1669 WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and
1670 we have to resort to a round trip, i.e. check that converting back
1671 results in the same string -- this is, of course, expensive but
1672 otherwise we simply can't be sure to not garble the data.
1675 // determine if we can rely on WC_NO_BEST_FIT_CHARS: according to MSDN
1676 // it doesn't work with CJK encodings (which we test for rather roughly
1677 // here...) nor with UTF-7/8 nor, of course, with Windows versions not
1679 BOOL usedDef
wxDUMMY_INITIALIZE(false);
1682 if ( CanUseNoBestFit() && m_CodePage
< 50000 )
1684 // it's our lucky day
1685 flags
= WC_NO_BEST_FIT_CHARS
;
1686 pUsedDef
= &usedDef
;
1688 else // old system or unsupported encoding
1694 const size_t len
= ::WideCharToMultiByte
1696 m_CodePage
, // code page
1697 flags
, // either none or no best fit
1698 pwz
, // input string
1699 -1, // it is (wide) NUL-terminated
1700 buf
, // output buffer
1701 buf
? n
: 0, // and its size
1702 NULL
, // default "replacement" char
1703 pUsedDef
// [out] was it used?
1708 // function totally failed
1712 // if we were really converting, check if we succeeded
1717 // check if the conversion failed, i.e. if any replacements
1722 else // we must resort to double tripping...
1724 wxWCharBuffer
wcBuf(n
);
1725 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
1726 wcscmp(wcBuf
, pwz
) != 0 )
1728 // we didn't obtain the same thing we started from, hence
1729 // the conversion was lossy and we consider that it failed
1735 // see the comment above for the reason of "len - 1"
1739 bool IsOk() const { return m_CodePage
!= -1; }
1742 static bool CanUseNoBestFit()
1744 static int s_isWin98Or2k
= -1;
1746 if ( s_isWin98Or2k
== -1 )
1749 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1752 s_isWin98Or2k
= verMaj
>= 4 && verMin
>= 10;
1756 s_isWin98Or2k
= verMaj
>= 5;
1760 // unknown, be conseravtive by default
1764 wxASSERT_MSG( s_isWin98Or2k
!= -1, _T("should be set above") );
1767 return s_isWin98Or2k
== 1;
1773 #endif // wxHAVE_WIN32_MB2WC
1775 // ============================================================================
1776 // Cocoa conversion classes
1777 // ============================================================================
1779 #if defined(__WXCOCOA__)
1781 // RN: There is no UTF-32 support in either Core Foundation or
1782 // Cocoa. Strangely enough, internally Core Foundation uses
1783 // UTF 32 internally quite a bit - its just not public (yet).
1785 #include <CoreFoundation/CFString.h>
1786 #include <CoreFoundation/CFStringEncodingExt.h>
1788 CFStringEncoding
wxCFStringEncFromFontEnc(wxFontEncoding encoding
)
1790 CFStringEncoding enc
= kCFStringEncodingInvalidId
;
1791 if ( encoding
== wxFONTENCODING_DEFAULT
)
1793 enc
= CFStringGetSystemEncoding();
1795 else switch( encoding
)
1797 case wxFONTENCODING_ISO8859_1
:
1798 enc
= kCFStringEncodingISOLatin1
;
1800 case wxFONTENCODING_ISO8859_2
:
1801 enc
= kCFStringEncodingISOLatin2
;
1803 case wxFONTENCODING_ISO8859_3
:
1804 enc
= kCFStringEncodingISOLatin3
;
1806 case wxFONTENCODING_ISO8859_4
:
1807 enc
= kCFStringEncodingISOLatin4
;
1809 case wxFONTENCODING_ISO8859_5
:
1810 enc
= kCFStringEncodingISOLatinCyrillic
;
1812 case wxFONTENCODING_ISO8859_6
:
1813 enc
= kCFStringEncodingISOLatinArabic
;
1815 case wxFONTENCODING_ISO8859_7
:
1816 enc
= kCFStringEncodingISOLatinGreek
;
1818 case wxFONTENCODING_ISO8859_8
:
1819 enc
= kCFStringEncodingISOLatinHebrew
;
1821 case wxFONTENCODING_ISO8859_9
:
1822 enc
= kCFStringEncodingISOLatin5
;
1824 case wxFONTENCODING_ISO8859_10
:
1825 enc
= kCFStringEncodingISOLatin6
;
1827 case wxFONTENCODING_ISO8859_11
:
1828 enc
= kCFStringEncodingISOLatinThai
;
1830 case wxFONTENCODING_ISO8859_13
:
1831 enc
= kCFStringEncodingISOLatin7
;
1833 case wxFONTENCODING_ISO8859_14
:
1834 enc
= kCFStringEncodingISOLatin8
;
1836 case wxFONTENCODING_ISO8859_15
:
1837 enc
= kCFStringEncodingISOLatin9
;
1840 case wxFONTENCODING_KOI8
:
1841 enc
= kCFStringEncodingKOI8_R
;
1843 case wxFONTENCODING_ALTERNATIVE
: // MS-DOS CP866
1844 enc
= kCFStringEncodingDOSRussian
;
1847 // case wxFONTENCODING_BULGARIAN :
1851 case wxFONTENCODING_CP437
:
1852 enc
=kCFStringEncodingDOSLatinUS
;
1854 case wxFONTENCODING_CP850
:
1855 enc
= kCFStringEncodingDOSLatin1
;
1857 case wxFONTENCODING_CP852
:
1858 enc
= kCFStringEncodingDOSLatin2
;
1860 case wxFONTENCODING_CP855
:
1861 enc
= kCFStringEncodingDOSCyrillic
;
1863 case wxFONTENCODING_CP866
:
1864 enc
=kCFStringEncodingDOSRussian
;
1866 case wxFONTENCODING_CP874
:
1867 enc
= kCFStringEncodingDOSThai
;
1869 case wxFONTENCODING_CP932
:
1870 enc
= kCFStringEncodingDOSJapanese
;
1872 case wxFONTENCODING_CP936
:
1873 enc
=kCFStringEncodingDOSChineseSimplif
;
1875 case wxFONTENCODING_CP949
:
1876 enc
= kCFStringEncodingDOSKorean
;
1878 case wxFONTENCODING_CP950
:
1879 enc
= kCFStringEncodingDOSChineseTrad
;
1881 case wxFONTENCODING_CP1250
:
1882 enc
= kCFStringEncodingWindowsLatin2
;
1884 case wxFONTENCODING_CP1251
:
1885 enc
=kCFStringEncodingWindowsCyrillic
;
1887 case wxFONTENCODING_CP1252
:
1888 enc
=kCFStringEncodingWindowsLatin1
;
1890 case wxFONTENCODING_CP1253
:
1891 enc
= kCFStringEncodingWindowsGreek
;
1893 case wxFONTENCODING_CP1254
:
1894 enc
= kCFStringEncodingWindowsLatin5
;
1896 case wxFONTENCODING_CP1255
:
1897 enc
=kCFStringEncodingWindowsHebrew
;
1899 case wxFONTENCODING_CP1256
:
1900 enc
=kCFStringEncodingWindowsArabic
;
1902 case wxFONTENCODING_CP1257
:
1903 enc
= kCFStringEncodingWindowsBalticRim
;
1905 // This only really encodes to UTF7 (if that) evidently
1906 // case wxFONTENCODING_UTF7 :
1907 // enc = kCFStringEncodingNonLossyASCII ;
1909 case wxFONTENCODING_UTF8
:
1910 enc
= kCFStringEncodingUTF8
;
1912 case wxFONTENCODING_EUC_JP
:
1913 enc
= kCFStringEncodingEUC_JP
;
1915 case wxFONTENCODING_UTF16
:
1916 enc
= kCFStringEncodingUnicode
;
1918 case wxFONTENCODING_MACROMAN
:
1919 enc
= kCFStringEncodingMacRoman
;
1921 case wxFONTENCODING_MACJAPANESE
:
1922 enc
= kCFStringEncodingMacJapanese
;
1924 case wxFONTENCODING_MACCHINESETRAD
:
1925 enc
= kCFStringEncodingMacChineseTrad
;
1927 case wxFONTENCODING_MACKOREAN
:
1928 enc
= kCFStringEncodingMacKorean
;
1930 case wxFONTENCODING_MACARABIC
:
1931 enc
= kCFStringEncodingMacArabic
;
1933 case wxFONTENCODING_MACHEBREW
:
1934 enc
= kCFStringEncodingMacHebrew
;
1936 case wxFONTENCODING_MACGREEK
:
1937 enc
= kCFStringEncodingMacGreek
;
1939 case wxFONTENCODING_MACCYRILLIC
:
1940 enc
= kCFStringEncodingMacCyrillic
;
1942 case wxFONTENCODING_MACDEVANAGARI
:
1943 enc
= kCFStringEncodingMacDevanagari
;
1945 case wxFONTENCODING_MACGURMUKHI
:
1946 enc
= kCFStringEncodingMacGurmukhi
;
1948 case wxFONTENCODING_MACGUJARATI
:
1949 enc
= kCFStringEncodingMacGujarati
;
1951 case wxFONTENCODING_MACORIYA
:
1952 enc
= kCFStringEncodingMacOriya
;
1954 case wxFONTENCODING_MACBENGALI
:
1955 enc
= kCFStringEncodingMacBengali
;
1957 case wxFONTENCODING_MACTAMIL
:
1958 enc
= kCFStringEncodingMacTamil
;
1960 case wxFONTENCODING_MACTELUGU
:
1961 enc
= kCFStringEncodingMacTelugu
;
1963 case wxFONTENCODING_MACKANNADA
:
1964 enc
= kCFStringEncodingMacKannada
;
1966 case wxFONTENCODING_MACMALAJALAM
:
1967 enc
= kCFStringEncodingMacMalayalam
;
1969 case wxFONTENCODING_MACSINHALESE
:
1970 enc
= kCFStringEncodingMacSinhalese
;
1972 case wxFONTENCODING_MACBURMESE
:
1973 enc
= kCFStringEncodingMacBurmese
;
1975 case wxFONTENCODING_MACKHMER
:
1976 enc
= kCFStringEncodingMacKhmer
;
1978 case wxFONTENCODING_MACTHAI
:
1979 enc
= kCFStringEncodingMacThai
;
1981 case wxFONTENCODING_MACLAOTIAN
:
1982 enc
= kCFStringEncodingMacLaotian
;
1984 case wxFONTENCODING_MACGEORGIAN
:
1985 enc
= kCFStringEncodingMacGeorgian
;
1987 case wxFONTENCODING_MACARMENIAN
:
1988 enc
= kCFStringEncodingMacArmenian
;
1990 case wxFONTENCODING_MACCHINESESIMP
:
1991 enc
= kCFStringEncodingMacChineseSimp
;
1993 case wxFONTENCODING_MACTIBETAN
:
1994 enc
= kCFStringEncodingMacTibetan
;
1996 case wxFONTENCODING_MACMONGOLIAN
:
1997 enc
= kCFStringEncodingMacMongolian
;
1999 case wxFONTENCODING_MACETHIOPIC
:
2000 enc
= kCFStringEncodingMacEthiopic
;
2002 case wxFONTENCODING_MACCENTRALEUR
:
2003 enc
= kCFStringEncodingMacCentralEurRoman
;
2005 case wxFONTENCODING_MACVIATNAMESE
:
2006 enc
= kCFStringEncodingMacVietnamese
;
2008 case wxFONTENCODING_MACARABICEXT
:
2009 enc
= kCFStringEncodingMacExtArabic
;
2011 case wxFONTENCODING_MACSYMBOL
:
2012 enc
= kCFStringEncodingMacSymbol
;
2014 case wxFONTENCODING_MACDINGBATS
:
2015 enc
= kCFStringEncodingMacDingbats
;
2017 case wxFONTENCODING_MACTURKISH
:
2018 enc
= kCFStringEncodingMacTurkish
;
2020 case wxFONTENCODING_MACCROATIAN
:
2021 enc
= kCFStringEncodingMacCroatian
;
2023 case wxFONTENCODING_MACICELANDIC
:
2024 enc
= kCFStringEncodingMacIcelandic
;
2026 case wxFONTENCODING_MACROMANIAN
:
2027 enc
= kCFStringEncodingMacRomanian
;
2029 case wxFONTENCODING_MACCELTIC
:
2030 enc
= kCFStringEncodingMacCeltic
;
2032 case wxFONTENCODING_MACGAELIC
:
2033 enc
= kCFStringEncodingMacGaelic
;
2035 // case wxFONTENCODING_MACKEYBOARD :
2036 // enc = kCFStringEncodingMacKeyboardGlyphs ;
2039 // because gcc is picky
2045 class wxMBConv_cocoa
: public wxMBConv
2050 Init(CFStringGetSystemEncoding()) ;
2054 wxMBConv_cocoa(const wxChar
* name
)
2056 Init( wxCFStringEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2060 wxMBConv_cocoa(wxFontEncoding encoding
)
2062 Init( wxCFStringEncFromFontEnc(encoding
) );
2069 void Init( CFStringEncoding encoding
)
2071 m_encoding
= encoding
;
2074 size_t MB2WC(wchar_t * szOut
, const char * szUnConv
, size_t nOutSize
) const
2078 CFStringRef theString
= CFStringCreateWithBytes (
2079 NULL
, //the allocator
2080 (const UInt8
*)szUnConv
,
2083 false //no BOM/external representation
2086 wxASSERT(theString
);
2088 size_t nOutLength
= CFStringGetLength(theString
);
2092 CFRelease(theString
);
2096 CFRange theRange
= { 0, nOutSize
};
2098 #if SIZEOF_WCHAR_T == 4
2099 UniChar
* szUniCharBuffer
= new UniChar
[nOutSize
];
2102 CFStringGetCharacters(theString
, theRange
, szUniCharBuffer
);
2104 CFRelease(theString
);
2106 szUniCharBuffer
[nOutLength
] = '\0' ;
2108 #if SIZEOF_WCHAR_T == 4
2109 wxMBConvUTF16 converter
;
2110 converter
.MB2WC(szOut
, (const char*)szUniCharBuffer
, nOutSize
) ;
2111 delete[] szUniCharBuffer
;
2117 size_t WC2MB(char *szOut
, const wchar_t *szUnConv
, size_t nOutSize
) const
2121 size_t nRealOutSize
;
2122 size_t nBufSize
= wxWcslen(szUnConv
);
2123 UniChar
* szUniBuffer
= (UniChar
*) szUnConv
;
2125 #if SIZEOF_WCHAR_T == 4
2126 wxMBConvUTF16BE converter
;
2127 nBufSize
= converter
.WC2MB( NULL
, szUnConv
, 0 );
2128 szUniBuffer
= new UniChar
[ (nBufSize
/ sizeof(UniChar
)) + 1] ;
2129 converter
.WC2MB( (char*) szUniBuffer
, szUnConv
, nBufSize
+ sizeof(UniChar
)) ;
2130 nBufSize
/= sizeof(UniChar
);
2133 CFStringRef theString
= CFStringCreateWithCharactersNoCopy(
2137 kCFAllocatorNull
//deallocator - we want to deallocate it ourselves
2140 wxASSERT(theString
);
2142 //Note that CER puts a BOM when converting to unicode
2143 //so we check and use getchars instead in that case
2144 if (m_encoding
== kCFStringEncodingUnicode
)
2147 CFStringGetCharacters(theString
, CFRangeMake(0, nOutSize
- 1), (UniChar
*) szOut
);
2149 nRealOutSize
= CFStringGetLength(theString
) + 1;
2155 CFRangeMake(0, CFStringGetLength(theString
)),
2157 0, //what to put in characters that can't be converted -
2158 //0 tells CFString to return NULL if it meets such a character
2159 false, //not an external representation
2162 (CFIndex
*) &nRealOutSize
2166 CFRelease(theString
);
2168 #if SIZEOF_WCHAR_T == 4
2169 delete[] szUniBuffer
;
2172 return nRealOutSize
- 1;
2177 return m_encoding
!= kCFStringEncodingInvalidId
&&
2178 CFStringIsEncodingAvailable(m_encoding
);
2182 CFStringEncoding m_encoding
;
2185 #endif // defined(__WXCOCOA__)
2187 // ============================================================================
2188 // Mac conversion classes
2189 // ============================================================================
2191 #if defined(__WXMAC__) && defined(TARGET_CARBON)
2193 class wxMBConv_mac
: public wxMBConv
2198 Init(CFStringGetSystemEncoding()) ;
2202 wxMBConv_mac(const wxChar
* name
)
2204 Init( wxMacGetSystemEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2208 wxMBConv_mac(wxFontEncoding encoding
)
2210 Init( wxMacGetSystemEncFromFontEnc(encoding
) );
2215 OSStatus status
= noErr
;
2216 status
= TECDisposeConverter(m_MB2WC_converter
);
2217 status
= TECDisposeConverter(m_WC2MB_converter
);
2221 void Init( TextEncodingBase encoding
)
2223 OSStatus status
= noErr
;
2224 m_char_encoding
= encoding
;
2225 m_unicode_encoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ;
2227 status
= TECCreateConverter(&m_MB2WC_converter
,
2229 m_unicode_encoding
);
2230 status
= TECCreateConverter(&m_WC2MB_converter
,
2235 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2237 OSStatus status
= noErr
;
2238 ByteCount byteOutLen
;
2239 ByteCount byteInLen
= strlen(psz
) ;
2240 wchar_t *tbuf
= NULL
;
2241 UniChar
* ubuf
= NULL
;
2246 //apple specs say at least 32
2247 n
= wxMax( 32 , byteInLen
) ;
2248 tbuf
= (wchar_t*) malloc( n
* SIZEOF_WCHAR_T
) ;
2250 ByteCount byteBufferLen
= n
* sizeof( UniChar
) ;
2251 #if SIZEOF_WCHAR_T == 4
2252 ubuf
= (UniChar
*) malloc( byteBufferLen
+ 2 ) ;
2254 ubuf
= (UniChar
*) (buf
? buf
: tbuf
) ;
2256 status
= TECConvertText(m_MB2WC_converter
, (ConstTextPtr
) psz
, byteInLen
, &byteInLen
,
2257 (TextPtr
) ubuf
, byteBufferLen
, &byteOutLen
);
2258 #if SIZEOF_WCHAR_T == 4
2259 // we have to terminate here, because n might be larger for the trailing zero, and if UniChar
2260 // is not properly terminated we get random characters at the end
2261 ubuf
[byteOutLen
/ sizeof( UniChar
) ] = 0 ;
2262 wxMBConvUTF16BE converter
;
2263 res
= converter
.MB2WC( (buf
? buf
: tbuf
) , (const char*)ubuf
, n
) ;
2266 res
= byteOutLen
/ sizeof( UniChar
) ;
2271 if ( buf
&& res
< n
)
2277 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2279 OSStatus status
= noErr
;
2280 ByteCount byteOutLen
;
2281 ByteCount byteInLen
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
2287 //apple specs say at least 32
2288 n
= wxMax( 32 , ((byteInLen
/ SIZEOF_WCHAR_T
) * 8) + SIZEOF_WCHAR_T
);
2289 tbuf
= (char*) malloc( n
) ;
2292 ByteCount byteBufferLen
= n
;
2293 UniChar
* ubuf
= NULL
;
2294 #if SIZEOF_WCHAR_T == 4
2295 wxMBConvUTF16BE converter
;
2296 size_t unicharlen
= converter
.WC2MB( NULL
, psz
, 0 ) ;
2297 byteInLen
= unicharlen
;
2298 ubuf
= (UniChar
*) malloc( byteInLen
+ 2 ) ;
2299 converter
.WC2MB( (char*) ubuf
, psz
, unicharlen
+ 2 ) ;
2301 ubuf
= (UniChar
*) psz
;
2303 status
= TECConvertText(m_WC2MB_converter
, (ConstTextPtr
) ubuf
, byteInLen
, &byteInLen
,
2304 (TextPtr
) (buf
? buf
: tbuf
) , byteBufferLen
, &byteOutLen
);
2305 #if SIZEOF_WCHAR_T == 4
2311 size_t res
= byteOutLen
;
2312 if ( buf
&& res
< n
)
2316 //we need to double-trip to verify it didn't insert any ? in place
2317 //of bogus characters
2318 wxWCharBuffer
wcBuf(n
);
2319 size_t pszlen
= wxWcslen(psz
);
2320 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
2321 wxWcslen(wcBuf
) != pszlen
||
2322 memcmp(wcBuf
, psz
, pszlen
* sizeof(wchar_t)) != 0 )
2324 // we didn't obtain the same thing we started from, hence
2325 // the conversion was lossy and we consider that it failed
2334 { return m_MB2WC_converter
!= NULL
&& m_WC2MB_converter
!= NULL
; }
2337 TECObjectRef m_MB2WC_converter
;
2338 TECObjectRef m_WC2MB_converter
;
2340 TextEncodingBase m_char_encoding
;
2341 TextEncodingBase m_unicode_encoding
;
2344 #endif // defined(__WXMAC__) && defined(TARGET_CARBON)
2346 // ============================================================================
2347 // wxEncodingConverter based conversion classes
2348 // ============================================================================
2352 class wxMBConv_wxwin
: public wxMBConv
2357 m_ok
= m2w
.Init(m_enc
, wxFONTENCODING_UNICODE
) &&
2358 w2m
.Init(wxFONTENCODING_UNICODE
, m_enc
);
2362 // temporarily just use wxEncodingConverter stuff,
2363 // so that it works while a better implementation is built
2364 wxMBConv_wxwin(const wxChar
* name
)
2367 m_enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
2369 m_enc
= wxFONTENCODING_SYSTEM
;
2374 wxMBConv_wxwin(wxFontEncoding enc
)
2381 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t WXUNUSED(n
)) const
2383 size_t inbuf
= strlen(psz
);
2386 if (!m2w
.Convert(psz
,buf
))
2392 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t WXUNUSED(n
)) const
2394 const size_t inbuf
= wxWcslen(psz
);
2397 if (!w2m
.Convert(psz
,buf
))
2404 bool IsOk() const { return m_ok
; }
2407 wxFontEncoding m_enc
;
2408 wxEncodingConverter m2w
, w2m
;
2410 // were we initialized successfully?
2413 DECLARE_NO_COPY_CLASS(wxMBConv_wxwin
)
2416 #endif // wxUSE_FONTMAP
2418 // ============================================================================
2419 // wxCSConv implementation
2420 // ============================================================================
2422 void wxCSConv::Init()
2429 wxCSConv::wxCSConv(const wxChar
*charset
)
2438 m_encoding
= wxFONTENCODING_SYSTEM
;
2441 wxCSConv::wxCSConv(wxFontEncoding encoding
)
2443 if ( encoding
== wxFONTENCODING_MAX
|| encoding
== wxFONTENCODING_DEFAULT
)
2445 wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
2447 encoding
= wxFONTENCODING_SYSTEM
;
2452 m_encoding
= encoding
;
2455 wxCSConv::~wxCSConv()
2460 wxCSConv::wxCSConv(const wxCSConv
& conv
)
2465 SetName(conv
.m_name
);
2466 m_encoding
= conv
.m_encoding
;
2469 wxCSConv
& wxCSConv::operator=(const wxCSConv
& conv
)
2473 SetName(conv
.m_name
);
2474 m_encoding
= conv
.m_encoding
;
2479 void wxCSConv::Clear()
2488 void wxCSConv::SetName(const wxChar
*charset
)
2492 m_name
= wxStrdup(charset
);
2497 wxMBConv
*wxCSConv::DoCreate() const
2499 // check for the special case of ASCII or ISO8859-1 charset: as we have
2500 // special knowledge of it anyhow, we don't need to create a special
2501 // conversion object
2502 if ( m_encoding
== wxFONTENCODING_ISO8859_1
)
2504 // don't convert at all
2508 // we trust OS to do conversion better than we can so try external
2509 // conversion methods first
2511 // the full order is:
2512 // 1. OS conversion (iconv() under Unix or Win32 API)
2513 // 2. hard coded conversions for UTF
2514 // 3. wxEncodingConverter as fall back
2520 #endif // !wxUSE_FONTMAP
2522 wxString
name(m_name
);
2526 name
= wxFontMapperBase::Get()->GetEncodingName(m_encoding
);
2527 #endif // wxUSE_FONTMAP
2529 wxMBConv_iconv
*conv
= new wxMBConv_iconv(name
);
2535 #endif // HAVE_ICONV
2537 #ifdef wxHAVE_WIN32_MB2WC
2540 wxMBConv_win32
*conv
= m_name
? new wxMBConv_win32(m_name
)
2541 : new wxMBConv_win32(m_encoding
);
2550 #endif // wxHAVE_WIN32_MB2WC
2551 #if defined(__WXMAC__)
2553 // leave UTF16 and UTF32 to the built-ins of wx
2554 if ( m_name
|| ( m_encoding
< wxFONTENCODING_UTF16BE
||
2555 ( m_encoding
>= wxFONTENCODING_MACMIN
&& m_encoding
<= wxFONTENCODING_MACMAX
) ) )
2559 wxMBConv_mac
*conv
= m_name
? new wxMBConv_mac(m_name
)
2560 : new wxMBConv_mac(m_encoding
);
2562 wxMBConv_mac
*conv
= new wxMBConv_mac(m_encoding
);
2571 #if defined(__WXCOCOA__)
2573 if ( m_name
|| ( m_encoding
<= wxFONTENCODING_UTF16
) )
2577 wxMBConv_cocoa
*conv
= m_name
? new wxMBConv_cocoa(m_name
)
2578 : new wxMBConv_cocoa(m_encoding
);
2580 wxMBConv_cocoa
*conv
= new wxMBConv_cocoa(m_encoding
);
2590 wxFontEncoding enc
= m_encoding
;
2592 if ( enc
== wxFONTENCODING_SYSTEM
&& m_name
)
2594 // use "false" to suppress interactive dialogs -- we can be called from
2595 // anywhere and popping up a dialog from here is the last thing we want to
2597 enc
= wxFontMapperBase::Get()->CharsetToEncoding(m_name
, false);
2599 #endif // wxUSE_FONTMAP
2603 case wxFONTENCODING_UTF7
:
2604 return new wxMBConvUTF7
;
2606 case wxFONTENCODING_UTF8
:
2607 return new wxMBConvUTF8
;
2609 case wxFONTENCODING_UTF16BE
:
2610 return new wxMBConvUTF16BE
;
2612 case wxFONTENCODING_UTF16LE
:
2613 return new wxMBConvUTF16LE
;
2615 case wxFONTENCODING_UTF32BE
:
2616 return new wxMBConvUTF32BE
;
2618 case wxFONTENCODING_UTF32LE
:
2619 return new wxMBConvUTF32LE
;
2622 // nothing to do but put here to suppress gcc warnings
2629 wxMBConv_wxwin
*conv
= m_name
? new wxMBConv_wxwin(m_name
)
2630 : new wxMBConv_wxwin(m_encoding
);
2636 #endif // wxUSE_FONTMAP
2638 // NB: This is a hack to prevent deadlock. What could otherwise happen
2639 // in Unicode build: wxConvLocal creation ends up being here
2640 // because of some failure and logs the error. But wxLog will try to
2641 // attach timestamp, for which it will need wxConvLocal (to convert
2642 // time to char* and then wchar_t*), but that fails, tries to log
2643 // error, but wxLog has a (already locked) critical section that
2644 // guards static buffer.
2645 static bool alreadyLoggingError
= false;
2646 if (!alreadyLoggingError
)
2648 alreadyLoggingError
= true;
2649 wxLogError(_("Cannot convert from the charset '%s'!"),
2653 wxFontMapperBase::GetEncodingDescription(m_encoding
).c_str()
2654 #else // !wxUSE_FONTMAP
2655 wxString::Format(_("encoding %s"), m_encoding
).c_str()
2656 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
2658 alreadyLoggingError
= false;
2664 void wxCSConv::CreateConvIfNeeded() const
2668 wxCSConv
*self
= (wxCSConv
*)this; // const_cast
2671 // if we don't have neither the name nor the encoding, use the default
2672 // encoding for this system
2673 if ( !m_name
&& m_encoding
== wxFONTENCODING_SYSTEM
)
2675 self
->m_name
= wxStrdup(wxLocale::GetSystemEncodingName());
2677 #endif // wxUSE_INTL
2679 self
->m_convReal
= DoCreate();
2680 self
->m_deferred
= false;
2684 size_t wxCSConv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2686 CreateConvIfNeeded();
2689 return m_convReal
->MB2WC(buf
, psz
, n
);
2692 size_t len
= strlen(psz
);
2696 for (size_t c
= 0; c
<= len
; c
++)
2697 buf
[c
] = (unsigned char)(psz
[c
]);
2703 size_t wxCSConv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2705 CreateConvIfNeeded();
2708 return m_convReal
->WC2MB(buf
, psz
, n
);
2711 const size_t len
= wxWcslen(psz
);
2714 for (size_t c
= 0; c
<= len
; c
++)
2718 buf
[c
] = (char)psz
[c
];
2723 for (size_t c
= 0; c
<= len
; c
++)
2733 // ----------------------------------------------------------------------------
2735 // ----------------------------------------------------------------------------
2738 static wxMBConv_win32 wxConvLibcObj
;
2739 #elif defined(__WXMAC__) && !defined(__MACH__)
2740 static wxMBConv_mac wxConvLibcObj
;
2742 static wxMBConvLibc wxConvLibcObj
;
2745 static wxCSConv
wxConvLocalObj(wxFONTENCODING_SYSTEM
);
2746 static wxCSConv
wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1
);
2747 static wxMBConvUTF7 wxConvUTF7Obj
;
2748 static wxMBConvUTF8 wxConvUTF8Obj
;
2750 WXDLLIMPEXP_DATA_BASE(wxMBConv
&) wxConvLibc
= wxConvLibcObj
;
2751 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvLocal
= wxConvLocalObj
;
2752 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvISO8859_1
= wxConvISO8859_1Obj
;
2753 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7
&) wxConvUTF7
= wxConvUTF7Obj
;
2754 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8
&) wxConvUTF8
= wxConvUTF8Obj
;
2755 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvCurrent
= &wxConvLibcObj
;
2756 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvFileName
= &
2764 #else // !wxUSE_WCHAR_T
2766 // stand-ins in absence of wchar_t
2767 WXDLLIMPEXP_DATA_BASE(wxMBConv
) wxConvLibc
,
2772 #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T