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"
59 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
60 #define wxHAVE_WIN32_MB2WC
61 #endif // __WIN32__ but !__WXMICROWIN__
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
73 #include "wx/thread.h"
76 #include "wx/encconv.h"
77 #include "wx/fontmap.h"
81 #include <ATSUnicode.h>
82 #include <TextCommon.h>
83 #include <TextEncodingConverter.h>
85 #include "wx/mac/private.h" // includes mac headers
87 // ----------------------------------------------------------------------------
89 // ----------------------------------------------------------------------------
91 #define BSWAP_UCS4(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT32_SWAP_ALWAYS(str[_c]); }
92 #define BSWAP_UTF16(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT16_SWAP_ALWAYS(str[_c]); }
94 #if SIZEOF_WCHAR_T == 4
95 #define WC_NAME "UCS4"
96 #define WC_BSWAP BSWAP_UCS4
97 #ifdef WORDS_BIGENDIAN
98 #define WC_NAME_BEST "UCS-4BE"
100 #define WC_NAME_BEST "UCS-4LE"
102 #elif SIZEOF_WCHAR_T == 2
103 #define WC_NAME "UTF16"
104 #define WC_BSWAP BSWAP_UTF16
106 #ifdef WORDS_BIGENDIAN
107 #define WC_NAME_BEST "UTF-16BE"
109 #define WC_NAME_BEST "UTF-16LE"
111 #else // sizeof(wchar_t) != 2 nor 4
112 // does this ever happen?
113 #error "Unknown sizeof(wchar_t): please report this to wx-dev@lists.wxwindows.org"
116 // ============================================================================
118 // ============================================================================
120 // ----------------------------------------------------------------------------
121 // UTF-16 en/decoding to/from UCS-4
122 // ----------------------------------------------------------------------------
125 static size_t encode_utf16(wxUint32 input
, wxUint16
*output
)
130 *output
= (wxUint16
) input
;
133 else if (input
>=0x110000)
141 *output
++ = (wxUint16
) ((input
>> 10)+0xd7c0);
142 *output
= (wxUint16
) ((input
&0x3ff)+0xdc00);
148 static size_t decode_utf16(const wxUint16
* input
, wxUint32
& output
)
150 if ((*input
<0xd800) || (*input
>0xdfff))
155 else if ((input
[1]<0xdc00) || (input
[1]>0xdfff))
162 output
= ((input
[0] - 0xd7c0) << 10) + (input
[1] - 0xdc00);
168 // ----------------------------------------------------------------------------
170 // ----------------------------------------------------------------------------
172 wxMBConv::~wxMBConv()
174 // nothing to do here (necessary for Darwin linking probably)
177 const wxWCharBuffer
wxMBConv::cMB2WC(const char *psz
) const
181 // calculate the length of the buffer needed first
182 size_t nLen
= MB2WC(NULL
, psz
, 0);
183 if ( nLen
!= (size_t)-1 )
185 // now do the actual conversion
186 wxWCharBuffer
buf(nLen
);
187 nLen
= MB2WC(buf
.data(), psz
, nLen
+ 1); // with the trailing NULL
188 if ( nLen
!= (size_t)-1 )
195 wxWCharBuffer
buf((wchar_t *)NULL
);
200 const wxCharBuffer
wxMBConv::cWC2MB(const wchar_t *pwz
) const
204 size_t nLen
= WC2MB(NULL
, pwz
, 0);
205 if ( nLen
!= (size_t)-1 )
207 wxCharBuffer
buf(nLen
+3); // space for a wxUint32 trailing zero
208 nLen
= WC2MB(buf
.data(), pwz
, nLen
+ 4);
209 if ( nLen
!= (size_t)-1 )
216 wxCharBuffer
buf((char *)NULL
);
221 const wxWCharBuffer
wxMBConv::cMB2WC(const char *szString
, size_t nStringLen
, size_t* pOutSize
) const
223 wxASSERT(pOutSize
!= NULL
);
225 const char* szEnd
= szString
+ nStringLen
+ 1;
226 const char* szPos
= szString
;
227 const char* szStart
= szPos
;
229 size_t nActualLength
= 0;
230 size_t nCurrentSize
= nStringLen
; //try normal size first (should never resize?)
232 wxWCharBuffer
theBuffer(nCurrentSize
);
234 //Convert the string until the length() is reached, continuing the
235 //loop every time a null character is reached
236 while(szPos
!= szEnd
)
238 wxASSERT(szPos
< szEnd
); //something is _really_ screwed up if this rings true
240 //Get the length of the current (sub)string
241 size_t nLen
= MB2WC(NULL
, szPos
, 0);
243 //Invalid conversion?
244 if( nLen
== (size_t)-1 )
247 theBuffer
.data()[0u] = wxT('\0');
252 //Increase the actual length (+1 for current null character)
253 nActualLength
+= nLen
+ 1;
255 //if buffer too big, realloc the buffer
256 if (nActualLength
> (nCurrentSize
+1))
258 wxWCharBuffer
theNewBuffer(nCurrentSize
<< 1);
259 memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize
* sizeof(wchar_t));
260 theBuffer
= theNewBuffer
;
264 //Convert the current (sub)string
265 if ( MB2WC(&theBuffer
.data()[szPos
- szStart
], szPos
, nLen
+ 1) == (size_t)-1 )
268 theBuffer
.data()[0u] = wxT('\0');
272 //Increment to next (sub)string
273 //Note that we have to use strlen here instead of nLen
274 //here because XX2XX gives us the size of the output buffer,
275 //not neccessarly the length of the string
276 szPos
+= strlen(szPos
) + 1;
279 //success - return actual length and the buffer
280 *pOutSize
= nActualLength
;
284 const wxCharBuffer
wxMBConv::cWC2MB(const wchar_t *szString
, size_t nStringLen
, size_t* pOutSize
) const
286 wxASSERT(pOutSize
!= NULL
);
288 const wchar_t* szEnd
= szString
+ nStringLen
+ 1;
289 const wchar_t* szPos
= szString
;
290 const wchar_t* szStart
= szPos
;
292 size_t nActualLength
= 0;
293 size_t nCurrentSize
= nStringLen
<< 2; //try * 4 first
295 wxCharBuffer
theBuffer(nCurrentSize
);
297 //Convert the string until the length() is reached, continuing the
298 //loop every time a null character is reached
299 while(szPos
!= szEnd
)
301 wxASSERT(szPos
< szEnd
); //something is _really_ screwed up if this rings true
303 //Get the length of the current (sub)string
304 size_t nLen
= WC2MB(NULL
, szPos
, 0);
306 //Invalid conversion?
307 if( nLen
== (size_t)-1 )
310 theBuffer
.data()[0u] = wxT('\0');
314 //Increase the actual length (+1 for current null character)
315 nActualLength
+= nLen
+ 1;
317 //if buffer too big, realloc the buffer
318 if (nActualLength
> (nCurrentSize
+1))
320 wxCharBuffer
theNewBuffer(nCurrentSize
<< 1);
321 memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize
);
322 theBuffer
= theNewBuffer
;
326 //Convert the current (sub)string
327 if(WC2MB(&theBuffer
.data()[szPos
- szStart
], szPos
, nLen
+ 1) == (size_t)-1 )
330 theBuffer
.data()[0u] = wxT('\0');
334 //Increment to next (sub)string
335 //Note that we have to use wxWcslen here instead of nLen
336 //here because XX2XX gives us the size of the output buffer,
337 //not neccessarly the length of the string
338 szPos
+= wxWcslen(szPos
) + 1;
341 //success - return actual length and the buffer
342 *pOutSize
= nActualLength
;
346 // ----------------------------------------------------------------------------
348 // ----------------------------------------------------------------------------
350 size_t wxMBConvLibc::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
352 return wxMB2WC(buf
, psz
, n
);
355 size_t wxMBConvLibc::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
357 return wxWC2MB(buf
, psz
, n
);
362 // ----------------------------------------------------------------------------
363 // wxConvBrokenFileNames
364 // ----------------------------------------------------------------------------
366 wxConvBrokenFileNames::wxConvBrokenFileNames()
368 // decide which conversion to use for the file names
370 // (1) this variable exists for the sole purpose of specifying the encoding
371 // of the filenames for GTK+ programs, so use it if it is set
372 wxString
encName(wxGetenv(_T("G_FILENAME_ENCODING")));
374 if ( !encName
.empty() && encName
!= _T("UTF-8") && encName
!= _T("UTF8") )
376 m_conv
= new wxCSConv(encName
);
378 else // no G_FILENAME_ENCODING
381 if ( encName
.empty() )
382 encName
= wxLocale::GetSystemEncodingName().Upper();
385 // (2) if a non default locale is set, assume that the user wants his
386 // filenames in this locale too
387 if ( !encName
.empty() && encName
!= _T("UTF-8") && encName
!= _T("UTF8") )
389 wxSetEnv(_T("G_FILENAME_ENCODING"), encName
);
390 m_conv
= new wxCSConv(encName
);
394 // (3) finally use UTF-8 by default
395 m_conv
= new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL
);
401 wxConvBrokenFileNames::MB2WC(wchar_t *outputBuf
,
403 size_t outputSize
) const
405 return m_conv
->MB2WC( outputBuf
, psz
, outputSize
);
409 wxConvBrokenFileNames::WC2MB(char *outputBuf
,
411 size_t outputSize
) const
413 return m_conv
->WC2MB( outputBuf
, psz
, outputSize
);
418 // ----------------------------------------------------------------------------
420 // ----------------------------------------------------------------------------
422 // Implementation (C) 2004 Fredrik Roubert
425 // BASE64 decoding table
427 static const unsigned char utf7unb64
[] =
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, 0xff, 0xff, 0xff, 0xff, 0xff,
434 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
435 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
436 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
437 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
438 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
439 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
440 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
441 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
442 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
443 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
444 0x31, 0x32, 0x33, 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,
460 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
463 size_t wxMBConvUTF7::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
467 while (*psz
&& ((!buf
) || (len
< n
)))
469 unsigned char cc
= *psz
++;
477 else if (*psz
== '-')
487 // BASE64 encoded string
491 for (lsb
= false, d
= 0, l
= 0;
492 (cc
= utf7unb64
[(unsigned char)*psz
]) != 0xff; psz
++)
496 for (l
+= 6; l
>= 8; lsb
= !lsb
)
498 c
= (unsigned char)((d
>> (l
-= 8)) % 256);
507 *buf
= (wchar_t)(c
<< 8);
514 if (buf
&& (len
< n
))
520 // BASE64 encoding table
522 static const unsigned char utf7enb64
[] =
524 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
525 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
526 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
527 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
528 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
529 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
530 'w', 'x', 'y', 'z', '0', '1', '2', '3',
531 '4', '5', '6', '7', '8', '9', '+', '/'
535 // UTF-7 encoding table
537 // 0 - Set D (directly encoded characters)
538 // 1 - Set O (optional direct characters)
539 // 2 - whitespace characters (optional)
540 // 3 - special characters
542 static const unsigned char utf7encode
[128] =
544 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3,
545 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
546 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 3,
547 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
548 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1,
550 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
551 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3
554 size_t wxMBConvUTF7::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
560 while (*psz
&& ((!buf
) || (len
< n
)))
563 if (cc
< 0x80 && utf7encode
[cc
] < 1)
571 else if (((wxUint32
)cc
) > 0xffff)
573 // no surrogate pair generation (yet?)
584 // BASE64 encode string
585 unsigned int lsb
, d
, l
;
586 for (d
= 0, l
= 0;; psz
++)
588 for (lsb
= 0; lsb
< 2; lsb
++)
591 d
+= lsb
? cc
& 0xff : (cc
& 0xff00) >> 8;
593 for (l
+= 8; l
>= 6; )
597 *buf
++ = utf7enb64
[(d
>> l
) % 64];
602 if (!(cc
) || (cc
< 0x80 && utf7encode
[cc
] < 1))
608 *buf
++ = utf7enb64
[((d
% 16) << (6 - l
)) % 64];
617 if (buf
&& (len
< n
))
622 // ----------------------------------------------------------------------------
624 // ----------------------------------------------------------------------------
626 static wxUint32 utf8_max
[]=
627 { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff };
629 // boundaries of the private use area we use to (temporarily) remap invalid
630 // characters invalid in a UTF-8 encoded string
631 const wxUint32 wxUnicodePUA
= 0x100000;
632 const wxUint32 wxUnicodePUAEnd
= wxUnicodePUA
+ 256;
634 size_t wxMBConvUTF8::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
638 while (*psz
&& ((!buf
) || (len
< n
)))
640 const char *opsz
= psz
;
641 bool invalid
= false;
642 unsigned char cc
= *psz
++, fc
= cc
;
644 for (cnt
= 0; fc
& 0x80; cnt
++)
653 // escape the escape character for octal escapes
654 if ((m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
655 && cc
== '\\' && (!buf
|| len
< n
))
667 // invalid UTF-8 sequence
672 unsigned ocnt
= cnt
- 1;
673 wxUint32 res
= cc
& (0x3f >> cnt
);
677 if ((cc
& 0xC0) != 0x80)
679 // invalid UTF-8 sequence
684 res
= (res
<< 6) | (cc
& 0x3f);
686 if (invalid
|| res
<= utf8_max
[ocnt
])
688 // illegal UTF-8 encoding
691 else if ((m_options
& MAP_INVALID_UTF8_TO_PUA
) &&
692 res
>= wxUnicodePUA
&& res
< wxUnicodePUAEnd
)
694 // if one of our PUA characters turns up externally
695 // it must also be treated as an illegal sequence
696 // (a bit like you have to escape an escape character)
702 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
703 size_t pa
= encode_utf16(res
, (wxUint16
*)buf
);
704 if (pa
== (size_t)-1)
718 #endif // WC_UTF16/!WC_UTF16
723 if (m_options
& MAP_INVALID_UTF8_TO_PUA
)
725 while (opsz
< psz
&& (!buf
|| len
< n
))
728 // cast is ok because wchar_t == wxUuint16 if WC_UTF16
729 size_t pa
= encode_utf16((unsigned char)*opsz
+ wxUnicodePUA
, (wxUint16
*)buf
);
730 wxASSERT(pa
!= (size_t)-1);
737 *buf
++ = wxUnicodePUA
+ (unsigned char)*opsz
;
743 else if (m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
745 while (opsz
< psz
&& (!buf
|| len
< n
))
747 if ( buf
&& len
+ 3 < n
)
749 unsigned char n
= *opsz
;
751 *buf
++ = (wchar_t)( L
'0' + n
/ 0100 );
752 *buf
++ = (wchar_t)( L
'0' + (n
% 0100) / 010 );
753 *buf
++ = (wchar_t)( L
'0' + n
% 010 );
759 else // MAP_INVALID_UTF8_NOT
766 if (buf
&& (len
< n
))
771 static inline bool isoctal(wchar_t wch
)
773 return L
'0' <= wch
&& wch
<= L
'7';
776 size_t wxMBConvUTF8::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
780 while (*psz
&& ((!buf
) || (len
< n
)))
784 // cast is ok for WC_UTF16
785 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
786 psz
+= (pa
== (size_t)-1) ? 1 : pa
;
788 cc
=(*psz
++) & 0x7fffffff;
791 if ( (m_options
& MAP_INVALID_UTF8_TO_PUA
)
792 && cc
>= wxUnicodePUA
&& cc
< wxUnicodePUAEnd
)
795 *buf
++ = (char)(cc
- wxUnicodePUA
);
798 else if ( (m_options
& MAP_INVALID_UTF8_TO_OCTAL
)
799 && cc
== L
'\\' && psz
[0] == L
'\\' )
806 else if ( (m_options
& MAP_INVALID_UTF8_TO_OCTAL
) &&
808 isoctal(psz
[0]) && isoctal(psz
[1]) && isoctal(psz
[2]) )
812 *buf
++ = (char) ((psz
[0] - L
'0')*0100 +
813 (psz
[1] - L
'0')*010 +
823 for (cnt
= 0; cc
> utf8_max
[cnt
]; cnt
++) {}
837 *buf
++ = (char) ((-128 >> cnt
) | ((cc
>> (cnt
* 6)) & (0x3f >> cnt
)));
839 *buf
++ = (char) (0x80 | ((cc
>> (cnt
* 6)) & 0x3f));
851 // ----------------------------------------------------------------------------
853 // ----------------------------------------------------------------------------
855 #ifdef WORDS_BIGENDIAN
856 #define wxMBConvUTF16straight wxMBConvUTF16BE
857 #define wxMBConvUTF16swap wxMBConvUTF16LE
859 #define wxMBConvUTF16swap wxMBConvUTF16BE
860 #define wxMBConvUTF16straight wxMBConvUTF16LE
866 // copy 16bit MB to 16bit String
867 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
871 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
874 *buf
++ = *(wxUint16
*)psz
;
877 psz
+= sizeof(wxUint16
);
879 if (buf
&& len
<n
) *buf
=0;
885 // copy 16bit String to 16bit MB
886 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
890 while (*psz
&& (!buf
|| len
< n
))
894 *(wxUint16
*)buf
= *psz
;
895 buf
+= sizeof(wxUint16
);
897 len
+= sizeof(wxUint16
);
900 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
906 // swap 16bit MB to 16bit String
907 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
911 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
915 ((char *)buf
)[0] = psz
[1];
916 ((char *)buf
)[1] = psz
[0];
920 psz
+= sizeof(wxUint16
);
922 if (buf
&& len
<n
) *buf
=0;
928 // swap 16bit MB to 16bit String
929 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
933 while (*psz
&& (!buf
|| len
< n
))
937 *buf
++ = ((char*)psz
)[1];
938 *buf
++ = ((char*)psz
)[0];
940 len
+= sizeof(wxUint16
);
943 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
952 // copy 16bit MB to 32bit String
953 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
957 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
960 size_t pa
=decode_utf16((wxUint16
*)psz
, cc
);
961 if (pa
== (size_t)-1)
967 psz
+= pa
* sizeof(wxUint16
);
969 if (buf
&& len
<n
) *buf
=0;
975 // copy 32bit String to 16bit MB
976 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
980 while (*psz
&& (!buf
|| len
< n
))
983 size_t pa
=encode_utf16(*psz
, cc
);
985 if (pa
== (size_t)-1)
990 *(wxUint16
*)buf
= cc
[0];
991 buf
+= sizeof(wxUint16
);
994 *(wxUint16
*)buf
= cc
[1];
995 buf
+= sizeof(wxUint16
);
999 len
+= pa
*sizeof(wxUint16
);
1002 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
1008 // swap 16bit MB to 32bit String
1009 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1013 while (*(wxUint16
*)psz
&& (!buf
|| len
< n
))
1017 tmp
[0]=psz
[1]; tmp
[1]=psz
[0];
1018 tmp
[2]=psz
[3]; tmp
[3]=psz
[2];
1020 size_t pa
=decode_utf16((wxUint16
*)tmp
, cc
);
1021 if (pa
== (size_t)-1)
1028 psz
+= pa
* sizeof(wxUint16
);
1030 if (buf
&& len
<n
) *buf
=0;
1036 // swap 32bit String to 16bit MB
1037 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1041 while (*psz
&& (!buf
|| len
< n
))
1044 size_t pa
=encode_utf16(*psz
, cc
);
1046 if (pa
== (size_t)-1)
1051 *buf
++ = ((char*)cc
)[1];
1052 *buf
++ = ((char*)cc
)[0];
1055 *buf
++ = ((char*)cc
)[3];
1056 *buf
++ = ((char*)cc
)[2];
1060 len
+= pa
*sizeof(wxUint16
);
1063 if (buf
&& len
<=n
-sizeof(wxUint16
)) *(wxUint16
*)buf
=0;
1071 // ----------------------------------------------------------------------------
1073 // ----------------------------------------------------------------------------
1075 #ifdef WORDS_BIGENDIAN
1076 #define wxMBConvUTF32straight wxMBConvUTF32BE
1077 #define wxMBConvUTF32swap wxMBConvUTF32LE
1079 #define wxMBConvUTF32swap wxMBConvUTF32BE
1080 #define wxMBConvUTF32straight wxMBConvUTF32LE
1084 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32LE
) wxConvUTF32LE
;
1085 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32BE
) wxConvUTF32BE
;
1090 // copy 32bit MB to 16bit String
1091 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1095 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1099 size_t pa
=encode_utf16(*(wxUint32
*)psz
, cc
);
1100 if (pa
== (size_t)-1)
1110 psz
+= sizeof(wxUint32
);
1112 if (buf
&& len
<n
) *buf
=0;
1118 // copy 16bit String to 32bit MB
1119 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1123 while (*psz
&& (!buf
|| len
< n
))
1127 // cast is ok for WC_UTF16
1128 size_t pa
= decode_utf16((const wxUint16
*)psz
, cc
);
1129 if (pa
== (size_t)-1)
1134 *(wxUint32
*)buf
= cc
;
1135 buf
+= sizeof(wxUint32
);
1137 len
+= sizeof(wxUint32
);
1141 if (buf
&& len
<=n
-sizeof(wxUint32
))
1149 // swap 32bit MB to 16bit String
1150 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1154 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1157 tmp
[0] = psz
[3]; tmp
[1] = psz
[2];
1158 tmp
[2] = psz
[1]; tmp
[3] = psz
[0];
1163 size_t pa
=encode_utf16(*(wxUint32
*)tmp
, cc
);
1164 if (pa
== (size_t)-1)
1174 psz
+= sizeof(wxUint32
);
1184 // swap 16bit String to 32bit MB
1185 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1189 while (*psz
&& (!buf
|| len
< n
))
1193 // cast is ok for WC_UTF16
1194 size_t pa
=decode_utf16((const wxUint16
*)psz
, *(wxUint32
*)cc
);
1195 if (pa
== (size_t)-1)
1205 len
+= sizeof(wxUint32
);
1209 if (buf
&& len
<=n
-sizeof(wxUint32
))
1218 // copy 32bit MB to 32bit String
1219 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1223 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1226 *buf
++ = *(wxUint32
*)psz
;
1228 psz
+= sizeof(wxUint32
);
1238 // copy 32bit String to 32bit MB
1239 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1243 while (*psz
&& (!buf
|| len
< n
))
1247 *(wxUint32
*)buf
= *psz
;
1248 buf
+= sizeof(wxUint32
);
1251 len
+= sizeof(wxUint32
);
1255 if (buf
&& len
<=n
-sizeof(wxUint32
))
1262 // swap 32bit MB to 32bit String
1263 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1267 while (*(wxUint32
*)psz
&& (!buf
|| len
< n
))
1271 ((char *)buf
)[0] = psz
[3];
1272 ((char *)buf
)[1] = psz
[2];
1273 ((char *)buf
)[2] = psz
[1];
1274 ((char *)buf
)[3] = psz
[0];
1278 psz
+= sizeof(wxUint32
);
1288 // swap 32bit String to 32bit MB
1289 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1293 while (*psz
&& (!buf
|| len
< n
))
1297 *buf
++ = ((char *)psz
)[3];
1298 *buf
++ = ((char *)psz
)[2];
1299 *buf
++ = ((char *)psz
)[1];
1300 *buf
++ = ((char *)psz
)[0];
1302 len
+= sizeof(wxUint32
);
1306 if (buf
&& len
<=n
-sizeof(wxUint32
))
1316 // ============================================================================
1317 // The classes doing conversion using the iconv_xxx() functions
1318 // ============================================================================
1322 // VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with
1323 // E2BIG if output buffer is _exactly_ as big as needed. Such case is
1324 // (unless there's yet another bug in glibc) the only case when iconv()
1325 // returns with (size_t)-1 (which means error) and says there are 0 bytes
1326 // left in the input buffer -- when _real_ error occurs,
1327 // bytes-left-in-input buffer is non-zero. Hence, this alternative test for
1329 // [This bug does not appear in glibc 2.2.]
1330 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1
1331 #define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \
1332 (errno != E2BIG || bufLeft != 0))
1334 #define ICONV_FAILED(cres, bufLeft) (cres == (size_t)-1)
1337 #define ICONV_CHAR_CAST(x) ((ICONV_CONST char **)(x))
1339 // ----------------------------------------------------------------------------
1340 // wxMBConv_iconv: encapsulates an iconv character set
1341 // ----------------------------------------------------------------------------
1343 class wxMBConv_iconv
: public wxMBConv
1346 wxMBConv_iconv(const wxChar
*name
);
1347 virtual ~wxMBConv_iconv();
1349 virtual size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const;
1350 virtual size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const;
1353 { return (m2w
!= (iconv_t
)-1) && (w2m
!= (iconv_t
)-1); }
1356 // the iconv handlers used to translate from multibyte to wide char and in
1357 // the other direction
1361 // guards access to m2w and w2m objects
1362 wxMutex m_iconvMutex
;
1366 // the name (for iconv_open()) of a wide char charset -- if none is
1367 // available on this machine, it will remain NULL
1368 static const char *ms_wcCharsetName
;
1370 // true if the wide char encoding we use (i.e. ms_wcCharsetName) has
1371 // different endian-ness than the native one
1372 static bool ms_wcNeedsSwap
;
1375 const char *wxMBConv_iconv::ms_wcCharsetName
= NULL
;
1376 bool wxMBConv_iconv::ms_wcNeedsSwap
= false;
1378 wxMBConv_iconv::wxMBConv_iconv(const wxChar
*name
)
1380 // Do it the hard way
1382 for (size_t i
= 0; i
< wxStrlen(name
)+1; i
++)
1383 cname
[i
] = (char) name
[i
];
1385 // check for charset that represents wchar_t:
1386 if (ms_wcCharsetName
== NULL
)
1388 ms_wcNeedsSwap
= false;
1390 // try charset with explicit bytesex info (e.g. "UCS-4LE"):
1391 ms_wcCharsetName
= WC_NAME_BEST
;
1392 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1394 if (m2w
== (iconv_t
)-1)
1396 // try charset w/o bytesex info (e.g. "UCS4")
1397 // and check for bytesex ourselves:
1398 ms_wcCharsetName
= WC_NAME
;
1399 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1401 // last bet, try if it knows WCHAR_T pseudo-charset
1402 if (m2w
== (iconv_t
)-1)
1404 ms_wcCharsetName
= "WCHAR_T";
1405 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1408 if (m2w
!= (iconv_t
)-1)
1410 char buf
[2], *bufPtr
;
1411 wchar_t wbuf
[2], *wbufPtr
;
1419 outsz
= SIZEOF_WCHAR_T
* 2;
1423 res
= iconv(m2w
, ICONV_CHAR_CAST(&bufPtr
), &insz
,
1424 (char**)&wbufPtr
, &outsz
);
1426 if (ICONV_FAILED(res
, insz
))
1428 ms_wcCharsetName
= NULL
;
1429 wxLogLastError(wxT("iconv"));
1430 wxLogError(_("Conversion to charset '%s' doesn't work."), name
);
1434 ms_wcNeedsSwap
= wbuf
[0] != (wchar_t)buf
[0];
1439 ms_wcCharsetName
= NULL
;
1441 // VS: we must not output an error here, since wxWidgets will safely
1442 // fall back to using wxEncodingConverter.
1443 wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name
);
1447 wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName
, ms_wcNeedsSwap
);
1449 else // we already have ms_wcCharsetName
1451 m2w
= iconv_open(ms_wcCharsetName
, cname
);
1454 // NB: don't ever pass NULL to iconv_open(), it may crash!
1455 if ( ms_wcCharsetName
)
1457 w2m
= iconv_open( cname
, ms_wcCharsetName
);
1465 wxMBConv_iconv::~wxMBConv_iconv()
1467 if ( m2w
!= (iconv_t
)-1 )
1469 if ( w2m
!= (iconv_t
)-1 )
1473 size_t wxMBConv_iconv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1476 // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle.
1477 // Unfortunately there is a couple of global wxCSConv objects such as
1478 // wxConvLocal that are used all over wx code, so we have to make sure
1479 // the handle is used by at most one thread at the time. Otherwise
1480 // only a few wx classes would be safe to use from non-main threads
1481 // as MB<->WC conversion would fail "randomly".
1482 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1485 size_t inbuf
= strlen(psz
);
1486 size_t outbuf
= n
* SIZEOF_WCHAR_T
;
1488 // VS: Use these instead of psz, buf because iconv() modifies its arguments:
1489 wchar_t *bufPtr
= buf
;
1490 const char *pszPtr
= psz
;
1494 // have destination buffer, convert there
1496 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1497 (char**)&bufPtr
, &outbuf
);
1498 res
= n
- (outbuf
/ SIZEOF_WCHAR_T
);
1502 // convert to native endianness
1503 WC_BSWAP(buf
/* _not_ bufPtr */, res
)
1506 // NB: iconv was given only strlen(psz) characters on input, and so
1507 // it couldn't convert the trailing zero. Let's do it ourselves
1508 // if there's some room left for it in the output buffer.
1514 // no destination buffer... convert using temp buffer
1515 // to calculate destination buffer requirement
1520 outbuf
= 8*SIZEOF_WCHAR_T
;
1523 ICONV_CHAR_CAST(&pszPtr
), &inbuf
,
1524 (char**)&bufPtr
, &outbuf
);
1526 res
+= 8-(outbuf
/SIZEOF_WCHAR_T
);
1527 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1530 if (ICONV_FAILED(cres
, inbuf
))
1532 //VS: it is ok if iconv fails, hence trace only
1533 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1540 size_t wxMBConv_iconv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
1543 // NB: explained in MB2WC
1544 wxMutexLocker
lock(wxConstCast(this, wxMBConv_iconv
)->m_iconvMutex
);
1547 size_t inbuf
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
1551 wchar_t *tmpbuf
= 0;
1555 // need to copy to temp buffer to switch endianness
1556 // this absolutely doesn't rock!
1557 // (no, doing WC_BSWAP twice on the original buffer won't help, as it
1558 // could be in read-only memory, or be accessed in some other thread)
1559 tmpbuf
=(wchar_t*)malloc((inbuf
+1)*SIZEOF_WCHAR_T
);
1560 memcpy(tmpbuf
,psz
,(inbuf
+1)*SIZEOF_WCHAR_T
);
1561 WC_BSWAP(tmpbuf
, inbuf
)
1567 // have destination buffer, convert there
1568 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1572 // NB: iconv was given only wcslen(psz) characters on input, and so
1573 // it couldn't convert the trailing zero. Let's do it ourselves
1574 // if there's some room left for it in the output buffer.
1580 // no destination buffer... convert using temp buffer
1581 // to calculate destination buffer requirement
1585 buf
= tbuf
; outbuf
= 16;
1587 cres
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf
);
1590 } while ((cres
==(size_t)-1) && (errno
==E2BIG
));
1598 if (ICONV_FAILED(cres
, inbuf
))
1600 //VS: it is ok if iconv fails, hence trace only
1601 wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode()));
1608 #endif // HAVE_ICONV
1611 // ============================================================================
1612 // Win32 conversion classes
1613 // ============================================================================
1615 #ifdef wxHAVE_WIN32_MB2WC
1619 extern WXDLLIMPEXP_BASE
long wxCharsetToCodepage(const wxChar
*charset
);
1620 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
);
1623 class wxMBConv_win32
: public wxMBConv
1628 m_CodePage
= CP_ACP
;
1632 wxMBConv_win32(const wxChar
* name
)
1634 m_CodePage
= wxCharsetToCodepage(name
);
1637 wxMBConv_win32(wxFontEncoding encoding
)
1639 m_CodePage
= wxEncodingToCodepage(encoding
);
1643 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
1645 // note that we have to use MB_ERR_INVALID_CHARS flag as it without it
1646 // the behaviour is not compatible with the Unix version (using iconv)
1647 // and break the library itself, e.g. wxTextInputStream::NextChar()
1648 // wouldn't work if reading an incomplete MB char didn't result in an
1651 // note however that using MB_ERR_INVALID_CHARS with CP_UTF7 results in
1652 // an error (tested under Windows Server 2003) and apparently it is
1653 // done on purpose, i.e. the function accepts any input in this case
1654 // and although I'd prefer to return error on ill-formed output, our
1655 // own wxMBConvUTF7 doesn't detect errors (e.g. lone "+" which is
1656 // explicitly ill-formed according to RFC 2152) neither so we don't
1657 // even have any fallback here...
1658 int flags
= m_CodePage
== CP_UTF7
? 0 : MB_ERR_INVALID_CHARS
;
1660 const size_t len
= ::MultiByteToWideChar
1662 m_CodePage
, // code page
1663 flags
, // flags: fall on error
1664 psz
, // input string
1665 -1, // its length (NUL-terminated)
1666 buf
, // output string
1667 buf
? n
: 0 // size of output buffer
1670 // note that it returns count of written chars for buf != NULL and size
1671 // of the needed buffer for buf == NULL so in either case the length of
1672 // the string (which never includes the terminating NUL) is one less
1673 return len
? len
- 1 : (size_t)-1;
1676 size_t WC2MB(char *buf
, const wchar_t *pwz
, size_t n
) const
1679 we have a problem here: by default, WideCharToMultiByte() may
1680 replace characters unrepresentable in the target code page with bad
1681 quality approximations such as turning "1/2" symbol (U+00BD) into
1682 "1" for the code pages which don't have it and we, obviously, want
1683 to avoid this at any price
1685 the trouble is that this function does it _silently_, i.e. it won't
1686 even tell us whether it did or not... Win98/2000 and higher provide
1687 WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and
1688 we have to resort to a round trip, i.e. check that converting back
1689 results in the same string -- this is, of course, expensive but
1690 otherwise we simply can't be sure to not garble the data.
1693 // determine if we can rely on WC_NO_BEST_FIT_CHARS: according to MSDN
1694 // it doesn't work with CJK encodings (which we test for rather roughly
1695 // here...) nor with UTF-7/8 nor, of course, with Windows versions not
1697 BOOL usedDef
wxDUMMY_INITIALIZE(false);
1700 if ( CanUseNoBestFit() && m_CodePage
< 50000 )
1702 // it's our lucky day
1703 flags
= WC_NO_BEST_FIT_CHARS
;
1704 pUsedDef
= &usedDef
;
1706 else // old system or unsupported encoding
1712 const size_t len
= ::WideCharToMultiByte
1714 m_CodePage
, // code page
1715 flags
, // either none or no best fit
1716 pwz
, // input string
1717 -1, // it is (wide) NUL-terminated
1718 buf
, // output buffer
1719 buf
? n
: 0, // and its size
1720 NULL
, // default "replacement" char
1721 pUsedDef
// [out] was it used?
1726 // function totally failed
1730 // if we were really converting, check if we succeeded
1735 // check if the conversion failed, i.e. if any replacements
1740 else // we must resort to double tripping...
1742 wxWCharBuffer
wcBuf(n
);
1743 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
1744 wcscmp(wcBuf
, pwz
) != 0 )
1746 // we didn't obtain the same thing we started from, hence
1747 // the conversion was lossy and we consider that it failed
1753 // see the comment above for the reason of "len - 1"
1757 bool IsOk() const { return m_CodePage
!= -1; }
1760 static bool CanUseNoBestFit()
1762 static int s_isWin98Or2k
= -1;
1764 if ( s_isWin98Or2k
== -1 )
1767 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1770 s_isWin98Or2k
= verMaj
>= 4 && verMin
>= 10;
1774 s_isWin98Or2k
= verMaj
>= 5;
1778 // unknown, be conseravtive by default
1782 wxASSERT_MSG( s_isWin98Or2k
!= -1, _T("should be set above") );
1785 return s_isWin98Or2k
== 1;
1791 #endif // wxHAVE_WIN32_MB2WC
1793 // ============================================================================
1794 // Cocoa conversion classes
1795 // ============================================================================
1797 #if defined(__WXCOCOA__)
1799 // RN: There is no UTF-32 support in either Core Foundation or
1800 // Cocoa. Strangely enough, internally Core Foundation uses
1801 // UTF 32 internally quite a bit - its just not public (yet).
1803 #include <CoreFoundation/CFString.h>
1804 #include <CoreFoundation/CFStringEncodingExt.h>
1806 CFStringEncoding
wxCFStringEncFromFontEnc(wxFontEncoding encoding
)
1808 CFStringEncoding enc
= kCFStringEncodingInvalidId
;
1809 if ( encoding
== wxFONTENCODING_DEFAULT
)
1811 enc
= CFStringGetSystemEncoding();
1813 else switch( encoding
)
1815 case wxFONTENCODING_ISO8859_1
:
1816 enc
= kCFStringEncodingISOLatin1
;
1818 case wxFONTENCODING_ISO8859_2
:
1819 enc
= kCFStringEncodingISOLatin2
;
1821 case wxFONTENCODING_ISO8859_3
:
1822 enc
= kCFStringEncodingISOLatin3
;
1824 case wxFONTENCODING_ISO8859_4
:
1825 enc
= kCFStringEncodingISOLatin4
;
1827 case wxFONTENCODING_ISO8859_5
:
1828 enc
= kCFStringEncodingISOLatinCyrillic
;
1830 case wxFONTENCODING_ISO8859_6
:
1831 enc
= kCFStringEncodingISOLatinArabic
;
1833 case wxFONTENCODING_ISO8859_7
:
1834 enc
= kCFStringEncodingISOLatinGreek
;
1836 case wxFONTENCODING_ISO8859_8
:
1837 enc
= kCFStringEncodingISOLatinHebrew
;
1839 case wxFONTENCODING_ISO8859_9
:
1840 enc
= kCFStringEncodingISOLatin5
;
1842 case wxFONTENCODING_ISO8859_10
:
1843 enc
= kCFStringEncodingISOLatin6
;
1845 case wxFONTENCODING_ISO8859_11
:
1846 enc
= kCFStringEncodingISOLatinThai
;
1848 case wxFONTENCODING_ISO8859_13
:
1849 enc
= kCFStringEncodingISOLatin7
;
1851 case wxFONTENCODING_ISO8859_14
:
1852 enc
= kCFStringEncodingISOLatin8
;
1854 case wxFONTENCODING_ISO8859_15
:
1855 enc
= kCFStringEncodingISOLatin9
;
1858 case wxFONTENCODING_KOI8
:
1859 enc
= kCFStringEncodingKOI8_R
;
1861 case wxFONTENCODING_ALTERNATIVE
: // MS-DOS CP866
1862 enc
= kCFStringEncodingDOSRussian
;
1865 // case wxFONTENCODING_BULGARIAN :
1869 case wxFONTENCODING_CP437
:
1870 enc
=kCFStringEncodingDOSLatinUS
;
1872 case wxFONTENCODING_CP850
:
1873 enc
= kCFStringEncodingDOSLatin1
;
1875 case wxFONTENCODING_CP852
:
1876 enc
= kCFStringEncodingDOSLatin2
;
1878 case wxFONTENCODING_CP855
:
1879 enc
= kCFStringEncodingDOSCyrillic
;
1881 case wxFONTENCODING_CP866
:
1882 enc
=kCFStringEncodingDOSRussian
;
1884 case wxFONTENCODING_CP874
:
1885 enc
= kCFStringEncodingDOSThai
;
1887 case wxFONTENCODING_CP932
:
1888 enc
= kCFStringEncodingDOSJapanese
;
1890 case wxFONTENCODING_CP936
:
1891 enc
=kCFStringEncodingDOSChineseSimplif
;
1893 case wxFONTENCODING_CP949
:
1894 enc
= kCFStringEncodingDOSKorean
;
1896 case wxFONTENCODING_CP950
:
1897 enc
= kCFStringEncodingDOSChineseTrad
;
1899 case wxFONTENCODING_CP1250
:
1900 enc
= kCFStringEncodingWindowsLatin2
;
1902 case wxFONTENCODING_CP1251
:
1903 enc
=kCFStringEncodingWindowsCyrillic
;
1905 case wxFONTENCODING_CP1252
:
1906 enc
=kCFStringEncodingWindowsLatin1
;
1908 case wxFONTENCODING_CP1253
:
1909 enc
= kCFStringEncodingWindowsGreek
;
1911 case wxFONTENCODING_CP1254
:
1912 enc
= kCFStringEncodingWindowsLatin5
;
1914 case wxFONTENCODING_CP1255
:
1915 enc
=kCFStringEncodingWindowsHebrew
;
1917 case wxFONTENCODING_CP1256
:
1918 enc
=kCFStringEncodingWindowsArabic
;
1920 case wxFONTENCODING_CP1257
:
1921 enc
= kCFStringEncodingWindowsBalticRim
;
1923 // This only really encodes to UTF7 (if that) evidently
1924 // case wxFONTENCODING_UTF7 :
1925 // enc = kCFStringEncodingNonLossyASCII ;
1927 case wxFONTENCODING_UTF8
:
1928 enc
= kCFStringEncodingUTF8
;
1930 case wxFONTENCODING_EUC_JP
:
1931 enc
= kCFStringEncodingEUC_JP
;
1933 case wxFONTENCODING_UTF16
:
1934 enc
= kCFStringEncodingUnicode
;
1936 case wxFONTENCODING_MACROMAN
:
1937 enc
= kCFStringEncodingMacRoman
;
1939 case wxFONTENCODING_MACJAPANESE
:
1940 enc
= kCFStringEncodingMacJapanese
;
1942 case wxFONTENCODING_MACCHINESETRAD
:
1943 enc
= kCFStringEncodingMacChineseTrad
;
1945 case wxFONTENCODING_MACKOREAN
:
1946 enc
= kCFStringEncodingMacKorean
;
1948 case wxFONTENCODING_MACARABIC
:
1949 enc
= kCFStringEncodingMacArabic
;
1951 case wxFONTENCODING_MACHEBREW
:
1952 enc
= kCFStringEncodingMacHebrew
;
1954 case wxFONTENCODING_MACGREEK
:
1955 enc
= kCFStringEncodingMacGreek
;
1957 case wxFONTENCODING_MACCYRILLIC
:
1958 enc
= kCFStringEncodingMacCyrillic
;
1960 case wxFONTENCODING_MACDEVANAGARI
:
1961 enc
= kCFStringEncodingMacDevanagari
;
1963 case wxFONTENCODING_MACGURMUKHI
:
1964 enc
= kCFStringEncodingMacGurmukhi
;
1966 case wxFONTENCODING_MACGUJARATI
:
1967 enc
= kCFStringEncodingMacGujarati
;
1969 case wxFONTENCODING_MACORIYA
:
1970 enc
= kCFStringEncodingMacOriya
;
1972 case wxFONTENCODING_MACBENGALI
:
1973 enc
= kCFStringEncodingMacBengali
;
1975 case wxFONTENCODING_MACTAMIL
:
1976 enc
= kCFStringEncodingMacTamil
;
1978 case wxFONTENCODING_MACTELUGU
:
1979 enc
= kCFStringEncodingMacTelugu
;
1981 case wxFONTENCODING_MACKANNADA
:
1982 enc
= kCFStringEncodingMacKannada
;
1984 case wxFONTENCODING_MACMALAJALAM
:
1985 enc
= kCFStringEncodingMacMalayalam
;
1987 case wxFONTENCODING_MACSINHALESE
:
1988 enc
= kCFStringEncodingMacSinhalese
;
1990 case wxFONTENCODING_MACBURMESE
:
1991 enc
= kCFStringEncodingMacBurmese
;
1993 case wxFONTENCODING_MACKHMER
:
1994 enc
= kCFStringEncodingMacKhmer
;
1996 case wxFONTENCODING_MACTHAI
:
1997 enc
= kCFStringEncodingMacThai
;
1999 case wxFONTENCODING_MACLAOTIAN
:
2000 enc
= kCFStringEncodingMacLaotian
;
2002 case wxFONTENCODING_MACGEORGIAN
:
2003 enc
= kCFStringEncodingMacGeorgian
;
2005 case wxFONTENCODING_MACARMENIAN
:
2006 enc
= kCFStringEncodingMacArmenian
;
2008 case wxFONTENCODING_MACCHINESESIMP
:
2009 enc
= kCFStringEncodingMacChineseSimp
;
2011 case wxFONTENCODING_MACTIBETAN
:
2012 enc
= kCFStringEncodingMacTibetan
;
2014 case wxFONTENCODING_MACMONGOLIAN
:
2015 enc
= kCFStringEncodingMacMongolian
;
2017 case wxFONTENCODING_MACETHIOPIC
:
2018 enc
= kCFStringEncodingMacEthiopic
;
2020 case wxFONTENCODING_MACCENTRALEUR
:
2021 enc
= kCFStringEncodingMacCentralEurRoman
;
2023 case wxFONTENCODING_MACVIATNAMESE
:
2024 enc
= kCFStringEncodingMacVietnamese
;
2026 case wxFONTENCODING_MACARABICEXT
:
2027 enc
= kCFStringEncodingMacExtArabic
;
2029 case wxFONTENCODING_MACSYMBOL
:
2030 enc
= kCFStringEncodingMacSymbol
;
2032 case wxFONTENCODING_MACDINGBATS
:
2033 enc
= kCFStringEncodingMacDingbats
;
2035 case wxFONTENCODING_MACTURKISH
:
2036 enc
= kCFStringEncodingMacTurkish
;
2038 case wxFONTENCODING_MACCROATIAN
:
2039 enc
= kCFStringEncodingMacCroatian
;
2041 case wxFONTENCODING_MACICELANDIC
:
2042 enc
= kCFStringEncodingMacIcelandic
;
2044 case wxFONTENCODING_MACROMANIAN
:
2045 enc
= kCFStringEncodingMacRomanian
;
2047 case wxFONTENCODING_MACCELTIC
:
2048 enc
= kCFStringEncodingMacCeltic
;
2050 case wxFONTENCODING_MACGAELIC
:
2051 enc
= kCFStringEncodingMacGaelic
;
2053 // case wxFONTENCODING_MACKEYBOARD :
2054 // enc = kCFStringEncodingMacKeyboardGlyphs ;
2057 // because gcc is picky
2063 class wxMBConv_cocoa
: public wxMBConv
2068 Init(CFStringGetSystemEncoding()) ;
2072 wxMBConv_cocoa(const wxChar
* name
)
2074 Init( wxCFStringEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2078 wxMBConv_cocoa(wxFontEncoding encoding
)
2080 Init( wxCFStringEncFromFontEnc(encoding
) );
2087 void Init( CFStringEncoding encoding
)
2089 m_encoding
= encoding
;
2092 size_t MB2WC(wchar_t * szOut
, const char * szUnConv
, size_t nOutSize
) const
2096 CFStringRef theString
= CFStringCreateWithBytes (
2097 NULL
, //the allocator
2098 (const UInt8
*)szUnConv
,
2101 false //no BOM/external representation
2104 wxASSERT(theString
);
2106 size_t nOutLength
= CFStringGetLength(theString
);
2110 CFRelease(theString
);
2114 CFRange theRange
= { 0, nOutSize
};
2116 #if SIZEOF_WCHAR_T == 4
2117 UniChar
* szUniCharBuffer
= new UniChar
[nOutSize
];
2120 CFStringGetCharacters(theString
, theRange
, szUniCharBuffer
);
2122 CFRelease(theString
);
2124 szUniCharBuffer
[nOutLength
] = '\0' ;
2126 #if SIZEOF_WCHAR_T == 4
2127 wxMBConvUTF16 converter
;
2128 converter
.MB2WC(szOut
, (const char*)szUniCharBuffer
, nOutSize
) ;
2129 delete[] szUniCharBuffer
;
2135 size_t WC2MB(char *szOut
, const wchar_t *szUnConv
, size_t nOutSize
) const
2139 size_t nRealOutSize
;
2140 size_t nBufSize
= wxWcslen(szUnConv
);
2141 UniChar
* szUniBuffer
= (UniChar
*) szUnConv
;
2143 #if SIZEOF_WCHAR_T == 4
2144 wxMBConvUTF16BE converter
;
2145 nBufSize
= converter
.WC2MB( NULL
, szUnConv
, 0 );
2146 szUniBuffer
= new UniChar
[ (nBufSize
/ sizeof(UniChar
)) + 1] ;
2147 converter
.WC2MB( (char*) szUniBuffer
, szUnConv
, nBufSize
+ sizeof(UniChar
)) ;
2148 nBufSize
/= sizeof(UniChar
);
2151 CFStringRef theString
= CFStringCreateWithCharactersNoCopy(
2155 kCFAllocatorNull
//deallocator - we want to deallocate it ourselves
2158 wxASSERT(theString
);
2160 //Note that CER puts a BOM when converting to unicode
2161 //so we check and use getchars instead in that case
2162 if (m_encoding
== kCFStringEncodingUnicode
)
2165 CFStringGetCharacters(theString
, CFRangeMake(0, nOutSize
- 1), (UniChar
*) szOut
);
2167 nRealOutSize
= CFStringGetLength(theString
) + 1;
2173 CFRangeMake(0, CFStringGetLength(theString
)),
2175 0, //what to put in characters that can't be converted -
2176 //0 tells CFString to return NULL if it meets such a character
2177 false, //not an external representation
2180 (CFIndex
*) &nRealOutSize
2184 CFRelease(theString
);
2186 #if SIZEOF_WCHAR_T == 4
2187 delete[] szUniBuffer
;
2190 return nRealOutSize
- 1;
2195 return m_encoding
!= kCFStringEncodingInvalidId
&&
2196 CFStringIsEncodingAvailable(m_encoding
);
2200 CFStringEncoding m_encoding
;
2203 #endif // defined(__WXCOCOA__)
2205 // ============================================================================
2206 // Mac conversion classes
2207 // ============================================================================
2209 #if defined(__WXMAC__) && defined(TARGET_CARBON)
2211 class wxMBConv_mac
: public wxMBConv
2216 Init(CFStringGetSystemEncoding()) ;
2220 wxMBConv_mac(const wxChar
* name
)
2222 Init( wxMacGetSystemEncFromFontEnc(wxFontMapperBase::Get()->CharsetToEncoding(name
, false) ) ) ;
2226 wxMBConv_mac(wxFontEncoding encoding
)
2228 Init( wxMacGetSystemEncFromFontEnc(encoding
) );
2233 OSStatus status
= noErr
;
2234 status
= TECDisposeConverter(m_MB2WC_converter
);
2235 status
= TECDisposeConverter(m_WC2MB_converter
);
2239 void Init( TextEncodingBase encoding
)
2241 OSStatus status
= noErr
;
2242 m_char_encoding
= encoding
;
2243 m_unicode_encoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ;
2245 status
= TECCreateConverter(&m_MB2WC_converter
,
2247 m_unicode_encoding
);
2248 status
= TECCreateConverter(&m_WC2MB_converter
,
2253 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2255 OSStatus status
= noErr
;
2256 ByteCount byteOutLen
;
2257 ByteCount byteInLen
= strlen(psz
) ;
2258 wchar_t *tbuf
= NULL
;
2259 UniChar
* ubuf
= NULL
;
2264 //apple specs say at least 32
2265 n
= wxMax( 32 , byteInLen
) ;
2266 tbuf
= (wchar_t*) malloc( n
* SIZEOF_WCHAR_T
) ;
2268 ByteCount byteBufferLen
= n
* sizeof( UniChar
) ;
2269 #if SIZEOF_WCHAR_T == 4
2270 ubuf
= (UniChar
*) malloc( byteBufferLen
+ 2 ) ;
2272 ubuf
= (UniChar
*) (buf
? buf
: tbuf
) ;
2274 status
= TECConvertText(m_MB2WC_converter
, (ConstTextPtr
) psz
, byteInLen
, &byteInLen
,
2275 (TextPtr
) ubuf
, byteBufferLen
, &byteOutLen
);
2276 #if SIZEOF_WCHAR_T == 4
2277 // we have to terminate here, because n might be larger for the trailing zero, and if UniChar
2278 // is not properly terminated we get random characters at the end
2279 ubuf
[byteOutLen
/ sizeof( UniChar
) ] = 0 ;
2280 wxMBConvUTF16BE converter
;
2281 res
= converter
.MB2WC( (buf
? buf
: tbuf
) , (const char*)ubuf
, n
) ;
2284 res
= byteOutLen
/ sizeof( UniChar
) ;
2289 if ( buf
&& res
< n
)
2295 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2297 OSStatus status
= noErr
;
2298 ByteCount byteOutLen
;
2299 ByteCount byteInLen
= wxWcslen(psz
) * SIZEOF_WCHAR_T
;
2305 //apple specs say at least 32
2306 n
= wxMax( 32 , ((byteInLen
/ SIZEOF_WCHAR_T
) * 8) + SIZEOF_WCHAR_T
);
2307 tbuf
= (char*) malloc( n
) ;
2310 ByteCount byteBufferLen
= n
;
2311 UniChar
* ubuf
= NULL
;
2312 #if SIZEOF_WCHAR_T == 4
2313 wxMBConvUTF16BE converter
;
2314 size_t unicharlen
= converter
.WC2MB( NULL
, psz
, 0 ) ;
2315 byteInLen
= unicharlen
;
2316 ubuf
= (UniChar
*) malloc( byteInLen
+ 2 ) ;
2317 converter
.WC2MB( (char*) ubuf
, psz
, unicharlen
+ 2 ) ;
2319 ubuf
= (UniChar
*) psz
;
2321 status
= TECConvertText(m_WC2MB_converter
, (ConstTextPtr
) ubuf
, byteInLen
, &byteInLen
,
2322 (TextPtr
) (buf
? buf
: tbuf
) , byteBufferLen
, &byteOutLen
);
2323 #if SIZEOF_WCHAR_T == 4
2329 size_t res
= byteOutLen
;
2330 if ( buf
&& res
< n
)
2334 //we need to double-trip to verify it didn't insert any ? in place
2335 //of bogus characters
2336 wxWCharBuffer
wcBuf(n
);
2337 size_t pszlen
= wxWcslen(psz
);
2338 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 ||
2339 wxWcslen(wcBuf
) != pszlen
||
2340 memcmp(wcBuf
, psz
, pszlen
* sizeof(wchar_t)) != 0 )
2342 // we didn't obtain the same thing we started from, hence
2343 // the conversion was lossy and we consider that it failed
2352 { return m_MB2WC_converter
!= NULL
&& m_WC2MB_converter
!= NULL
; }
2355 TECObjectRef m_MB2WC_converter
;
2356 TECObjectRef m_WC2MB_converter
;
2358 TextEncodingBase m_char_encoding
;
2359 TextEncodingBase m_unicode_encoding
;
2362 #endif // defined(__WXMAC__) && defined(TARGET_CARBON)
2364 // ============================================================================
2365 // wxEncodingConverter based conversion classes
2366 // ============================================================================
2370 class wxMBConv_wxwin
: public wxMBConv
2375 m_ok
= m2w
.Init(m_enc
, wxFONTENCODING_UNICODE
) &&
2376 w2m
.Init(wxFONTENCODING_UNICODE
, m_enc
);
2380 // temporarily just use wxEncodingConverter stuff,
2381 // so that it works while a better implementation is built
2382 wxMBConv_wxwin(const wxChar
* name
)
2385 m_enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
2387 m_enc
= wxFONTENCODING_SYSTEM
;
2392 wxMBConv_wxwin(wxFontEncoding enc
)
2399 size_t MB2WC(wchar_t *buf
, const char *psz
, size_t WXUNUSED(n
)) const
2401 size_t inbuf
= strlen(psz
);
2404 if (!m2w
.Convert(psz
,buf
))
2410 size_t WC2MB(char *buf
, const wchar_t *psz
, size_t WXUNUSED(n
)) const
2412 const size_t inbuf
= wxWcslen(psz
);
2415 if (!w2m
.Convert(psz
,buf
))
2422 bool IsOk() const { return m_ok
; }
2425 wxFontEncoding m_enc
;
2426 wxEncodingConverter m2w
, w2m
;
2428 // were we initialized successfully?
2431 DECLARE_NO_COPY_CLASS(wxMBConv_wxwin
)
2434 #endif // wxUSE_FONTMAP
2436 // ============================================================================
2437 // wxCSConv implementation
2438 // ============================================================================
2440 void wxCSConv::Init()
2447 wxCSConv::wxCSConv(const wxChar
*charset
)
2456 m_encoding
= wxFONTENCODING_SYSTEM
;
2459 wxCSConv::wxCSConv(wxFontEncoding encoding
)
2461 if ( encoding
== wxFONTENCODING_MAX
|| encoding
== wxFONTENCODING_DEFAULT
)
2463 wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
2465 encoding
= wxFONTENCODING_SYSTEM
;
2470 m_encoding
= encoding
;
2473 wxCSConv::~wxCSConv()
2478 wxCSConv::wxCSConv(const wxCSConv
& conv
)
2483 SetName(conv
.m_name
);
2484 m_encoding
= conv
.m_encoding
;
2487 wxCSConv
& wxCSConv::operator=(const wxCSConv
& conv
)
2491 SetName(conv
.m_name
);
2492 m_encoding
= conv
.m_encoding
;
2497 void wxCSConv::Clear()
2506 void wxCSConv::SetName(const wxChar
*charset
)
2510 m_name
= wxStrdup(charset
);
2515 wxMBConv
*wxCSConv::DoCreate() const
2517 // check for the special case of ASCII or ISO8859-1 charset: as we have
2518 // special knowledge of it anyhow, we don't need to create a special
2519 // conversion object
2520 if ( m_encoding
== wxFONTENCODING_ISO8859_1
)
2522 // don't convert at all
2526 // we trust OS to do conversion better than we can so try external
2527 // conversion methods first
2529 // the full order is:
2530 // 1. OS conversion (iconv() under Unix or Win32 API)
2531 // 2. hard coded conversions for UTF
2532 // 3. wxEncodingConverter as fall back
2538 #endif // !wxUSE_FONTMAP
2540 wxString
name(m_name
);
2544 name
= wxFontMapperBase::Get()->GetEncodingName(m_encoding
);
2545 #endif // wxUSE_FONTMAP
2547 wxMBConv_iconv
*conv
= new wxMBConv_iconv(name
);
2553 #endif // HAVE_ICONV
2555 #ifdef wxHAVE_WIN32_MB2WC
2558 wxMBConv_win32
*conv
= m_name
? new wxMBConv_win32(m_name
)
2559 : new wxMBConv_win32(m_encoding
);
2568 #endif // wxHAVE_WIN32_MB2WC
2569 #if defined(__WXMAC__)
2571 // leave UTF16 and UTF32 to the built-ins of wx
2572 if ( m_name
|| ( m_encoding
< wxFONTENCODING_UTF16BE
||
2573 ( m_encoding
>= wxFONTENCODING_MACMIN
&& m_encoding
<= wxFONTENCODING_MACMAX
) ) )
2577 wxMBConv_mac
*conv
= m_name
? new wxMBConv_mac(m_name
)
2578 : new wxMBConv_mac(m_encoding
);
2580 wxMBConv_mac
*conv
= new wxMBConv_mac(m_encoding
);
2589 #if defined(__WXCOCOA__)
2591 if ( m_name
|| ( m_encoding
<= wxFONTENCODING_UTF16
) )
2595 wxMBConv_cocoa
*conv
= m_name
? new wxMBConv_cocoa(m_name
)
2596 : new wxMBConv_cocoa(m_encoding
);
2598 wxMBConv_cocoa
*conv
= new wxMBConv_cocoa(m_encoding
);
2608 wxFontEncoding enc
= m_encoding
;
2610 if ( enc
== wxFONTENCODING_SYSTEM
&& m_name
)
2612 // use "false" to suppress interactive dialogs -- we can be called from
2613 // anywhere and popping up a dialog from here is the last thing we want to
2615 enc
= wxFontMapperBase::Get()->CharsetToEncoding(m_name
, false);
2617 #endif // wxUSE_FONTMAP
2621 case wxFONTENCODING_UTF7
:
2622 return new wxMBConvUTF7
;
2624 case wxFONTENCODING_UTF8
:
2625 return new wxMBConvUTF8
;
2627 case wxFONTENCODING_UTF16BE
:
2628 return new wxMBConvUTF16BE
;
2630 case wxFONTENCODING_UTF16LE
:
2631 return new wxMBConvUTF16LE
;
2633 case wxFONTENCODING_UTF32BE
:
2634 return new wxMBConvUTF32BE
;
2636 case wxFONTENCODING_UTF32LE
:
2637 return new wxMBConvUTF32LE
;
2640 // nothing to do but put here to suppress gcc warnings
2647 wxMBConv_wxwin
*conv
= m_name
? new wxMBConv_wxwin(m_name
)
2648 : new wxMBConv_wxwin(m_encoding
);
2654 #endif // wxUSE_FONTMAP
2656 // NB: This is a hack to prevent deadlock. What could otherwise happen
2657 // in Unicode build: wxConvLocal creation ends up being here
2658 // because of some failure and logs the error. But wxLog will try to
2659 // attach timestamp, for which it will need wxConvLocal (to convert
2660 // time to char* and then wchar_t*), but that fails, tries to log
2661 // error, but wxLog has a (already locked) critical section that
2662 // guards static buffer.
2663 static bool alreadyLoggingError
= false;
2664 if (!alreadyLoggingError
)
2666 alreadyLoggingError
= true;
2667 wxLogError(_("Cannot convert from the charset '%s'!"),
2671 wxFontMapperBase::GetEncodingDescription(m_encoding
).c_str()
2672 #else // !wxUSE_FONTMAP
2673 wxString::Format(_("encoding %s"), m_encoding
).c_str()
2674 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
2676 alreadyLoggingError
= false;
2682 void wxCSConv::CreateConvIfNeeded() const
2686 wxCSConv
*self
= (wxCSConv
*)this; // const_cast
2689 // if we don't have neither the name nor the encoding, use the default
2690 // encoding for this system
2691 if ( !m_name
&& m_encoding
== wxFONTENCODING_SYSTEM
)
2693 self
->m_name
= wxStrdup(wxLocale::GetSystemEncodingName());
2695 #endif // wxUSE_INTL
2697 self
->m_convReal
= DoCreate();
2698 self
->m_deferred
= false;
2702 size_t wxCSConv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const
2704 CreateConvIfNeeded();
2707 return m_convReal
->MB2WC(buf
, psz
, n
);
2710 size_t len
= strlen(psz
);
2714 for (size_t c
= 0; c
<= len
; c
++)
2715 buf
[c
] = (unsigned char)(psz
[c
]);
2721 size_t wxCSConv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const
2723 CreateConvIfNeeded();
2726 return m_convReal
->WC2MB(buf
, psz
, n
);
2729 const size_t len
= wxWcslen(psz
);
2732 for (size_t c
= 0; c
<= len
; c
++)
2736 buf
[c
] = (char)psz
[c
];
2741 for (size_t c
= 0; c
<= len
; c
++)
2751 // ----------------------------------------------------------------------------
2753 // ----------------------------------------------------------------------------
2756 static wxMBConv_win32 wxConvLibcObj
;
2757 #elif defined(__WXMAC__) && !defined(__MACH__)
2758 static wxMBConv_mac wxConvLibcObj
;
2760 static wxMBConvLibc wxConvLibcObj
;
2763 static wxCSConv
wxConvLocalObj(wxFONTENCODING_SYSTEM
);
2764 static wxCSConv
wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1
);
2765 static wxMBConvUTF7 wxConvUTF7Obj
;
2766 static wxMBConvUTF8 wxConvUTF8Obj
;
2768 WXDLLIMPEXP_DATA_BASE(wxMBConv
&) wxConvLibc
= wxConvLibcObj
;
2769 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvLocal
= wxConvLocalObj
;
2770 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvISO8859_1
= wxConvISO8859_1Obj
;
2771 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7
&) wxConvUTF7
= wxConvUTF7Obj
;
2772 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8
&) wxConvUTF8
= wxConvUTF8Obj
;
2773 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvCurrent
= &wxConvLibcObj
;
2774 WXDLLIMPEXP_DATA_BASE(wxMBConv
*) wxConvFileName
= &
2782 #else // !wxUSE_WCHAR_T
2784 // stand-ins in absence of wchar_t
2785 WXDLLIMPEXP_DATA_BASE(wxMBConv
) wxConvLibc
,
2790 #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T