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
);
363 // ----------------------------------------------------------------------------
364 // wxConvBrokenFileNames is made for GTK2 in Unicode mode when
365 // files are accidentally written in an encoding which is not
366 // the system encoding. Typically, the system encoding will be
367 // UTF8 but there might be files stored in ISO8859-1 on disk.
368 // ----------------------------------------------------------------------------
370 class wxConvBrokenFileNames
: public wxMBConvLibc
373 wxConvBrokenFileNames() : m_utf8conv(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL
) { }
374 virtual size_t MB2WC(wchar_t *outputBuf
, const char *psz
, size_t outputSize
) const;
375 virtual size_t WC2MB(char *outputBuf
, const wchar_t *psz
, size_t outputSize
) const;
376 inline bool UseUTF8() const;
378 wxMBConvUTF8 m_utf8conv
;
381 bool wxConvBrokenFileNames::UseUTF8() const
383 #if defined HAVE_LANGINFO_H && defined CODESET
384 char *codeset
= nl_langinfo(CODESET
);
385 return strcmp(codeset
, "UTF-8") == 0;
391 size_t wxConvBrokenFileNames::MB2WC(wchar_t *outputBuf
, const char *psz
, size_t outputSize
) const
394 return m_utf8conv
.MB2WC( outputBuf
, psz
, outputSize
);
396 return wxMBConvLibc::MB2WC( outputBuf
, psz
, outputSize
);
399 size_t wxConvBrokenFileNames::WC2MB(char *outputBuf
, const wchar_t *psz
, size_t outputSize
) const
402 return m_utf8conv
.WC2MB( outputBuf
, psz
, outputSize
);
404 return wxMBConvLibc::WC2MB( outputBuf
, psz
, outputSize
);
407 // ----------------------------------------------------------------------------
409 // ----------------------------------------------------------------------------
411 // Implementation (C) 2004 Fredrik Roubert
414 // BASE64 decoding table
416 static const unsigned char utf7unb64
[] =
418 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
419 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
420 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
421 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
422 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
423 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
424 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
425 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
426 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
427 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
428 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
429 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
430 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
431 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
432 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
433 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
434 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
435 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
436 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
437 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
438 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
439 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
440 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
442 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
443 0xff, 0xff, 0xff, 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
452 size_t wxMBConvUTF7::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
456 while (*psz
&& ((!buf
) || (len
< n
)))
458 unsigned char cc
= *psz
++;
466 else if (*psz
== '-')
476 // BASE64 encoded string
480 for (lsb
= false, d
= 0, l
= 0;
481 (cc
= utf7unb64
[(unsigned char)*psz
]) != 0xff; psz
++)
485 for (l
+= 6; l
>= 8; lsb
= !lsb
)
487 c
= (unsigned char)((d
>> (l
-= 8)) % 256);
496 *buf
= (wchar_t)(c
<< 8);
503 if (buf
&& (len
< n
))
509 // BASE64 encoding table
511 static const unsigned char utf7enb64
[] =
513 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
514 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
515 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
516 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
517 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
518 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
519 'w', 'x', 'y', 'z', '0', '1', '2', '3',
520 '4', '5', '6', '7', '8', '9', '+', '/'
524 // UTF-7 encoding table
526 // 0 - Set D (directly encoded characters)
527 // 1 - Set O (optional direct characters)
528 // 2 - whitespace characters (optional)
529 // 3 - special characters
531 static const unsigned char utf7encode
[128] =
533 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,
534 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
535 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 3,
536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
537 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
538 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1,
539 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3
543 size_t wxMBConvUTF7::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
549 while (*psz
&& ((!buf
) || (len
< n
)))
552 if (cc
< 0x80 && utf7encode
[cc
] < 1)
560 else if (((wxUint32
)cc
) > 0xffff)
562 // no surrogate pair generation (yet?)
573 // BASE64 encode string
574 unsigned int lsb
, d
, l
;
575 for (d
= 0, l
= 0;; psz
++)
577 for (lsb
= 0; lsb
< 2; lsb
++)
580 d
+= lsb
? cc
& 0xff : (cc
& 0xff00) >> 8;
582 for (l
+= 8; l
>= 6; )
586 *buf
++ = utf7enb64
[(d
>> l
) % 64];
591 if (!(cc
) || (cc
< 0x80 && utf7encode
[cc
] < 1))
597 *buf
++ = utf7enb64
[((d
% 16) << (6 - l
)) % 64];
606 if (buf
&& (len
< n
))
611 // ----------------------------------------------------------------------------
613 // ----------------------------------------------------------------------------
615 static wxUint32 utf8_max
[]=
616 { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff };
618 const wxUint32 wxUnicodePUA
= 0x100000;
619 const wxUint32 wxUnicodePUAEnd
= wxUnicodePUA
+ 256;
621 size_t wxMBConvUTF8::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
625 while (*psz
&& ((!buf
) || (len
< n
)))
627 const char *opsz
= psz
;
628 bool invalid
= false;
629 unsigned char cc
= *psz
++, fc
= cc
;
631 for (cnt
= 0; fc
& 0x80; cnt
++)
645 // invalid UTF-8 sequence
650 unsigned ocnt
= cnt
- 1;
651 wxUint32 res
= cc
& (0x3f >> cnt
);
655 if ((cc
& 0xC0) != 0x80)
657 // invalid UTF-8 sequence
662 res
= (res
<< 6) | (cc
& 0x3f);
664 if (invalid
|| res
<= utf8_max
[ocnt
])
666 // illegal UTF-8 encoding
669 else if ((m_options
& MAP_INVALID_UTF8_TO_PUA
) &&
670 res
>= wxUnicodePUA
&& res
< wxUnicodePUAEnd
)
672 // if one of our PUA characters turns up externally
673 // it must also be treated as an illegal sequence
674 // (a bit like you have to escape an escape character)
680 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
681 size_t pa
= encode_utf16(res
, (wxUint16
*)buf
);
682 if (pa
== (size_t)-1)
696 #endif // WC_UTF16/!WC_UTF16
701 if (m_options
& MAP_INVALID_UTF8_TO_PUA
)
703 while (opsz
< psz
&& (!buf
|| len
< n
))
706 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
707 size_t pa
= encode_utf16((unsigned char)*opsz
+ wxUnicodePUA
, (wxUint16
*)buf
);
708 wxASSERT(pa
!= (size_t)-1);
715 *buf
++ = wxUnicodePUA
+ (unsigned char)*opsz
;
722 if (m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
724 while (opsz
< psz
&& (!buf
|| len
< n
))
727 wxSnprintf( str
, 5, L
"\\%o", (int) (unsigned char) *opsz
);
747 if (buf
&& (len
< n
))
752 size_t wxMBConvUTF8::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
756 while (*psz
&& ((!buf
) || (len
< n
)))
760 // cast is ok for WC_UTF16
761 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
762 psz
+= (pa
== (size_t)-1) ? 1 : pa
;
764 cc
=(*psz
++) & 0x7fffffff;
766 if ((m_options
& MAP_INVALID_UTF8_TO_PUA
)
767 && cc
>= wxUnicodePUA
&& cc
< wxUnicodePUAEnd
)
770 *buf
++ = (char)(cc
- wxUnicodePUA
);
774 if ((m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
778 str
[0] = *psz
; psz
++;
779 str
[1] = *psz
; psz
++;
780 str
[2] = *psz
; psz
++;
783 wxSscanf( str
, L
"%o", &octal
);
785 *buf
++ = (char) octal
;
791 for (cnt
= 0; cc
> utf8_max
[cnt
]; cnt
++) {}
805 *buf
++ = (char) ((-128 >> cnt
) | ((cc
>> (cnt
* 6)) & (0x3f >> cnt
)));
807 *buf
++ = (char) (0x80 | ((cc
>> (cnt
* 6)) & 0x3f));
813 if (buf
&& (len
<n
)) *buf
= 0;
818 // ----------------------------------------------------------------------------
820 // ----------------------------------------------------------------------------
822 #ifdef WORDS_BIGENDIAN
823 #define wxMBConvUTF16straight wxMBConvUTF16BE
824 #define wxMBConvUTF16swap wxMBConvUTF16LE
826 #define wxMBConvUTF16swap wxMBConvUTF16BE
827 #define wxMBConvUTF16straight wxMBConvUTF16LE
833 // copy 16bit MB to 16bit String
834 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
838 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
841 *buf
++ = *(wxUint16
*)psz
;
844 psz
+= sizeof(wxUint16
);
846 if (buf
&& len
<n
) *buf
=0;
852 // copy 16bit String to 16bit MB
853 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
857 while (*psz
&& (!buf
|| len
< n
))
861 *(wxUint16
*)buf
= *psz
;
862 buf
+= sizeof(wxUint16
);
864 len
+= sizeof(wxUint16
);
867 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
873 // swap 16bit MB to 16bit String
874 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
878 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
882 ((char *)buf
)[0] = psz
[1];
883 ((char *)buf
)[1] = psz
[0];
887 psz
+= sizeof(wxUint16
);
889 if (buf
&& len
<n
) *buf
=0;
895 // swap 16bit MB to 16bit String
896 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
900 while (*psz
&& (!buf
|| len
< n
))
904 *buf
++ = ((char*)psz
)[1];
905 *buf
++ = ((char*)psz
)[0];
907 len
+= sizeof(wxUint16
);
910 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
919 // copy 16bit MB to 32bit String
920 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
924 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
927 size_t pa
=decode_utf16((wxUint16
*)psz
, cc
);
928 if (pa
== (size_t)-1)
934 psz
+= pa
* sizeof(wxUint16
);
936 if (buf
&& len
<n
) *buf
=0;
942 // copy 32bit String to 16bit MB
943 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
947 while (*psz
&& (!buf
|| len
< n
))
950 size_t pa
=encode_utf16(*psz
, cc
);
952 if (pa
== (size_t)-1)
957 *(wxUint16
*)buf
= cc
[0];
958 buf
+= sizeof(wxUint16
);
961 *(wxUint16
*)buf
= cc
[1];
962 buf
+= sizeof(wxUint16
);
966 len
+= pa
*sizeof(wxUint16
);
969 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
975 // swap 16bit MB to 32bit String
976 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
980 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
984 tmp
[0]=psz
[1]; tmp
[1]=psz
[0];
985 tmp
[2]=psz
[3]; tmp
[3]=psz
[2];
987 size_t pa
=decode_utf16((wxUint16
*)tmp
, cc
);
988 if (pa
== (size_t)-1)
995 psz
+= pa
* sizeof(wxUint16
);
997 if (buf
&& len
<n
) *buf
=0;
1003 // swap 32bit String to 16bit MB
1004 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1008 while (*psz
&& (!buf
|| len
< n
))
1011 size_t pa
=encode_utf16(*psz
, cc
);
1013 if (pa
== (size_t)-1)
1018 *buf
++ = ((char*)cc
)[1];
1019 *buf
++ = ((char*)cc
)[0];
1022 *buf
++ = ((char*)cc
)[3];
1023 *buf
++ = ((char*)cc
)[2];
1027 len
+= pa
*sizeof(wxUint16
);
1030 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
1038 // ----------------------------------------------------------------------------
1040 // ----------------------------------------------------------------------------
1042 #ifdef WORDS_BIGENDIAN
1043 #define wxMBConvUTF32straight wxMBConvUTF32BE
1044 #define wxMBConvUTF32swap wxMBConvUTF32LE
1046 #define wxMBConvUTF32swap wxMBConvUTF32BE
1047 #define wxMBConvUTF32straight wxMBConvUTF32LE
1051 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32LE
) wxConvUTF32LE
;
1052 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32BE
) wxConvUTF32BE
;
1057 // copy 32bit MB to 16bit String
1058 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1062 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1066 size_t pa
=encode_utf16(*(wxUint32
*)psz
, cc
);
1067 if (pa
== (size_t)-1)
1077 psz
+= sizeof(wxUint32
);
1079 if (buf
&& len
<n
) *buf
=0;
1085 // copy 16bit String to 32bit MB
1086 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1090 while (*psz
&& (!buf
|| len
< n
))
1094 // cast is ok for WC_UTF16
1095 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
1096 if (pa
== (size_t)-1)
1101 *(wxUint32
*)buf
= cc
;
1102 buf
+= sizeof(wxUint32
);
1104 len
+= sizeof(wxUint32
);
1108 if (buf
&& len
<=n
-sizeof(wxUint32
))
1116 // swap 32bit MB to 16bit String
1117 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1121 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1124 tmp
[0] = psz
[3]; tmp
[1] = psz
[2];
1125 tmp
[2] = psz
[1]; tmp
[3] = psz
[0];
1130 size_t pa
=encode_utf16(*(wxUint32
*)tmp
, cc
);
1131 if (pa
== (size_t)-1)
1141 psz
+= sizeof(wxUint32
);
1151 // swap 16bit String to 32bit MB
1152 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1156 while (*psz
&& (!buf
|| len
< n
))
1160 // cast is ok for WC_UTF16
1161 size_t pa
=decode_utf16((const wxUint16
*)psz
, *(wxUint32
*)cc
);
1162 if (pa
== (size_t)-1)
1172 len
+= sizeof(wxUint32
);
1176 if (buf
&& len
<=n
-sizeof(wxUint32
))
1185 // copy 32bit MB to 32bit String
1186 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1190 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1193 *buf
++ = *(wxUint32
*)psz
;
1195 psz
+= sizeof(wxUint32
);
1205 // copy 32bit String to 32bit MB
1206 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1210 while (*psz
&& (!buf
|| len
< n
))
1214 *(wxUint32
*)buf
= *psz
;
1215 buf
+= sizeof(wxUint32
);
1218 len
+= sizeof(wxUint32
);
1222 if (buf
&& len
<=n
-sizeof(wxUint32
))
1229 // swap 32bit MB to 32bit String
1230 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1234 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1238 ((char *)buf
)[0] = psz
[3];
1239 ((char *)buf
)[1] = psz
[2];
1240 ((char *)buf
)[2] = psz
[1];
1241 ((char *)buf
)[3] = psz
[0];
1245 psz
+= sizeof(wxUint32
);
1255 // swap 32bit String to 32bit MB
1256 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1260 while (*psz
&& (!buf
|| len
< n
))
1264 *buf
++ = ((char *)psz
)[3];
1265 *buf
++ = ((char *)psz
)[2];
1266 *buf
++ = ((char *)psz
)[1];
1267 *buf
++ = ((char *)psz
)[0];
1269 len
+= sizeof(wxUint32
);
1273 if (buf
&& len
<=n
-sizeof(wxUint32
))
1283 // ============================================================================
1284 // The classes doing conversion using the iconv_xxx() functions
1285 // ============================================================================
1289 // VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with
1290 // E2BIG if output buffer is _exactly_ as big as needed. Such case is
1291 // (unless there's yet another bug in glibc) the only case when iconv()
1292 // returns with (size_t)-1 (which means error) and says there are 0 bytes
1293 // left in the input buffer -- when _real_ error occurs,
1294 // bytes-left-in-input buffer is non-zero. Hence, this alternative test for
1296 // [This bug does not appear in glibc 2.2.]
1297 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1
1298 #define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \
1299 (errno != E2BIG || bufLeft != 0))
1301 #define ICONV_FAILED(cres, bufLeft) (cres == (size_t)-1)
1304 #define ICONV_CHAR_CAST(x) ((ICONV_CONST char **)(x))
1306 // ----------------------------------------------------------------------------
1307 // wxMBConv_iconv: encapsulates an iconv character set
1308 // ----------------------------------------------------------------------------
1310 class wxMBConv_iconv
: public wxMBConv
1313 wxMBConv_iconv(const wxChar
*name
);
1314 virtual ~wxMBConv_iconv();
1316 virtual size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const;
1317 virtual size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const;
1320 { return (m2w
!= (iconv_t
)-1) && (w2m
!= (iconv_t
)-1); }
1323 // the iconv handlers used to translate from multibyte to wide char and in
1324 // the other direction
1328 // guards access to m2w and w2m objects
1329 wxMutex m_iconvMutex
;
1333 // the name (for iconv_open()) of a wide char charset -- if none is
1334 // available on this machine, it will remain NULL
1335 static const char *ms_wcCharsetName
;
1337 // true if the wide char encoding we use (i.e. ms_wcCharsetName) has
1338 // different endian-ness than the native one
1339 static bool ms_wcNeedsSwap
;
1342 const char *wxMBConv_iconv::ms_wcCharsetName
= NULL
;
1343 bool wxMBConv_iconv::ms_wcNeedsSwap
= false;
1345 wxMBConv_iconv::wxMBConv_iconv(const wxChar
*name
)
1347 // Do it the hard way
1349 for (size_t i
= 0; i
< wxStrlen(name
)+1; i
++)
1350 cname
[i
] = (char) name
[i
];
1352 // check for charset that represents wchar_t:
1353 if (ms_wcCharsetName
== NULL
)
1355 ms_wcNeedsSwap
= false;
1357 // try charset with explicit bytesex info (e.g. "UCS-4LE"):
1358 ms_wcCharsetName
= WC_NAME_BEST
;
1359 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1361 if (m2w
== (iconv_t
)-1)
1363 // try charset w/o bytesex info (e.g. "UCS4")
1364 // and check for bytesex ourselves:
1365 ms_wcCharsetName
= WC_NAME
;
1366 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1368 // last bet, try if it knows WCHAR_T pseudo-charset
1369 if (m2w
== (iconv_t
)-1)
1371 ms_wcCharsetName
= "WCHAR_T";
1372 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1375 if (m2w
!= (iconv_t
)-1)
1377 char buf
[2], *bufPtr
;
1378 wchar_t wbuf
[2], *wbufPtr
;
1386 outsz
= SIZEOF_WCHAR_T
* 2;
1390 res
= iconv(m2w
, ICONV_CHAR_CAST(&bufPtr
), &insz
,
1391 (char**)&wbufPtr
, &outsz
);
1393 if (ICONV_FAILED(res
, insz
))
1395 ms_wcCharsetName
= NULL
;
1396 wxLogLastError(wxT("iconv"));
1397 wxLogError(_("Conversion to charset '%s' doesn't work."), name
);
1401 ms_wcNeedsSwap
= wbuf
[0] != (wchar_t)buf
[0];
1406 ms_wcCharsetName
= NULL
;
1408 // VS: we must not output an error here, since wxWidgets will safely
1409 // fall back to using wxEncodingConverter.
1410 wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name
);
1414 wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName
, ms_wcNeedsSwap
);
1416 else // we already have ms_wcCharsetName
1418 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1421 // NB: don't ever pass NULL to iconv_open(), it may crash!
1422 if ( ms_wcCharsetName
)
1424 w2m
= iconv_open( cname
, ms_wcCharsetName
);
1432 wxMBConv_iconv::~wxMBConv_iconv()
1434 if ( m2w
!= (iconv_t
)-1 )
1436 if ( w2m
!= (iconv_t
)-1 )
1440 size_t wxMBConv_iconv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1443 // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle.
1444 // Unfortunately there is a couple of global wxCSConv objects such as
1445 // wxConvLocal that are used all over wx code, so we have to make sure
1446 // the handle is used by at most one thread at the time. Otherwise
1447 // only a few wx classes would be safe to use from non-main threads
1448 // as MB<->WC conversion would fail "randomly".
1449 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1452 size_t inbuf
= strlen(psz
);
1453 size_t outbuf
= n
* SIZEOF_WCHAR_T
;
1455 // VS: Use these instead of psz, buf because iconv() modifies its arguments:
1456 wchar_t *bufPtr
= buf
;
1457 const char *pszPtr
= psz
;
1461 // have destination buffer, convert there
1463 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1464 (char**)&bufPtr
, &outbuf
);
1465 res
= n
- (outbuf
/ SIZEOF_WCHAR_T
);
1469 // convert to native endianness
1470 WC_BSWAP(buf
/* _not_ bufPtr */, res
)
1473 // NB: iconv was given only strlen(psz) characters on input, and so
1474 // it couldn't convert the trailing zero. Let's do it ourselves
1475 // if there's some room left for it in the output buffer.
1481 // no destination buffer... convert using temp buffer
1482 // to calculate destination buffer requirement
1487 outbuf
= 8*SIZEOF_WCHAR_T
;
1490 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1491 (char**)&bufPtr
, &outbuf
);
1493 res
+= 8-(outbuf
/SIZEOF_WCHAR_T
);
1494 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1497 if (ICONV_FAILED(cres
, inbuf
))
1499 //VS: it is ok if iconv fails, hence trace only
1500 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1507 size_t wxMBConv_iconv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1510 // NB: explained in MB2WC
1511 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1514 size_t inbuf
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
1518 wchar_t *tmpbuf
= 0;
1522 // need to copy to temp buffer to switch endianness
1523 // this absolutely doesn't rock!
1524 // (no, doing WC_BSWAP twice on the original buffer won't help, as it
1525 // could be in read-only memory, or be accessed in some other thread)
1526 tmpbuf
=(wchar_t*)malloc((inbuf
+1)*SIZEOF_WCHAR_T
);
1527 memcpy(tmpbuf
,psz
,(inbuf
+1)*SIZEOF_WCHAR_T
);
1528 WC_BSWAP(tmpbuf
, inbuf
)
1534 // have destination buffer, convert there
1535 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1539 // NB: iconv was given only wcslen(psz) characters on input, and so
1540 // it couldn't convert the trailing zero. Let's do it ourselves
1541 // if there's some room left for it in the output buffer.
1547 // no destination buffer... convert using temp buffer
1548 // to calculate destination buffer requirement
1552 buf
= tbuf
; outbuf
= 16;
1554 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1557 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1565 if (ICONV_FAILED(cres
, inbuf
))
1567 //VS: it is ok if iconv fails, hence trace only
1568 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1575 #endif // HAVE_ICONV
1578 // ============================================================================
1579 // Win32 conversion classes
1580 // ============================================================================
1582 #ifdef wxHAVE_WIN32_MB2WC
1586 extern WXDLLIMPEXP_BASE
long wxCharsetToCodepage(const wxChar
*charset
);
1587 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
);
1590 class wxMBConv_win32
: public wxMBConv
1595 m_CodePage
= CP_ACP
;
1599 wxMBConv_win32(const wxChar
* name
)
1601 m_CodePage
= wxCharsetToCodepage(name
);
1604 wxMBConv_win32(wxFontEncoding encoding
)
1606 m_CodePage
= wxEncodingToCodepage(encoding
);
1610 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1612 // note that we have to use MB_ERR_INVALID_CHARS flag as it without it
1613 // the behaviour is not compatible with the Unix version (using iconv)
1614 // and break the library itself, e.g. wxTextInputStream::NextChar()
1615 // wouldn't work if reading an incomplete MB char didn't result in an
1618 // note however that using MB_ERR_INVALID_CHARS with CP_UTF7 results in
1619 // an error (tested under Windows Server 2003) and apparently it is
1620 // done on purpose, i.e. the function accepts any input in this case
1621 // and although I'd prefer to return error on ill-formed output, our
1622 // own wxMBConvUTF7 doesn't detect errors (e.g. lone "+" which is
1623 // explicitly ill-formed according to RFC 2152) neither so we don't
1624 // even have any fallback here...
1625 int flags
= m_CodePage
== CP_UTF7
? 0 : MB_ERR_INVALID_CHARS
;
1627 const size_t len
= ::MultiByteToWideChar
1629 m_CodePage
, // code page
1630 flags
, // flags: fall on error
1631 psz
, // input string
1632 -1, // its length (NUL-terminated)
1633 buf
, // output string
1634 buf
? n
: 0 // size of output buffer
1637 // note that it returns count of written chars for buf != NULL and size
1638 // of the needed buffer for buf == NULL so in either case the length of
1639 // the string (which never includes the terminating NUL) is one less
1640 return len
? len
- 1 : (size_t)-1;
1643 size_t WC2MB(char *buf
, const wchar_t *pwz
, size_t n
) const
1646 we have a problem here: by default, WideCharToMultiByte() may
1647 replace characters unrepresentable in the target code page with bad
1648 quality approximations such as turning "1/2" symbol (U+00BD) into
1649 "1" for the code pages which don't have it and we, obviously, want
1650 to avoid this at any price
1652 the trouble is that this function does it _silently_, i.e. it won't
1653 even tell us whether it did or not... Win98/2000 and higher provide
1654 WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and
1655 we have to resort to a round trip, i.e. check that converting back
1656 results in the same string -- this is, of course, expensive but
1657 otherwise we simply can't be sure to not garble the data.
1660 // determine if we can rely on WC_NO_BEST_FIT_CHARS: according to MSDN
1661 // it doesn't work with CJK encodings (which we test for rather roughly
1662 // here...) nor with UTF-7/8 nor, of course, with Windows versions not
1664 BOOL usedDef
wxDUMMY_INITIALIZE(false);
1667 if ( CanUseNoBestFit() && m_CodePage
< 50000 )
1669 // it's our lucky day
1670 flags
= WC_NO_BEST_FIT_CHARS
;
1671 pUsedDef
= &usedDef
;
1673 else // old system or unsupported encoding
1679 const size_t len
= ::WideCharToMultiByte
1681 m_CodePage
, // code page
1682 flags
, // either none or no best fit
1683 pwz
, // input string
1684 -1, // it is (wide) NUL-terminated
1685 buf
, // output buffer
1686 buf
? n
: 0, // and its size
1687 NULL
, // default "replacement" char
1688 pUsedDef
// [out] was it used?
1693 // function totally failed
1697 // if we were really converting, check if we succeeded
1702 // check if the conversion failed, i.e. if any replacements
1707 else // we must resort to double tripping...
1709 wxWCharBuffer
wcBuf(n
);
1710 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
1711 wcscmp(wcBuf
, pwz
) != 0 )
1713 // we didn't obtain the same thing we started from, hence
1714 // the conversion was lossy and we consider that it failed
1720 // see the comment above for the reason of "len - 1"
1724 bool IsOk() const { return m_CodePage
!= -1; }
1727 static bool CanUseNoBestFit()
1729 static int s_isWin98Or2k
= -1;
1731 if ( s_isWin98Or2k
== -1 )
1734 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1737 s_isWin98Or2k
= verMaj
>= 4 && verMin
>= 10;
1741 s_isWin98Or2k
= verMaj
>= 5;
1745 // unknown, be conseravtive by default
1749 wxASSERT_MSG( s_isWin98Or2k
!= -1, _T("should be set above") );
1752 return s_isWin98Or2k
== 1;
1758 #endif // wxHAVE_WIN32_MB2WC
1760 // ============================================================================
1761 // Cocoa conversion classes
1762 // ============================================================================
1764 #if defined(__WXCOCOA__)
1766 // RN: There is no UTF-32 support in either Core Foundation or
1767 // Cocoa. Strangely enough, internally Core Foundation uses
1768 // UTF 32 internally quite a bit - its just not public (yet).
1770 #include <CoreFoundation/CFString.h>
1771 #include <CoreFoundation/CFStringEncodingExt.h>
1773 CFStringEncoding
wxCFStringEncFromFontEnc(wxFontEncoding encoding
)
1775 CFStringEncoding enc
= kCFStringEncodingInvalidId
;
1776 if ( encoding
== wxFONTENCODING_DEFAULT
)
1778 enc
= CFStringGetSystemEncoding();
1780 else switch( encoding
)
1782 case wxFONTENCODING_ISO8859_1
:
1783 enc
= kCFStringEncodingISOLatin1
;
1785 case wxFONTENCODING_ISO8859_2
:
1786 enc
= kCFStringEncodingISOLatin2
;
1788 case wxFONTENCODING_ISO8859_3
:
1789 enc
= kCFStringEncodingISOLatin3
;
1791 case wxFONTENCODING_ISO8859_4
:
1792 enc
= kCFStringEncodingISOLatin4
;
1794 case wxFONTENCODING_ISO8859_5
:
1795 enc
= kCFStringEncodingISOLatinCyrillic
;
1797 case wxFONTENCODING_ISO8859_6
:
1798 enc
= kCFStringEncodingISOLatinArabic
;
1800 case wxFONTENCODING_ISO8859_7
:
1801 enc
= kCFStringEncodingISOLatinGreek
;
1803 case wxFONTENCODING_ISO8859_8
:
1804 enc
= kCFStringEncodingISOLatinHebrew
;
1806 case wxFONTENCODING_ISO8859_9
:
1807 enc
= kCFStringEncodingISOLatin5
;
1809 case wxFONTENCODING_ISO8859_10
:
1810 enc
= kCFStringEncodingISOLatin6
;
1812 case wxFONTENCODING_ISO8859_11
:
1813 enc
= kCFStringEncodingISOLatinThai
;
1815 case wxFONTENCODING_ISO8859_13
:
1816 enc
= kCFStringEncodingISOLatin7
;
1818 case wxFONTENCODING_ISO8859_14
:
1819 enc
= kCFStringEncodingISOLatin8
;
1821 case wxFONTENCODING_ISO8859_15
:
1822 enc
= kCFStringEncodingISOLatin9
;
1825 case wxFONTENCODING_KOI8
:
1826 enc
= kCFStringEncodingKOI8_R
;
1828 case wxFONTENCODING_ALTERNATIVE
: // MS-DOS CP866
1829 enc
= kCFStringEncodingDOSRussian
;
1832 // case wxFONTENCODING_BULGARIAN :
1836 case wxFONTENCODING_CP437
:
1837 enc
=kCFStringEncodingDOSLatinUS
;
1839 case wxFONTENCODING_CP850
:
1840 enc
= kCFStringEncodingDOSLatin1
;
1842 case wxFONTENCODING_CP852
:
1843 enc
= kCFStringEncodingDOSLatin2
;
1845 case wxFONTENCODING_CP855
:
1846 enc
= kCFStringEncodingDOSCyrillic
;
1848 case wxFONTENCODING_CP866
:
1849 enc
=kCFStringEncodingDOSRussian
;
1851 case wxFONTENCODING_CP874
:
1852 enc
= kCFStringEncodingDOSThai
;
1854 case wxFONTENCODING_CP932
:
1855 enc
= kCFStringEncodingDOSJapanese
;
1857 case wxFONTENCODING_CP936
:
1858 enc
=kCFStringEncodingDOSChineseSimplif
;
1860 case wxFONTENCODING_CP949
:
1861 enc
= kCFStringEncodingDOSKorean
;
1863 case wxFONTENCODING_CP950
:
1864 enc
= kCFStringEncodingDOSChineseTrad
;
1866 case wxFONTENCODING_CP1250
:
1867 enc
= kCFStringEncodingWindowsLatin2
;
1869 case wxFONTENCODING_CP1251
:
1870 enc
=kCFStringEncodingWindowsCyrillic
;
1872 case wxFONTENCODING_CP1252
:
1873 enc
=kCFStringEncodingWindowsLatin1
;
1875 case wxFONTENCODING_CP1253
:
1876 enc
= kCFStringEncodingWindowsGreek
;
1878 case wxFONTENCODING_CP1254
:
1879 enc
= kCFStringEncodingWindowsLatin5
;
1881 case wxFONTENCODING_CP1255
:
1882 enc
=kCFStringEncodingWindowsHebrew
;
1884 case wxFONTENCODING_CP1256
:
1885 enc
=kCFStringEncodingWindowsArabic
;
1887 case wxFONTENCODING_CP1257
:
1888 enc
= kCFStringEncodingWindowsBalticRim
;
1890 // This only really encodes to UTF7 (if that) evidently
1891 // case wxFONTENCODING_UTF7 :
1892 // enc = kCFStringEncodingNonLossyASCII ;
1894 case wxFONTENCODING_UTF8
:
1895 enc
= kCFStringEncodingUTF8
;
1897 case wxFONTENCODING_EUC_JP
:
1898 enc
= kCFStringEncodingEUC_JP
;
1900 case wxFONTENCODING_UTF16
:
1901 enc
= kCFStringEncodingUnicode
;
1903 case wxFONTENCODING_MACROMAN
:
1904 enc
= kCFStringEncodingMacRoman
;
1906 case wxFONTENCODING_MACJAPANESE
:
1907 enc
= kCFStringEncodingMacJapanese
;
1909 case wxFONTENCODING_MACCHINESETRAD
:
1910 enc
= kCFStringEncodingMacChineseTrad
;
1912 case wxFONTENCODING_MACKOREAN
:
1913 enc
= kCFStringEncodingMacKorean
;
1915 case wxFONTENCODING_MACARABIC
:
1916 enc
= kCFStringEncodingMacArabic
;
1918 case wxFONTENCODING_MACHEBREW
:
1919 enc
= kCFStringEncodingMacHebrew
;
1921 case wxFONTENCODING_MACGREEK
:
1922 enc
= kCFStringEncodingMacGreek
;
1924 case wxFONTENCODING_MACCYRILLIC
:
1925 enc
= kCFStringEncodingMacCyrillic
;
1927 case wxFONTENCODING_MACDEVANAGARI
:
1928 enc
= kCFStringEncodingMacDevanagari
;
1930 case wxFONTENCODING_MACGURMUKHI
:
1931 enc
= kCFStringEncodingMacGurmukhi
;
1933 case wxFONTENCODING_MACGUJARATI
:
1934 enc
= kCFStringEncodingMacGujarati
;
1936 case wxFONTENCODING_MACORIYA
:
1937 enc
= kCFStringEncodingMacOriya
;
1939 case wxFONTENCODING_MACBENGALI
:
1940 enc
= kCFStringEncodingMacBengali
;
1942 case wxFONTENCODING_MACTAMIL
:
1943 enc
= kCFStringEncodingMacTamil
;
1945 case wxFONTENCODING_MACTELUGU
:
1946 enc
= kCFStringEncodingMacTelugu
;
1948 case wxFONTENCODING_MACKANNADA
:
1949 enc
= kCFStringEncodingMacKannada
;
1951 case wxFONTENCODING_MACMALAJALAM
:
1952 enc
= kCFStringEncodingMacMalayalam
;
1954 case wxFONTENCODING_MACSINHALESE
:
1955 enc
= kCFStringEncodingMacSinhalese
;
1957 case wxFONTENCODING_MACBURMESE
:
1958 enc
= kCFStringEncodingMacBurmese
;
1960 case wxFONTENCODING_MACKHMER
:
1961 enc
= kCFStringEncodingMacKhmer
;
1963 case wxFONTENCODING_MACTHAI
:
1964 enc
= kCFStringEncodingMacThai
;
1966 case wxFONTENCODING_MACLAOTIAN
:
1967 enc
= kCFStringEncodingMacLaotian
;
1969 case wxFONTENCODING_MACGEORGIAN
:
1970 enc
= kCFStringEncodingMacGeorgian
;
1972 case wxFONTENCODING_MACARMENIAN
:
1973 enc
= kCFStringEncodingMacArmenian
;
1975 case wxFONTENCODING_MACCHINESESIMP
:
1976 enc
= kCFStringEncodingMacChineseSimp
;
1978 case wxFONTENCODING_MACTIBETAN
:
1979 enc
= kCFStringEncodingMacTibetan
;
1981 case wxFONTENCODING_MACMONGOLIAN
:
1982 enc
= kCFStringEncodingMacMongolian
;
1984 case wxFONTENCODING_MACETHIOPIC
:
1985 enc
= kCFStringEncodingMacEthiopic
;
1987 case wxFONTENCODING_MACCENTRALEUR
:
1988 enc
= kCFStringEncodingMacCentralEurRoman
;
1990 case wxFONTENCODING_MACVIATNAMESE
:
1991 enc
= kCFStringEncodingMacVietnamese
;
1993 case wxFONTENCODING_MACARABICEXT
:
1994 enc
= kCFStringEncodingMacExtArabic
;
1996 case wxFONTENCODING_MACSYMBOL
:
1997 enc
= kCFStringEncodingMacSymbol
;
1999 case wxFONTENCODING_MACDINGBATS
:
2000 enc
= kCFStringEncodingMacDingbats
;
2002 case wxFONTENCODING_MACTURKISH
:
2003 enc
= kCFStringEncodingMacTurkish
;
2005 case wxFONTENCODING_MACCROATIAN
:
2006 enc
= kCFStringEncodingMacCroatian
;
2008 case wxFONTENCODING_MACICELANDIC
:
2009 enc
= kCFStringEncodingMacIcelandic
;
2011 case wxFONTENCODING_MACROMANIAN
:
2012 enc
= kCFStringEncodingMacRomanian
;
2014 case wxFONTENCODING_MACCELTIC
:
2015 enc
= kCFStringEncodingMacCeltic
;
2017 case wxFONTENCODING_MACGAELIC
:
2018 enc
= kCFStringEncodingMacGaelic
;
2020 // case wxFONTENCODING_MACKEYBOARD :
2021 // enc = kCFStringEncodingMacKeyboardGlyphs ;
2024 // because gcc is picky
2030 class wxMBConv_cocoa
: public wxMBConv
2035 Init(CFStringGetSystemEncoding()) ;
2039 wxMBConv_cocoa(const wxChar
* name
)
2041 Init( wxCFStringEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2045 wxMBConv_cocoa(wxFontEncoding encoding
)
2047 Init( wxCFStringEncFromFontEnc(encoding
) );
2054 void Init( CFStringEncoding encoding
)
2056 m_encoding
= encoding
;
2059 size_t MB2WC(wchar_t * szOut
, const char * szUnConv
, size_t nOutSize
) const
2063 CFStringRef theString
= CFStringCreateWithBytes (
2064 NULL
, //the allocator
2065 (const UInt8
*)szUnConv
,
2068 false //no BOM/external representation
2071 wxASSERT(theString
);
2073 size_t nOutLength
= CFStringGetLength(theString
);
2077 CFRelease(theString
);
2081 CFRange theRange
= { 0, nOutSize
};
2083 #if SIZEOF_WCHAR_T == 4
2084 UniChar
* szUniCharBuffer
= new UniChar
[nOutSize
];
2087 CFStringGetCharacters(theString
, theRange
, szUniCharBuffer
);
2089 CFRelease(theString
);
2091 szUniCharBuffer
[nOutLength
] = '\0' ;
2093 #if SIZEOF_WCHAR_T == 4
2094 wxMBConvUTF16 converter
;
2095 converter
.MB2WC(szOut
, (const char*)szUniCharBuffer
, nOutSize
) ;
2096 delete[] szUniCharBuffer
;
2102 size_t WC2MB(char *szOut
, const wchar_t *szUnConv
, size_t nOutSize
) const
2106 size_t nRealOutSize
;
2107 size_t nBufSize
= wxWcslen(szUnConv
);
2108 UniChar
* szUniBuffer
= (UniChar
*) szUnConv
;
2110 #if SIZEOF_WCHAR_T == 4
2111 wxMBConvUTF16BE converter
;
2112 nBufSize
= converter
.WC2MB( NULL
, szUnConv
, 0 );
2113 szUniBuffer
= new UniChar
[ (nBufSize
/ sizeof(UniChar
)) + 1] ;
2114 converter
.WC2MB( (char*) szUniBuffer
, szUnConv
, nBufSize
+ sizeof(UniChar
)) ;
2115 nBufSize
/= sizeof(UniChar
);
2118 CFStringRef theString
= CFStringCreateWithCharactersNoCopy(
2122 kCFAllocatorNull
//deallocator - we want to deallocate it ourselves
2125 wxASSERT(theString
);
2127 //Note that CER puts a BOM when converting to unicode
2128 //so we check and use getchars instead in that case
2129 if (m_encoding
== kCFStringEncodingUnicode
)
2132 CFStringGetCharacters(theString
, CFRangeMake(0, nOutSize
- 1), (UniChar
*) szOut
);
2134 nRealOutSize
= CFStringGetLength(theString
) + 1;
2140 CFRangeMake(0, CFStringGetLength(theString
)),
2142 0, //what to put in characters that can't be converted -
2143 //0 tells CFString to return NULL if it meets such a character
2144 false, //not an external representation
2147 (CFIndex
*) &nRealOutSize
2151 CFRelease(theString
);
2153 #if SIZEOF_WCHAR_T == 4
2154 delete[] szUniBuffer
;
2157 return nRealOutSize
- 1;
2162 return m_encoding
!= kCFStringEncodingInvalidId
&&
2163 CFStringIsEncodingAvailable(m_encoding
);
2167 CFStringEncoding m_encoding
;
2170 #endif // defined(__WXCOCOA__)
2172 // ============================================================================
2173 // Mac conversion classes
2174 // ============================================================================
2176 #if defined(__WXMAC__) && defined(TARGET_CARBON)
2178 class wxMBConv_mac
: public wxMBConv
2183 Init(CFStringGetSystemEncoding()) ;
2187 wxMBConv_mac(const wxChar
* name
)
2189 Init( wxMacGetSystemEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2193 wxMBConv_mac(wxFontEncoding encoding
)
2195 Init( wxMacGetSystemEncFromFontEnc(encoding
) );
2200 OSStatus status
= noErr
;
2201 status
= TECDisposeConverter(m_MB2WC_converter
);
2202 status
= TECDisposeConverter(m_WC2MB_converter
);
2206 void Init( TextEncodingBase encoding
)
2208 OSStatus status
= noErr
;
2209 m_char_encoding
= encoding
;
2210 m_unicode_encoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ;
2212 status
= TECCreateConverter(&m_MB2WC_converter
,
2214 m_unicode_encoding
);
2215 status
= TECCreateConverter(&m_WC2MB_converter
,
2220 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2222 OSStatus status
= noErr
;
2223 ByteCount byteOutLen
;
2224 ByteCount byteInLen
= strlen(psz
) ;
2225 wchar_t *tbuf
= NULL
;
2226 UniChar
* ubuf
= NULL
;
2231 //apple specs say at least 32
2232 n
= wxMax( 32 , byteInLen
) ;
2233 tbuf
= (wchar_t*) malloc( n
* SIZEOF_WCHAR_T
) ;
2235 ByteCount byteBufferLen
= n
* sizeof( UniChar
) ;
2236 #if SIZEOF_WCHAR_T == 4
2237 ubuf
= (UniChar
*) malloc( byteBufferLen
+ 2 ) ;
2239 ubuf
= (UniChar
*) (buf
? buf
: tbuf
) ;
2241 status
= TECConvertText(m_MB2WC_converter
, (ConstTextPtr
) psz
, byteInLen
, &byteInLen
,
2242 (TextPtr
) ubuf
, byteBufferLen
, &byteOutLen
);
2243 #if SIZEOF_WCHAR_T == 4
2244 // we have to terminate here, because n might be larger for the trailing zero, and if UniChar
2245 // is not properly terminated we get random characters at the end
2246 ubuf
[byteOutLen
/ sizeof( UniChar
) ] = 0 ;
2247 wxMBConvUTF16BE converter
;
2248 res
= converter
.MB2WC( (buf
? buf
: tbuf
) , (const char*)ubuf
, n
) ;
2251 res
= byteOutLen
/ sizeof( UniChar
) ;
2256 if ( buf
&& res
< n
)
2262 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2264 OSStatus status
= noErr
;
2265 ByteCount byteOutLen
;
2266 ByteCount byteInLen
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
2272 //apple specs say at least 32
2273 n
= wxMax( 32 , ((byteInLen
/ SIZEOF_WCHAR_T
) * 8) + SIZEOF_WCHAR_T
);
2274 tbuf
= (char*) malloc( n
) ;
2277 ByteCount byteBufferLen
= n
;
2278 UniChar
* ubuf
= NULL
;
2279 #if SIZEOF_WCHAR_T == 4
2280 wxMBConvUTF16BE converter
;
2281 size_t unicharlen
= converter
.WC2MB( NULL
, psz
, 0 ) ;
2282 byteInLen
= unicharlen
;
2283 ubuf
= (UniChar
*) malloc( byteInLen
+ 2 ) ;
2284 converter
.WC2MB( (char*) ubuf
, psz
, unicharlen
+ 2 ) ;
2286 ubuf
= (UniChar
*) psz
;
2288 status
= TECConvertText(m_WC2MB_converter
, (ConstTextPtr
) ubuf
, byteInLen
, &byteInLen
,
2289 (TextPtr
) (buf
? buf
: tbuf
) , byteBufferLen
, &byteOutLen
);
2290 #if SIZEOF_WCHAR_T == 4
2296 size_t res
= byteOutLen
;
2297 if ( buf
&& res
< n
)
2301 //we need to double-trip to verify it didn't insert any ? in place
2302 //of bogus characters
2303 wxWCharBuffer
wcBuf(n
);
2304 size_t pszlen
= wxWcslen(psz
);
2305 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
2306 wxWcslen(wcBuf
) != pszlen
||
2307 memcmp(wcBuf
, psz
, pszlen
* sizeof(wchar_t)) != 0 )
2309 // we didn't obtain the same thing we started from, hence
2310 // the conversion was lossy and we consider that it failed
2319 { return m_MB2WC_converter
!= NULL
&& m_WC2MB_converter
!= NULL
; }
2322 TECObjectRef m_MB2WC_converter
;
2323 TECObjectRef m_WC2MB_converter
;
2325 TextEncodingBase m_char_encoding
;
2326 TextEncodingBase m_unicode_encoding
;
2329 #endif // defined(__WXMAC__) && defined(TARGET_CARBON)
2331 // ============================================================================
2332 // wxEncodingConverter based conversion classes
2333 // ============================================================================
2337 class wxMBConv_wxwin
: public wxMBConv
2342 m_ok
= m2w
.Init(m_enc
, wxFONTENCODING_UNICODE
) &&
2343 w2m
.Init(wxFONTENCODING_UNICODE
, m_enc
);
2347 // temporarily just use wxEncodingConverter stuff,
2348 // so that it works while a better implementation is built
2349 wxMBConv_wxwin(const wxChar
* name
)
2352 m_enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
2354 m_enc
= wxFONTENCODING_SYSTEM
;
2359 wxMBConv_wxwin(wxFontEncoding enc
)
2366 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t WXUNUSED(n
)) const
2368 size_t inbuf
= strlen(psz
);
2371 if (!m2w
.Convert(psz
,buf
))
2377 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t WXUNUSED(n
)) const
2379 const size_t inbuf
= wxWcslen(psz
);
2382 if (!w2m
.Convert(psz
,buf
))
2389 bool IsOk() const { return m_ok
; }
2392 wxFontEncoding m_enc
;
2393 wxEncodingConverter m2w
, w2m
;
2395 // were we initialized successfully?
2398 DECLARE_NO_COPY_CLASS(wxMBConv_wxwin
)
2401 #endif // wxUSE_FONTMAP
2403 // ============================================================================
2404 // wxCSConv implementation
2405 // ============================================================================
2407 void wxCSConv::Init()
2414 wxCSConv::wxCSConv(const wxChar
*charset
)
2423 m_encoding
= wxFONTENCODING_SYSTEM
;
2426 wxCSConv::wxCSConv(wxFontEncoding encoding
)
2428 if ( encoding
== wxFONTENCODING_MAX
|| encoding
== wxFONTENCODING_DEFAULT
)
2430 wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
2432 encoding
= wxFONTENCODING_SYSTEM
;
2437 m_encoding
= encoding
;
2440 wxCSConv::~wxCSConv()
2445 wxCSConv::wxCSConv(const wxCSConv
& conv
)
2450 SetName(conv
.m_name
);
2451 m_encoding
= conv
.m_encoding
;
2454 wxCSConv
& wxCSConv::operator=(const wxCSConv
& conv
)
2458 SetName(conv
.m_name
);
2459 m_encoding
= conv
.m_encoding
;
2464 void wxCSConv::Clear()
2473 void wxCSConv::SetName(const wxChar
*charset
)
2477 m_name
= wxStrdup(charset
);
2482 wxMBConv
*wxCSConv::DoCreate() const
2484 // check for the special case of ASCII or ISO8859-1 charset: as we have
2485 // special knowledge of it anyhow, we don't need to create a special
2486 // conversion object
2487 if ( m_encoding
== wxFONTENCODING_ISO8859_1
)
2489 // don't convert at all
2493 // we trust OS to do conversion better than we can so try external
2494 // conversion methods first
2496 // the full order is:
2497 // 1. OS conversion (iconv() under Unix or Win32 API)
2498 // 2. hard coded conversions for UTF
2499 // 3. wxEncodingConverter as fall back
2505 #endif // !wxUSE_FONTMAP
2507 wxString
name(m_name
);
2511 name
= wxFontMapperBase::Get()->GetEncodingName(m_encoding
);
2512 #endif // wxUSE_FONTMAP
2514 wxMBConv_iconv
*conv
= new wxMBConv_iconv(name
);
2520 #endif // HAVE_ICONV
2522 #ifdef wxHAVE_WIN32_MB2WC
2525 wxMBConv_win32
*conv
= m_name
? new wxMBConv_win32(m_name
)
2526 : new wxMBConv_win32(m_encoding
);
2535 #endif // wxHAVE_WIN32_MB2WC
2536 #if defined(__WXMAC__)
2538 // leave UTF16 and UTF32 to the built-ins of wx
2539 if ( m_name
|| ( m_encoding
< wxFONTENCODING_UTF16BE
||
2540 ( m_encoding
>= wxFONTENCODING_MACMIN
&& m_encoding
<= wxFONTENCODING_MACMAX
) ) )
2544 wxMBConv_mac
*conv
= m_name
? new wxMBConv_mac(m_name
)
2545 : new wxMBConv_mac(m_encoding
);
2547 wxMBConv_mac
*conv
= new wxMBConv_mac(m_encoding
);
2556 #if defined(__WXCOCOA__)
2558 if ( m_name
|| ( m_encoding
<= wxFONTENCODING_UTF16
) )
2562 wxMBConv_cocoa
*conv
= m_name
? new wxMBConv_cocoa(m_name
)
2563 : new wxMBConv_cocoa(m_encoding
);
2565 wxMBConv_cocoa
*conv
= new wxMBConv_cocoa(m_encoding
);
2575 wxFontEncoding enc
= m_encoding
;
2577 if ( enc
== wxFONTENCODING_SYSTEM
&& m_name
)
2579 // use "false" to suppress interactive dialogs -- we can be called from
2580 // anywhere and popping up a dialog from here is the last thing we want to
2582 enc
= wxFontMapperBase::Get()->CharsetToEncoding(m_name
, false);
2584 #endif // wxUSE_FONTMAP
2588 case wxFONTENCODING_UTF7
:
2589 return new wxMBConvUTF7
;
2591 case wxFONTENCODING_UTF8
:
2592 return new wxMBConvUTF8
;
2594 case wxFONTENCODING_UTF16BE
:
2595 return new wxMBConvUTF16BE
;
2597 case wxFONTENCODING_UTF16LE
:
2598 return new wxMBConvUTF16LE
;
2600 case wxFONTENCODING_UTF32BE
:
2601 return new wxMBConvUTF32BE
;
2603 case wxFONTENCODING_UTF32LE
:
2604 return new wxMBConvUTF32LE
;
2607 // nothing to do but put here to suppress gcc warnings
2614 wxMBConv_wxwin
*conv
= m_name
? new wxMBConv_wxwin(m_name
)
2615 : new wxMBConv_wxwin(m_encoding
);
2621 #endif // wxUSE_FONTMAP
2623 // NB: This is a hack to prevent deadlock. What could otherwise happen
2624 // in Unicode build: wxConvLocal creation ends up being here
2625 // because of some failure and logs the error. But wxLog will try to
2626 // attach timestamp, for which it will need wxConvLocal (to convert
2627 // time to char* and then wchar_t*), but that fails, tries to log
2628 // error, but wxLog has a (already locked) critical section that
2629 // guards static buffer.
2630 static bool alreadyLoggingError
= false;
2631 if (!alreadyLoggingError
)
2633 alreadyLoggingError
= true;
2634 wxLogError(_("Cannot convert from the charset '%s'!"),
2638 wxFontMapperBase::GetEncodingDescription(m_encoding
).c_str()
2639 #else // !wxUSE_FONTMAP
2640 wxString::Format(_("encoding %s"), m_encoding
).c_str()
2641 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
2643 alreadyLoggingError
= false;
2649 void wxCSConv::CreateConvIfNeeded() const
2653 wxCSConv
*self
= (wxCSConv
*)this; // const_cast
2656 // if we don't have neither the name nor the encoding, use the default
2657 // encoding for this system
2658 if ( !m_name
&& m_encoding
== wxFONTENCODING_SYSTEM
)
2660 self
->m_name
= wxStrdup(wxLocale::GetSystemEncodingName());
2662 #endif // wxUSE_INTL
2664 self
->m_convReal
= DoCreate();
2665 self
->m_deferred
= false;
2669 size_t wxCSConv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2671 CreateConvIfNeeded();
2674 return m_convReal
->MB2WC(buf
, psz
, n
);
2677 size_t len
= strlen(psz
);
2681 for (size_t c
= 0; c
<= len
; c
++)
2682 buf
[c
] = (unsigned char)(psz
[c
]);
2688 size_t wxCSConv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2690 CreateConvIfNeeded();
2693 return m_convReal
->WC2MB(buf
, psz
, n
);
2696 const size_t len
= wxWcslen(psz
);
2699 for (size_t c
= 0; c
<= len
; c
++)
2703 buf
[c
] = (char)psz
[c
];
2708 for (size_t c
= 0; c
<= len
; c
++)
2718 // ----------------------------------------------------------------------------
2720 // ----------------------------------------------------------------------------
2723 static wxMBConv_win32 wxConvLibcObj
;
2724 #elif defined(__WXMAC__) && !defined(__MACH__)
2725 static wxMBConv_mac wxConvLibcObj
;
2727 static wxMBConvLibc wxConvLibcObj
;
2730 static wxCSConv
wxConvLocalObj(wxFONTENCODING_SYSTEM
);
2731 static wxCSConv
wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1
);
2732 static wxMBConvUTF7 wxConvUTF7Obj
;
2733 static wxMBConvUTF8 wxConvUTF8Obj
;
2734 static wxConvBrokenFileNames wxConvBrokenFileNamesObj
;
2736 WXDLLIMPEXP_DATA_BASE(wxMBConv
&) wxConvLibc
= wxConvLibcObj
;
2737 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvLocal
= wxConvLocalObj
;
2738 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvISO8859_1
= wxConvISO8859_1Obj
;
2739 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7
&) wxConvUTF7
= wxConvUTF7Obj
;
2740 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8
&) wxConvUTF8
= wxConvUTF8Obj
;
2741 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvCurrent
= &wxConvLibcObj
;
2742 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvFileName
= &
2746 wxConvBrokenFileNamesObj
;
2752 #else // !wxUSE_WCHAR_T
2754 // stand-ins in absence of wchar_t
2755 WXDLLIMPEXP_DATA_BASE(wxMBConv
) wxConvLibc
,
2760 #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T