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 // ---------------------------------------------------------------------------- 
  75 #include "wx/encconv.h" 
  76 #include "wx/fontmap.h" 
  80 #include <ATSUnicode.h> 
  81 #include <TextCommon.h> 
  82 #include <TextEncodingConverter.h> 
  84 #include  "wx/mac/private.h"  // includes mac headers 
  86 // ---------------------------------------------------------------------------- 
  88 // ---------------------------------------------------------------------------- 
  90 #define BSWAP_UCS4(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT32_SWAP_ALWAYS(str[_c]); } 
  91 #define BSWAP_UTF16(str, len) { unsigned _c; for (_c=0; _c<len; _c++) str[_c]=wxUINT16_SWAP_ALWAYS(str[_c]); } 
  93 #if SIZEOF_WCHAR_T == 4 
  94     #define WC_NAME         "UCS4" 
  95     #define WC_BSWAP         BSWAP_UCS4 
  96     #ifdef WORDS_BIGENDIAN 
  97       #define WC_NAME_BEST  "UCS-4BE" 
  99       #define WC_NAME_BEST  "UCS-4LE" 
 101 #elif SIZEOF_WCHAR_T == 2 
 102     #define WC_NAME         "UTF16" 
 103     #define WC_BSWAP         BSWAP_UTF16 
 105     #ifdef WORDS_BIGENDIAN 
 106       #define WC_NAME_BEST  "UTF-16BE" 
 108       #define WC_NAME_BEST  "UTF-16LE" 
 110 #else // sizeof(wchar_t) != 2 nor 4 
 111     // does this ever happen? 
 112     #error "Unknown sizeof(wchar_t): please report this to wx-dev@lists.wxwindows.org" 
 115 // ============================================================================ 
 117 // ============================================================================ 
 119 // ---------------------------------------------------------------------------- 
 120 // UTF-16 en/decoding to/from UCS-4 
 121 // ---------------------------------------------------------------------------- 
 124 static size_t encode_utf16(wxUint32 input
, wxUint16 
*output
) 
 129             *output 
= (wxUint16
) input
; 
 132     else if (input
>=0x110000) 
 140             *output
++ = (wxUint16
) ((input 
>> 10)+0xd7c0); 
 141             *output 
= (wxUint16
) ((input
&0x3ff)+0xdc00); 
 147 static size_t decode_utf16(const wxUint16
* input
, wxUint32
& output
) 
 149     if ((*input
<0xd800) || (*input
>0xdfff)) 
 154     else if ((input
[1]<0xdc00) || (input
[1]>=0xdfff)) 
 161         output 
= ((input
[0] - 0xd7c0) << 10) + (input
[1] - 0xdc00); 
 167 // ---------------------------------------------------------------------------- 
 169 // ---------------------------------------------------------------------------- 
 171 wxMBConv::~wxMBConv() 
 173     // nothing to do here (necessary for Darwin linking probably) 
 176 const wxWCharBuffer 
wxMBConv::cMB2WC(const char *psz
) const 
 180         // calculate the length of the buffer needed first 
 181         size_t nLen 
= MB2WC(NULL
, psz
, 0); 
 182         if ( nLen 
!= (size_t)-1 ) 
 184             // now do the actual conversion 
 185             wxWCharBuffer 
buf(nLen
); 
 186             nLen 
= MB2WC(buf
.data(), psz
, nLen 
+ 1); // with the trailing NULL 
 187             if ( nLen 
!= (size_t)-1 ) 
 194     wxWCharBuffer 
buf((wchar_t *)NULL
); 
 199 const wxCharBuffer 
wxMBConv::cWC2MB(const wchar_t *pwz
) const 
 203         size_t nLen 
= WC2MB(NULL
, pwz
, 0); 
 204         if ( nLen 
!= (size_t)-1 ) 
 206             wxCharBuffer 
buf(nLen
+3);       // space for a wxUint32 trailing zero 
 207             nLen 
= WC2MB(buf
.data(), pwz
, nLen 
+ 4); 
 208             if ( nLen 
!= (size_t)-1 ) 
 215     wxCharBuffer 
buf((char *)NULL
); 
 220 const wxWCharBuffer 
wxMBConv::cMB2WC(const char *szString
, size_t nStringLen
, size_t* pOutSize
) const 
 222     wxASSERT(pOutSize 
!= NULL
); 
 224     const char* szEnd 
= szString 
+ nStringLen 
+ 1; 
 225     const char* szPos 
= szString
; 
 226     const char* szStart 
= szPos
; 
 228     size_t nActualLength 
= 0; 
 229     size_t nCurrentSize 
= nStringLen
; //try normal size first (should never resize?) 
 231     wxWCharBuffer 
theBuffer(nCurrentSize
); 
 233     //Convert the string until the length() is reached, continuing the 
 234     //loop every time a null character is reached 
 235     while(szPos 
!= szEnd
) 
 237         wxASSERT(szPos 
< szEnd
); //something is _really_ screwed up if this rings true 
 239         //Get the length of the current (sub)string 
 240         size_t nLen 
= MB2WC(NULL
, szPos
, 0); 
 242         //Invalid conversion? 
 243         if( nLen 
== (size_t)-1 ) 
 246             theBuffer
.data()[0u] = wxT('\0'); 
 251         //Increase the actual length (+1 for current null character) 
 252         nActualLength 
+= nLen 
+ 1; 
 254         //if buffer too big, realloc the buffer 
 255         if (nActualLength 
> (nCurrentSize
+1)) 
 257             wxWCharBuffer 
theNewBuffer(nCurrentSize 
<< 1); 
 258             memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize 
* sizeof(wchar_t)); 
 259             theBuffer 
= theNewBuffer
; 
 263         //Convert the current (sub)string 
 264         if ( MB2WC(&theBuffer
.data()[szPos 
- szStart
], szPos
, nLen 
+ 1) == (size_t)-1 ) 
 267             theBuffer
.data()[0u] = wxT('\0'); 
 271         //Increment to next (sub)string 
 272         //Note that we have to use strlen here instead of nLen 
 273         //here because XX2XX gives us the size of the output buffer, 
 274         //not neccessarly the length of the string 
 275         szPos 
+= strlen(szPos
) + 1; 
 278     //success - return actual length and the buffer 
 279     *pOutSize 
= nActualLength
; 
 283 const wxCharBuffer 
wxMBConv::cWC2MB(const wchar_t *szString
, size_t nStringLen
, size_t* pOutSize
) const 
 285     wxASSERT(pOutSize 
!= NULL
); 
 287     const wchar_t* szEnd 
= szString 
+ nStringLen 
+ 1; 
 288     const wchar_t* szPos 
= szString
; 
 289     const wchar_t* szStart 
= szPos
; 
 291     size_t nActualLength 
= 0; 
 292     size_t nCurrentSize 
= nStringLen 
<< 2; //try * 4 first 
 294     wxCharBuffer 
theBuffer(nCurrentSize
); 
 296     //Convert the string until the length() is reached, continuing the 
 297     //loop every time a null character is reached 
 298     while(szPos 
!= szEnd
) 
 300         wxASSERT(szPos 
< szEnd
); //something is _really_ screwed up if this rings true 
 302         //Get the length of the current (sub)string 
 303         size_t nLen 
= WC2MB(NULL
, szPos
, 0); 
 305         //Invalid conversion? 
 306         if( nLen 
== (size_t)-1 ) 
 309             theBuffer
.data()[0u] = wxT('\0'); 
 313         //Increase the actual length (+1 for current null character) 
 314         nActualLength 
+= nLen 
+ 1; 
 316         //if buffer too big, realloc the buffer 
 317         if (nActualLength 
> (nCurrentSize
+1)) 
 319             wxCharBuffer 
theNewBuffer(nCurrentSize 
<< 1); 
 320             memcpy(theNewBuffer
.data(), theBuffer
.data(), nCurrentSize
); 
 321             theBuffer 
= theNewBuffer
; 
 325         //Convert the current (sub)string 
 326         if(WC2MB(&theBuffer
.data()[szPos 
- szStart
], szPos
, nLen 
+ 1) == (size_t)-1 ) 
 329             theBuffer
.data()[0u] = wxT('\0'); 
 333         //Increment to next (sub)string 
 334         //Note that we have to use wxWcslen here instead of nLen 
 335         //here because XX2XX gives us the size of the output buffer, 
 336         //not neccessarly the length of the string 
 337         szPos 
+= wxWcslen(szPos
) + 1; 
 340     //success - return actual length and the buffer 
 341     *pOutSize 
= nActualLength
; 
 345 // ---------------------------------------------------------------------------- 
 347 // ---------------------------------------------------------------------------- 
 349 size_t wxMBConvLibc::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 351     return wxMB2WC(buf
, psz
, n
); 
 354 size_t wxMBConvLibc::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 356     return wxWC2MB(buf
, psz
, n
); 
 358 // ---------------------------------------------------------------------------- 
 360 // ---------------------------------------------------------------------------- 
 362 // Implementation (C) 2004 Fredrik Roubert 
 365 // BASE64 decoding table 
 367 static const unsigned char utf7unb64
[] = 
 369     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 370     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 371     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 372     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 373     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 374     0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
 375     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 
 376     0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 377     0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
 378     0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 
 379     0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 
 380     0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
 381     0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 
 382     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 
 383     0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
 384     0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 
 385     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 386     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 387     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 388     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 389     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 390     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 391     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 392     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 393     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 394     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 395     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 396     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 397     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 398     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 399     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 400     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 
 403 size_t wxMBConvUTF7::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 408     while (*psz 
&& ((!buf
) || (len 
< n
))) 
 410         unsigned char cc 
= *psz
++; 
 418         else if (*psz 
== '-') 
 428             // BASE64 encoded string 
 432             for (lsb 
= false, d 
= 0, l 
= 0; 
 433                 (cc 
= utf7unb64
[(unsigned char)*psz
]) != 0xff; psz
++) 
 437                 for (l 
+= 6; l 
>= 8; lsb 
= !lsb
) 
 439                     c 
= (unsigned char)((d 
>> (l 
-= 8)) % 256); 
 448                             *buf 
= (wchar_t)(c 
<< 8); 
 455     if (buf 
&& (len 
< n
)) 
 461 // BASE64 encoding table 
 463 static const unsigned char utf7enb64
[] = 
 465     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
 466     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
 467     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
 468     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
 469     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
 470     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
 471     'w', 'x', 'y', 'z', '0', '1', '2', '3', 
 472     '4', '5', '6', '7', '8', '9', '+', '/' 
 476 // UTF-7 encoding table 
 478 // 0 - Set D (directly encoded characters) 
 479 // 1 - Set O (optional direct characters) 
 480 // 2 - whitespace characters (optional) 
 481 // 3 - special characters 
 483 static const unsigned char utf7encode
[128] = 
 485     3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3, 
 486     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
 487     2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 3, 
 488     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 
 489     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 490     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1, 
 491     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 492     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3 
 495 size_t wxMBConvUTF7::WC2MB(char *buf
, const wchar_t  
 496 *psz
, size_t n
) const 
 502     while (*psz 
&& ((!buf
) || (len 
< n
))) 
 505         if (cc 
< 0x80 && utf7encode
[cc
] < 1) 
 513         else if (((wxUint32
)cc
) > 0xffff) 
 515             // no surrogate pair generation (yet?) 
 526                 // BASE64 encode string 
 527                 unsigned int lsb
, d
, l
; 
 528                 for (d 
= 0, l 
= 0;; psz
++) 
 530                     for (lsb 
= 0; lsb 
< 2; lsb 
++) 
 533                         d 
+= lsb 
? cc 
& 0xff : (cc 
& 0xff00) >> 8; 
 535                         for (l 
+= 8; l 
>= 6; ) 
 539                                 *buf
++ = utf7enb64
[(d 
>> l
) % 64]; 
 544                     if (!(cc
) || (cc 
< 0x80 && utf7encode
[cc
] < 1)) 
 550                         *buf
++ = utf7enb64
[((d 
% 16) << (6 - l
)) % 64]; 
 559     if (buf 
&& (len 
< n
)) 
 564 // ---------------------------------------------------------------------------- 
 566 // ---------------------------------------------------------------------------- 
 568 static wxUint32 utf8_max
[]= 
 569     { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff }; 
 571 size_t wxMBConvUTF8::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 575     while (*psz 
&& ((!buf
) || (len 
< n
))) 
 577         unsigned char cc 
= *psz
++, fc 
= cc
; 
 579         for (cnt 
= 0; fc 
& 0x80; cnt
++) 
 593                 // invalid UTF-8 sequence 
 598                 unsigned ocnt 
= cnt 
- 1; 
 599                 wxUint32 res 
= cc 
& (0x3f >> cnt
); 
 603                     if ((cc 
& 0xC0) != 0x80) 
 605                         // invalid UTF-8 sequence 
 608                     res 
= (res 
<< 6) | (cc 
& 0x3f); 
 610                 if (res 
<= utf8_max
[ocnt
]) 
 612                     // illegal UTF-8 encoding 
 616                 // cast is ok because wchar_t == wxUuint16 if WC_UTF16 
 617                 size_t pa 
= encode_utf16(res
, (wxUint16 
*)buf
); 
 618                 if (pa 
== (size_t)-1) 
 627 #endif // WC_UTF16/!WC_UTF16 
 631     if (buf 
&& (len 
< n
)) 
 636 size_t wxMBConvUTF8::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 640     while (*psz 
&& ((!buf
) || (len 
< n
))) 
 644         // cast is ok for WC_UTF16 
 645         size_t pa 
= decode_utf16((const wxUint16 
*)psz
, cc
); 
 646         psz 
+= (pa 
== (size_t)-1) ? 1 : pa
; 
 648         cc
=(*psz
++) & 0x7fffffff; 
 651         for (cnt 
= 0; cc 
> utf8_max
[cnt
]; cnt
++) {} 
 665                 *buf
++ = (char) ((-128 >> cnt
) | ((cc 
>> (cnt 
* 6)) & (0x3f >> cnt
))); 
 667                     *buf
++ = (char) (0x80 | ((cc 
>> (cnt 
* 6)) & 0x3f)); 
 672     if (buf 
&& (len
<n
)) *buf 
= 0; 
 680 // ---------------------------------------------------------------------------- 
 682 // ---------------------------------------------------------------------------- 
 684 #ifdef WORDS_BIGENDIAN 
 685     #define wxMBConvUTF16straight wxMBConvUTF16BE 
 686     #define wxMBConvUTF16swap     wxMBConvUTF16LE 
 688     #define wxMBConvUTF16swap     wxMBConvUTF16BE 
 689     #define wxMBConvUTF16straight wxMBConvUTF16LE 
 695 // copy 16bit MB to 16bit String 
 696 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 700     while (*(wxUint16
*)psz 
&& (!buf 
|| len 
< n
)) 
 703             *buf
++ = *(wxUint16
*)psz
; 
 706         psz 
+= sizeof(wxUint16
); 
 708     if (buf 
&& len
<n
)   *buf
=0; 
 714 // copy 16bit String to 16bit MB 
 715 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 719     while (*psz 
&& (!buf 
|| len 
< n
)) 
 723             *(wxUint16
*)buf 
= *psz
; 
 724             buf 
+= sizeof(wxUint16
); 
 726         len 
+= sizeof(wxUint16
); 
 729     if (buf 
&& len
<=n
-sizeof(wxUint16
))   *(wxUint16
*)buf
=0; 
 735 // swap 16bit MB to 16bit String 
 736 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 740     while (*(wxUint16
*)psz 
&& (!buf 
|| len 
< n
)) 
 744             ((char *)buf
)[0] = psz
[1]; 
 745             ((char *)buf
)[1] = psz
[0]; 
 749         psz 
+= sizeof(wxUint16
); 
 751     if (buf 
&& len
<n
)   *buf
=0; 
 757 // swap 16bit MB to 16bit String 
 758 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 762     while (*psz 
&& (!buf 
|| len 
< n
)) 
 766             *buf
++ = ((char*)psz
)[1]; 
 767             *buf
++ = ((char*)psz
)[0]; 
 769         len 
+= sizeof(wxUint16
); 
 772     if (buf 
&& len
<=n
-sizeof(wxUint16
))   *(wxUint16
*)buf
=0; 
 781 // copy 16bit MB to 32bit String 
 782 size_t wxMBConvUTF16straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 786     while (*(wxUint16
*)psz 
&& (!buf 
|| len 
< n
)) 
 789         size_t pa
=decode_utf16((wxUint16
*)psz
, cc
); 
 790         if (pa 
== (size_t)-1) 
 796         psz 
+= pa 
* sizeof(wxUint16
); 
 798     if (buf 
&& len
<n
)   *buf
=0; 
 804 // copy 32bit String to 16bit MB 
 805 size_t wxMBConvUTF16straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 809     while (*psz 
&& (!buf 
|| len 
< n
)) 
 812         size_t pa
=encode_utf16(*psz
, cc
); 
 814         if (pa 
== (size_t)-1) 
 819             *(wxUint16
*)buf 
= cc
[0]; 
 820             buf 
+= sizeof(wxUint16
); 
 823                 *(wxUint16
*)buf 
= cc
[1]; 
 824                 buf 
+= sizeof(wxUint16
); 
 828         len 
+= pa
*sizeof(wxUint16
); 
 831     if (buf 
&& len
<=n
-sizeof(wxUint16
))   *(wxUint16
*)buf
=0; 
 837 // swap 16bit MB to 32bit String 
 838 size_t wxMBConvUTF16swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 842     while (*(wxUint16
*)psz 
&& (!buf 
|| len 
< n
)) 
 846         tmp
[0]=psz
[1];  tmp
[1]=psz
[0]; 
 847         tmp
[2]=psz
[3];  tmp
[3]=psz
[2]; 
 849         size_t pa
=decode_utf16((wxUint16
*)tmp
, cc
); 
 850         if (pa 
== (size_t)-1) 
 857         psz 
+= pa 
* sizeof(wxUint16
); 
 859     if (buf 
&& len
<n
)   *buf
=0; 
 865 // swap 32bit String to 16bit MB 
 866 size_t wxMBConvUTF16swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 870     while (*psz 
&& (!buf 
|| len 
< n
)) 
 873         size_t pa
=encode_utf16(*psz
, cc
); 
 875         if (pa 
== (size_t)-1) 
 880             *buf
++ = ((char*)cc
)[1]; 
 881             *buf
++ = ((char*)cc
)[0]; 
 884                 *buf
++ = ((char*)cc
)[3]; 
 885                 *buf
++ = ((char*)cc
)[2]; 
 889         len 
+= pa
*sizeof(wxUint16
); 
 892     if (buf 
&& len
<=n
-sizeof(wxUint16
))   *(wxUint16
*)buf
=0; 
 900 // ---------------------------------------------------------------------------- 
 902 // ---------------------------------------------------------------------------- 
 904 #ifdef WORDS_BIGENDIAN 
 905 #define wxMBConvUTF32straight  wxMBConvUTF32BE 
 906 #define wxMBConvUTF32swap      wxMBConvUTF32LE 
 908 #define wxMBConvUTF32swap      wxMBConvUTF32BE 
 909 #define wxMBConvUTF32straight  wxMBConvUTF32LE 
 913 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32LE
) wxConvUTF32LE
; 
 914 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF32BE
) wxConvUTF32BE
; 
 919 // copy 32bit MB to 16bit String 
 920 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 924     while (*(wxUint32
*)psz 
&& (!buf 
|| len 
< n
)) 
 928         size_t pa
=encode_utf16(*(wxUint32
*)psz
, cc
); 
 929         if (pa 
== (size_t)-1) 
 939         psz 
+= sizeof(wxUint32
); 
 941     if (buf 
&& len
<n
)   *buf
=0; 
 947 // copy 16bit String to 32bit MB 
 948 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
 952     while (*psz 
&& (!buf 
|| len 
< n
)) 
 956         // cast is ok for WC_UTF16 
 957         size_t pa 
= decode_utf16((const wxUint16 
*)psz
, cc
); 
 958         if (pa 
== (size_t)-1) 
 963             *(wxUint32
*)buf 
= cc
; 
 964             buf 
+= sizeof(wxUint32
); 
 966         len 
+= sizeof(wxUint32
); 
 970     if (buf 
&& len
<=n
-sizeof(wxUint32
)) 
 978 // swap 32bit MB to 16bit String 
 979 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
 983     while (*(wxUint32
*)psz 
&& (!buf 
|| len 
< n
)) 
 986         tmp
[0] = psz
[3];   tmp
[1] = psz
[2]; 
 987         tmp
[2] = psz
[1];   tmp
[3] = psz
[0]; 
 992         size_t pa
=encode_utf16(*(wxUint32
*)tmp
, cc
); 
 993         if (pa 
== (size_t)-1) 
1003         psz 
+= sizeof(wxUint32
); 
1013 // swap 16bit String to 32bit MB 
1014 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
1018     while (*psz 
&& (!buf 
|| len 
< n
)) 
1022         // cast is ok for WC_UTF16 
1023         size_t pa
=decode_utf16((const wxUint16 
*)psz
, *(wxUint32
*)cc
); 
1024         if (pa 
== (size_t)-1) 
1034         len 
+= sizeof(wxUint32
); 
1038     if (buf 
&& len
<=n
-sizeof(wxUint32
)) 
1047 // copy 32bit MB to 32bit String 
1048 size_t wxMBConvUTF32straight::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
1052     while (*(wxUint32
*)psz 
&& (!buf 
|| len 
< n
)) 
1055             *buf
++ = *(wxUint32
*)psz
; 
1057         psz 
+= sizeof(wxUint32
); 
1067 // copy 32bit String to 32bit MB 
1068 size_t wxMBConvUTF32straight::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
1072     while (*psz 
&& (!buf 
|| len 
< n
)) 
1076             *(wxUint32
*)buf 
= *psz
; 
1077             buf 
+= sizeof(wxUint32
); 
1080         len 
+= sizeof(wxUint32
); 
1084     if (buf 
&& len
<=n
-sizeof(wxUint32
)) 
1091 // swap 32bit MB to 32bit String 
1092 size_t wxMBConvUTF32swap::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
1096     while (*(wxUint32
*)psz 
&& (!buf 
|| len 
< n
)) 
1100             ((char *)buf
)[0] = psz
[3]; 
1101             ((char *)buf
)[1] = psz
[2]; 
1102             ((char *)buf
)[2] = psz
[1]; 
1103             ((char *)buf
)[3] = psz
[0]; 
1107         psz 
+= sizeof(wxUint32
); 
1117 // swap 32bit String to 32bit MB 
1118 size_t wxMBConvUTF32swap::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
1122     while (*psz 
&& (!buf 
|| len 
< n
)) 
1126             *buf
++ = ((char *)psz
)[3]; 
1127             *buf
++ = ((char *)psz
)[2]; 
1128             *buf
++ = ((char *)psz
)[1]; 
1129             *buf
++ = ((char *)psz
)[0]; 
1131         len 
+= sizeof(wxUint32
); 
1135     if (buf 
&& len
<=n
-sizeof(wxUint32
)) 
1145 // ============================================================================ 
1146 // The classes doing conversion using the iconv_xxx() functions 
1147 // ============================================================================ 
1151 // VS: glibc 2.1.3 is broken in that iconv() conversion to/from UCS4 fails with E2BIG 
1152 //     if output buffer is _exactly_ as big as needed. Such case is (unless there's 
1153 //     yet another bug in glibc) the only case when iconv() returns with (size_t)-1 
1154 //     (which means error) and says there are 0 bytes left in the input buffer -- 
1155 //     when _real_ error occurs, bytes-left-in-input buffer is non-zero. Hence, 
1156 //     this alternative test for iconv() failure. 
1157 //     [This bug does not appear in glibc 2.2.] 
1158 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1 
1159 #define ICONV_FAILED(cres, bufLeft) ((cres == (size_t)-1) && \ 
1160                                      (errno != E2BIG || bufLeft != 0)) 
1162 #define ICONV_FAILED(cres, bufLeft)  (cres == (size_t)-1) 
1165 #define ICONV_CHAR_CAST(x)  ((ICONV_CONST char **)(x)) 
1167 // ---------------------------------------------------------------------------- 
1168 // wxMBConv_iconv: encapsulates an iconv character set 
1169 // ---------------------------------------------------------------------------- 
1171 class wxMBConv_iconv 
: public wxMBConv
 
1174     wxMBConv_iconv(const wxChar 
*name
); 
1175     virtual ~wxMBConv_iconv(); 
1177     virtual size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const; 
1178     virtual size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const; 
1181         { return (m2w 
!= (iconv_t
)-1) && (w2m 
!= (iconv_t
)-1); } 
1184     // the iconv handlers used to translate from multibyte to wide char and in 
1185     // the other direction 
1190     // the name (for iconv_open()) of a wide char charset -- if none is 
1191     // available on this machine, it will remain NULL 
1192     static const char *ms_wcCharsetName
; 
1194     // true if the wide char encoding we use (i.e. ms_wcCharsetName) has 
1195     // different endian-ness than the native one 
1196     static bool ms_wcNeedsSwap
; 
1199 const char *wxMBConv_iconv::ms_wcCharsetName 
= NULL
; 
1200 bool wxMBConv_iconv::ms_wcNeedsSwap 
= false; 
1202 wxMBConv_iconv::wxMBConv_iconv(const wxChar 
*name
) 
1204     // Do it the hard way 
1206     for (size_t i 
= 0; i 
< wxStrlen(name
)+1; i
++) 
1207         cname
[i
] = (char) name
[i
]; 
1209     // check for charset that represents wchar_t: 
1210     if (ms_wcCharsetName 
== NULL
) 
1212         ms_wcNeedsSwap 
= false; 
1214         // try charset with explicit bytesex info (e.g. "UCS-4LE"): 
1215         ms_wcCharsetName 
= WC_NAME_BEST
; 
1216         m2w 
= iconv_open(ms_wcCharsetName
, cname
); 
1218         if (m2w 
== (iconv_t
)-1) 
1220             // try charset w/o bytesex info (e.g. "UCS4") 
1221             // and check for bytesex ourselves: 
1222             ms_wcCharsetName 
= WC_NAME
; 
1223             m2w 
= iconv_open(ms_wcCharsetName
, cname
); 
1225             // last bet, try if it knows WCHAR_T pseudo-charset 
1226             if (m2w 
== (iconv_t
)-1) 
1228                 ms_wcCharsetName 
= "WCHAR_T"; 
1229                 m2w 
= iconv_open(ms_wcCharsetName
, cname
); 
1232             if (m2w 
!= (iconv_t
)-1) 
1234                 char    buf
[2], *bufPtr
; 
1235                 wchar_t wbuf
[2], *wbufPtr
; 
1243                 outsz 
= SIZEOF_WCHAR_T 
* 2; 
1247                 res 
= iconv(m2w
, ICONV_CHAR_CAST(&bufPtr
), &insz
, 
1248                             (char**)&wbufPtr
, &outsz
); 
1250                 if (ICONV_FAILED(res
, insz
)) 
1252                     ms_wcCharsetName 
= NULL
; 
1253                     wxLogLastError(wxT("iconv")); 
1254                     wxLogError(_("Conversion to charset '%s' doesn't work."), name
); 
1258                     ms_wcNeedsSwap 
= wbuf
[0] != (wchar_t)buf
[0]; 
1263                 ms_wcCharsetName 
= NULL
; 
1265                 // VS: we must not output an error here, since wxWidgets will safely 
1266                 //     fall back to using wxEncodingConverter. 
1267                 wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name
); 
1271         wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName
, ms_wcNeedsSwap
); 
1273     else // we already have ms_wcCharsetName 
1275         m2w 
= iconv_open(ms_wcCharsetName
, cname
); 
1278     // NB: don't ever pass NULL to iconv_open(), it may crash! 
1279     if ( ms_wcCharsetName 
) 
1281         w2m 
= iconv_open( cname
, ms_wcCharsetName
); 
1289 wxMBConv_iconv::~wxMBConv_iconv() 
1291     if ( m2w 
!= (iconv_t
)-1 ) 
1293     if ( w2m 
!= (iconv_t
)-1 ) 
1297 size_t wxMBConv_iconv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
1299     size_t inbuf 
= strlen(psz
); 
1300     size_t outbuf 
= n 
* SIZEOF_WCHAR_T
; 
1302     // VS: Use these instead of psz, buf because iconv() modifies its arguments: 
1303     wchar_t *bufPtr 
= buf
; 
1304     const char *pszPtr 
= psz
; 
1308         // have destination buffer, convert there 
1310                      ICONV_CHAR_CAST(&pszPtr
), &inbuf
, 
1311                      (char**)&bufPtr
, &outbuf
); 
1312         res 
= n 
- (outbuf 
/ SIZEOF_WCHAR_T
); 
1316             // convert to native endianness 
1317             WC_BSWAP(buf 
/* _not_ bufPtr */, res
) 
1320         // NB: iconv was given only strlen(psz) characters on input, and so 
1321         //     it couldn't convert the trailing zero. Let's do it ourselves 
1322         //     if there's some room left for it in the output buffer. 
1328         // no destination buffer... convert using temp buffer 
1329         // to calculate destination buffer requirement 
1334             outbuf 
= 8*SIZEOF_WCHAR_T
; 
1337                          ICONV_CHAR_CAST(&pszPtr
), &inbuf
, 
1338                          (char**)&bufPtr
, &outbuf 
); 
1340             res 
+= 8-(outbuf
/SIZEOF_WCHAR_T
); 
1341         } while ((cres
==(size_t)-1) && (errno
==E2BIG
)); 
1344     if (ICONV_FAILED(cres
, inbuf
)) 
1346         //VS: it is ok if iconv fails, hence trace only 
1347         wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode())); 
1354 size_t wxMBConv_iconv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
1356     size_t inbuf 
= wxWcslen(psz
) * SIZEOF_WCHAR_T
; 
1360     wchar_t *tmpbuf 
= 0; 
1364         // need to copy to temp buffer to switch endianness 
1365         // this absolutely doesn't rock! 
1366         // (no, doing WC_BSWAP twice on the original buffer won't help, as it 
1367         //  could be in read-only memory, or be accessed in some other thread) 
1368         tmpbuf
=(wchar_t*)malloc((inbuf
+1)*SIZEOF_WCHAR_T
); 
1369         memcpy(tmpbuf
,psz
,(inbuf
+1)*SIZEOF_WCHAR_T
); 
1370         WC_BSWAP(tmpbuf
, inbuf
) 
1376         // have destination buffer, convert there 
1377         cres 
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf 
); 
1381         // NB: iconv was given only wcslen(psz) characters on input, and so 
1382         //     it couldn't convert the trailing zero. Let's do it ourselves 
1383         //     if there's some room left for it in the output buffer. 
1389         // no destination buffer... convert using temp buffer 
1390         // to calculate destination buffer requirement 
1394             buf 
= tbuf
; outbuf 
= 16; 
1396             cres 
= iconv( w2m
, ICONV_CHAR_CAST(&psz
), &inbuf
, &buf
, &outbuf 
); 
1399         } while ((cres
==(size_t)-1) && (errno
==E2BIG
)); 
1407     if (ICONV_FAILED(cres
, inbuf
)) 
1409         //VS: it is ok if iconv fails, hence trace only 
1410         wxLogTrace(wxT("strconv"), wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode())); 
1417 #endif // HAVE_ICONV 
1420 // ============================================================================ 
1421 // Win32 conversion classes 
1422 // ============================================================================ 
1424 #ifdef wxHAVE_WIN32_MB2WC 
1428 extern WXDLLIMPEXP_BASE 
long wxCharsetToCodepage(const wxChar 
*charset
); 
1429 extern WXDLLIMPEXP_BASE 
long wxEncodingToCodepage(wxFontEncoding encoding
); 
1432 class wxMBConv_win32 
: public wxMBConv
 
1437         m_CodePage 
= CP_ACP
; 
1441     wxMBConv_win32(const wxChar
* name
) 
1443         m_CodePage 
= wxCharsetToCodepage(name
); 
1446     wxMBConv_win32(wxFontEncoding encoding
) 
1448         m_CodePage 
= wxEncodingToCodepage(encoding
); 
1452     size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
1454         // note that we have to use MB_ERR_INVALID_CHARS flag as it without it 
1455         // the behaviour is not compatible with the Unix version (using iconv) 
1456         // and break the library itself, e.g. wxTextInputStream::NextChar() 
1457         // wouldn't work if reading an incomplete MB char didn't result in an 
1459         const size_t len 
= ::MultiByteToWideChar
 
1461                                 m_CodePage
,     // code page 
1462                                 MB_ERR_INVALID_CHARS
, // flags: fall on error 
1463                                 psz
,            // input string 
1464                                 -1,             // its length (NUL-terminated) 
1465                                 buf
,            // output string 
1466                                 buf 
? n 
: 0     // size of output buffer 
1469         // note that it returns count of written chars for buf != NULL and size 
1470         // of the needed buffer for buf == NULL so in either case the length of 
1471         // the string (which never includes the terminating NUL) is one less 
1472         return len 
? len 
- 1 : (size_t)-1; 
1475     size_t WC2MB(char *buf
, const wchar_t *pwz
, size_t n
) const 
1478             we have a problem here: by default, WideCharToMultiByte() may 
1479             replace characters unrepresentable in the target code page with bad 
1480             quality approximations such as turning "1/2" symbol (U+00BD) into 
1481             "1" for the code pages which don't have it and we, obviously, want 
1482             to avoid this at any price 
1484             the trouble is that this function does it _silently_, i.e. it won't 
1485             even tell us whether it did or not... Win98/2000 and higher provide 
1486             WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and 
1487             we have to resort to a round trip, i.e. check that converting back 
1488             results in the same string -- this is, of course, expensive but 
1489             otherwise we simply can't be sure to not garble the data. 
1492         // determine if we can rely on WC_NO_BEST_FIT_CHARS: according to MSDN 
1493         // it doesn't work with CJK encodings (which we test for rather roughly 
1494         // here...) nor with UTF-7/8 nor, of course, with Windows versions not 
1496         BOOL usedDef 
wxDUMMY_INITIALIZE(false); 
1499         if ( CanUseNoBestFit() && m_CodePage 
< 50000 ) 
1501             // it's our lucky day 
1502             flags 
= WC_NO_BEST_FIT_CHARS
; 
1503             pUsedDef 
= &usedDef
; 
1505         else // old system or unsupported encoding 
1511         const size_t len 
= ::WideCharToMultiByte
 
1513                                 m_CodePage
,     // code page 
1514                                 flags
,          // either none or no best fit 
1515                                 pwz
,            // input string 
1516                                 -1,             // it is (wide) NUL-terminated 
1517                                 buf
,            // output buffer 
1518                                 buf 
? n 
: 0,    // and its size 
1519                                 NULL
,           // default "replacement" char 
1520                                 pUsedDef        
// [out] was it used? 
1525             // function totally failed 
1529         // if we were really converting, check if we succeeded 
1534                 // check if the conversion failed, i.e. if any replacements 
1539             else // we must resort to double tripping... 
1541                 wxWCharBuffer 
wcBuf(n
); 
1542                 if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 || 
1543                         wcscmp(wcBuf
, pwz
) != 0 ) 
1545                     // we didn't obtain the same thing we started from, hence 
1546                     // the conversion was lossy and we consider that it failed 
1552         // see the comment above for the reason of "len - 1" 
1556     bool IsOk() const { return m_CodePage 
!= -1; } 
1559     static bool CanUseNoBestFit() 
1561         static int s_isWin98Or2k 
= -1; 
1563         if ( s_isWin98Or2k 
== -1 ) 
1566             switch ( wxGetOsVersion(&verMaj
, &verMin
) ) 
1569                     s_isWin98Or2k 
= verMaj 
>= 4 && verMin 
>= 10; 
1573                     s_isWin98Or2k 
= verMaj 
>= 5; 
1577                     // unknown, be conseravtive by default 
1581             wxASSERT_MSG( s_isWin98Or2k 
!= -1, _T("should be set above") ); 
1584         return s_isWin98Or2k 
== 1; 
1590 #endif // wxHAVE_WIN32_MB2WC 
1592 // ============================================================================ 
1593 // Cocoa conversion classes 
1594 // ============================================================================ 
1596 #if defined(__WXCOCOA__) 
1598 // RN:  There is no UTF-32 support in either Core Foundation or 
1599 // Cocoa.  Strangely enough, internally Core Foundation uses 
1600 // UTF 32 internally quite a bit - its just not public (yet). 
1602 #include <CoreFoundation/CFString.h> 
1603 #include <CoreFoundation/CFStringEncodingExt.h> 
1605 CFStringEncoding 
wxCFStringEncFromFontEnc(wxFontEncoding encoding
) 
1607     CFStringEncoding enc 
= kCFStringEncodingInvalidId 
; 
1608     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
1610         enc 
= CFStringGetSystemEncoding(); 
1612     else switch( encoding
) 
1614         case wxFONTENCODING_ISO8859_1 
: 
1615             enc 
= kCFStringEncodingISOLatin1 
; 
1617         case wxFONTENCODING_ISO8859_2 
: 
1618             enc 
= kCFStringEncodingISOLatin2
; 
1620         case wxFONTENCODING_ISO8859_3 
: 
1621             enc 
= kCFStringEncodingISOLatin3 
; 
1623         case wxFONTENCODING_ISO8859_4 
: 
1624             enc 
= kCFStringEncodingISOLatin4
; 
1626         case wxFONTENCODING_ISO8859_5 
: 
1627             enc 
= kCFStringEncodingISOLatinCyrillic
; 
1629         case wxFONTENCODING_ISO8859_6 
: 
1630             enc 
= kCFStringEncodingISOLatinArabic
; 
1632         case wxFONTENCODING_ISO8859_7 
: 
1633             enc 
= kCFStringEncodingISOLatinGreek
; 
1635         case wxFONTENCODING_ISO8859_8 
: 
1636             enc 
= kCFStringEncodingISOLatinHebrew
; 
1638         case wxFONTENCODING_ISO8859_9 
: 
1639             enc 
= kCFStringEncodingISOLatin5
; 
1641         case wxFONTENCODING_ISO8859_10 
: 
1642             enc 
= kCFStringEncodingISOLatin6
; 
1644         case wxFONTENCODING_ISO8859_11 
: 
1645             enc 
= kCFStringEncodingISOLatinThai
; 
1647         case wxFONTENCODING_ISO8859_13 
: 
1648             enc 
= kCFStringEncodingISOLatin7
; 
1650         case wxFONTENCODING_ISO8859_14 
: 
1651             enc 
= kCFStringEncodingISOLatin8
; 
1653         case wxFONTENCODING_ISO8859_15 
: 
1654             enc 
= kCFStringEncodingISOLatin9
; 
1657         case wxFONTENCODING_KOI8 
: 
1658             enc 
= kCFStringEncodingKOI8_R
; 
1660         case wxFONTENCODING_ALTERNATIVE 
: // MS-DOS CP866 
1661             enc 
= kCFStringEncodingDOSRussian
; 
1664 //      case wxFONTENCODING_BULGARIAN : 
1668         case wxFONTENCODING_CP437 
: 
1669             enc 
=kCFStringEncodingDOSLatinUS 
; 
1671         case wxFONTENCODING_CP850 
: 
1672             enc 
= kCFStringEncodingDOSLatin1
; 
1674         case wxFONTENCODING_CP852 
: 
1675             enc 
= kCFStringEncodingDOSLatin2
; 
1677         case wxFONTENCODING_CP855 
: 
1678             enc 
= kCFStringEncodingDOSCyrillic
; 
1680         case wxFONTENCODING_CP866 
: 
1681             enc 
=kCFStringEncodingDOSRussian 
; 
1683         case wxFONTENCODING_CP874 
: 
1684             enc 
= kCFStringEncodingDOSThai
; 
1686         case wxFONTENCODING_CP932 
: 
1687             enc 
= kCFStringEncodingDOSJapanese
; 
1689         case wxFONTENCODING_CP936 
: 
1690             enc 
=kCFStringEncodingDOSChineseSimplif 
; 
1692         case wxFONTENCODING_CP949 
: 
1693             enc 
= kCFStringEncodingDOSKorean
; 
1695         case wxFONTENCODING_CP950 
: 
1696             enc 
= kCFStringEncodingDOSChineseTrad
; 
1698         case wxFONTENCODING_CP1250 
: 
1699             enc 
= kCFStringEncodingWindowsLatin2
; 
1701         case wxFONTENCODING_CP1251 
: 
1702             enc 
=kCFStringEncodingWindowsCyrillic 
; 
1704         case wxFONTENCODING_CP1252 
: 
1705             enc 
=kCFStringEncodingWindowsLatin1 
; 
1707         case wxFONTENCODING_CP1253 
: 
1708             enc 
= kCFStringEncodingWindowsGreek
; 
1710         case wxFONTENCODING_CP1254 
: 
1711             enc 
= kCFStringEncodingWindowsLatin5
; 
1713         case wxFONTENCODING_CP1255 
: 
1714             enc 
=kCFStringEncodingWindowsHebrew 
; 
1716         case wxFONTENCODING_CP1256 
: 
1717             enc 
=kCFStringEncodingWindowsArabic 
; 
1719         case wxFONTENCODING_CP1257 
: 
1720             enc 
= kCFStringEncodingWindowsBalticRim
; 
1722 //   This only really encodes to UTF7 (if that) evidently 
1723 //        case wxFONTENCODING_UTF7 : 
1724 //            enc = kCFStringEncodingNonLossyASCII ; 
1726         case wxFONTENCODING_UTF8 
: 
1727             enc 
= kCFStringEncodingUTF8 
; 
1729         case wxFONTENCODING_EUC_JP 
: 
1730             enc 
= kCFStringEncodingEUC_JP
; 
1732         case wxFONTENCODING_UTF16 
: 
1733             enc 
= kCFStringEncodingUnicode 
; 
1735         case wxFONTENCODING_MACROMAN 
: 
1736             enc 
= kCFStringEncodingMacRoman 
; 
1738         case wxFONTENCODING_MACJAPANESE 
: 
1739             enc 
= kCFStringEncodingMacJapanese 
; 
1741         case wxFONTENCODING_MACCHINESETRAD 
: 
1742             enc 
= kCFStringEncodingMacChineseTrad 
; 
1744         case wxFONTENCODING_MACKOREAN 
: 
1745             enc 
= kCFStringEncodingMacKorean 
; 
1747         case wxFONTENCODING_MACARABIC 
: 
1748             enc 
= kCFStringEncodingMacArabic 
; 
1750         case wxFONTENCODING_MACHEBREW 
: 
1751             enc 
= kCFStringEncodingMacHebrew 
; 
1753         case wxFONTENCODING_MACGREEK 
: 
1754             enc 
= kCFStringEncodingMacGreek 
; 
1756         case wxFONTENCODING_MACCYRILLIC 
: 
1757             enc 
= kCFStringEncodingMacCyrillic 
; 
1759         case wxFONTENCODING_MACDEVANAGARI 
: 
1760             enc 
= kCFStringEncodingMacDevanagari 
; 
1762         case wxFONTENCODING_MACGURMUKHI 
: 
1763             enc 
= kCFStringEncodingMacGurmukhi 
; 
1765         case wxFONTENCODING_MACGUJARATI 
: 
1766             enc 
= kCFStringEncodingMacGujarati 
; 
1768         case wxFONTENCODING_MACORIYA 
: 
1769             enc 
= kCFStringEncodingMacOriya 
; 
1771         case wxFONTENCODING_MACBENGALI 
: 
1772             enc 
= kCFStringEncodingMacBengali 
; 
1774         case wxFONTENCODING_MACTAMIL 
: 
1775             enc 
= kCFStringEncodingMacTamil 
; 
1777         case wxFONTENCODING_MACTELUGU 
: 
1778             enc 
= kCFStringEncodingMacTelugu 
; 
1780         case wxFONTENCODING_MACKANNADA 
: 
1781             enc 
= kCFStringEncodingMacKannada 
; 
1783         case wxFONTENCODING_MACMALAJALAM 
: 
1784             enc 
= kCFStringEncodingMacMalayalam 
; 
1786         case wxFONTENCODING_MACSINHALESE 
: 
1787             enc 
= kCFStringEncodingMacSinhalese 
; 
1789         case wxFONTENCODING_MACBURMESE 
: 
1790             enc 
= kCFStringEncodingMacBurmese 
; 
1792         case wxFONTENCODING_MACKHMER 
: 
1793             enc 
= kCFStringEncodingMacKhmer 
; 
1795         case wxFONTENCODING_MACTHAI 
: 
1796             enc 
= kCFStringEncodingMacThai 
; 
1798         case wxFONTENCODING_MACLAOTIAN 
: 
1799             enc 
= kCFStringEncodingMacLaotian 
; 
1801         case wxFONTENCODING_MACGEORGIAN 
: 
1802             enc 
= kCFStringEncodingMacGeorgian 
; 
1804         case wxFONTENCODING_MACARMENIAN 
: 
1805             enc 
= kCFStringEncodingMacArmenian 
; 
1807         case wxFONTENCODING_MACCHINESESIMP 
: 
1808             enc 
= kCFStringEncodingMacChineseSimp 
; 
1810         case wxFONTENCODING_MACTIBETAN 
: 
1811             enc 
= kCFStringEncodingMacTibetan 
; 
1813         case wxFONTENCODING_MACMONGOLIAN 
: 
1814             enc 
= kCFStringEncodingMacMongolian 
; 
1816         case wxFONTENCODING_MACETHIOPIC 
: 
1817             enc 
= kCFStringEncodingMacEthiopic 
; 
1819         case wxFONTENCODING_MACCENTRALEUR 
: 
1820             enc 
= kCFStringEncodingMacCentralEurRoman 
; 
1822         case wxFONTENCODING_MACVIATNAMESE 
: 
1823             enc 
= kCFStringEncodingMacVietnamese 
; 
1825         case wxFONTENCODING_MACARABICEXT 
: 
1826             enc 
= kCFStringEncodingMacExtArabic 
; 
1828         case wxFONTENCODING_MACSYMBOL 
: 
1829             enc 
= kCFStringEncodingMacSymbol 
; 
1831         case wxFONTENCODING_MACDINGBATS 
: 
1832             enc 
= kCFStringEncodingMacDingbats 
; 
1834         case wxFONTENCODING_MACTURKISH 
: 
1835             enc 
= kCFStringEncodingMacTurkish 
; 
1837         case wxFONTENCODING_MACCROATIAN 
: 
1838             enc 
= kCFStringEncodingMacCroatian 
; 
1840         case wxFONTENCODING_MACICELANDIC 
: 
1841             enc 
= kCFStringEncodingMacIcelandic 
; 
1843         case wxFONTENCODING_MACROMANIAN 
: 
1844             enc 
= kCFStringEncodingMacRomanian 
; 
1846         case wxFONTENCODING_MACCELTIC 
: 
1847             enc 
= kCFStringEncodingMacCeltic 
; 
1849         case wxFONTENCODING_MACGAELIC 
: 
1850             enc 
= kCFStringEncodingMacGaelic 
; 
1852 //      case wxFONTENCODING_MACKEYBOARD : 
1853 //          enc = kCFStringEncodingMacKeyboardGlyphs ; 
1856             // because gcc is picky 
1862 class wxMBConv_cocoa 
: public wxMBConv
 
1867         Init(CFStringGetSystemEncoding()) ; 
1870     wxMBConv_cocoa(const wxChar
* name
) 
1872         Init( wxCFStringEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name
, false) ) ) ; 
1875     wxMBConv_cocoa(wxFontEncoding encoding
) 
1877         Init( wxCFStringEncFromFontEnc(encoding
) ); 
1884     void Init( CFStringEncoding encoding
) 
1886         m_encoding 
= encoding 
; 
1889     size_t MB2WC(wchar_t * szOut
, const char * szUnConv
, size_t nOutSize
) const 
1893         CFStringRef theString 
= CFStringCreateWithBytes ( 
1894                                                 NULL
, //the allocator 
1895                                                 (const UInt8
*)szUnConv
, 
1898                                                 false //no BOM/external representation 
1901         wxASSERT(theString
); 
1903         size_t nOutLength 
= CFStringGetLength(theString
); 
1907             CFRelease(theString
); 
1911         CFRange theRange 
= { 0, nOutSize 
}; 
1913 #if SIZEOF_WCHAR_T == 4 
1914         UniChar
* szUniCharBuffer 
= new UniChar
[nOutSize
]; 
1917         CFStringGetCharacters(theString
, theRange
, szUniCharBuffer
); 
1919         CFRelease(theString
); 
1921         szUniCharBuffer
[nOutLength
] = '\0' ; 
1923 #if SIZEOF_WCHAR_T == 4 
1924         wxMBConvUTF16 converter 
; 
1925         converter
.MB2WC(szOut
, (const char*)szUniCharBuffer 
, nOutSize 
) ; 
1926         delete[] szUniCharBuffer
; 
1932     size_t WC2MB(char *szOut
, const wchar_t *szUnConv
, size_t nOutSize
) const 
1936         size_t nRealOutSize
; 
1937         size_t nBufSize 
= wxWcslen(szUnConv
); 
1938         UniChar
* szUniBuffer 
= (UniChar
*) szUnConv
; 
1940 #if SIZEOF_WCHAR_T == 4 
1941         wxMBConvUTF16BE converter 
; 
1942         nBufSize 
= converter
.WC2MB( NULL 
, szUnConv 
, 0 ); 
1943         szUniBuffer 
= new UniChar
[ (nBufSize 
/ sizeof(UniChar
)) + 1] ; 
1944         converter
.WC2MB( (char*) szUniBuffer 
, szUnConv
, nBufSize 
+ sizeof(UniChar
)) ; 
1945         nBufSize 
/= sizeof(UniChar
); 
1948         CFStringRef theString 
= CFStringCreateWithCharactersNoCopy( 
1952                                 kCFAllocatorNull 
//deallocator - we want to deallocate it ourselves 
1955         wxASSERT(theString
); 
1957         //Note that CER puts a BOM when converting to unicode 
1958         //so we  check and use getchars instead in that case 
1959         if (m_encoding 
== kCFStringEncodingUnicode
) 
1962                 CFStringGetCharacters(theString
, CFRangeMake(0, nOutSize 
- 1), (UniChar
*) szOut
); 
1964             nRealOutSize 
= CFStringGetLength(theString
) + 1; 
1970                 CFRangeMake(0, CFStringGetLength(theString
)), 
1972                 0, //what to put in characters that can't be converted - 
1973                     //0 tells CFString to return NULL if it meets such a character 
1974                 false, //not an external representation 
1977                 (CFIndex
*) &nRealOutSize
 
1981         CFRelease(theString
); 
1983 #if SIZEOF_WCHAR_T == 4 
1984         delete[] szUniBuffer
; 
1987         return  nRealOutSize 
- 1; 
1992         return m_encoding 
!= kCFStringEncodingInvalidId 
&&  
1993               CFStringIsEncodingAvailable(m_encoding
); 
1997     CFStringEncoding m_encoding 
; 
2000 #endif // defined(__WXCOCOA__) 
2002 // ============================================================================ 
2003 // Mac conversion classes 
2004 // ============================================================================ 
2006 #if defined(__WXMAC__) && defined(TARGET_CARBON) 
2008 class wxMBConv_mac 
: public wxMBConv
 
2013         Init(CFStringGetSystemEncoding()) ; 
2016     wxMBConv_mac(const wxChar
* name
) 
2018         Init( wxMacGetSystemEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name
, false) ) ) ; 
2021     wxMBConv_mac(wxFontEncoding encoding
) 
2023         Init( wxMacGetSystemEncFromFontEnc(encoding
) ); 
2028         OSStatus status 
= noErr 
; 
2029         status 
= TECDisposeConverter(m_MB2WC_converter
); 
2030         status 
= TECDisposeConverter(m_WC2MB_converter
); 
2034     void Init( TextEncodingBase encoding
) 
2036         OSStatus status 
= noErr 
; 
2037         m_char_encoding 
= encoding 
; 
2038         m_unicode_encoding 
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ; 
2040         status 
= TECCreateConverter(&m_MB2WC_converter
, 
2042                                     m_unicode_encoding
); 
2043         status 
= TECCreateConverter(&m_WC2MB_converter
, 
2048     size_t MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
2050         OSStatus status 
= noErr 
; 
2051         ByteCount byteOutLen 
; 
2052         ByteCount byteInLen 
= strlen(psz
) ; 
2053         wchar_t *tbuf 
= NULL 
; 
2054         UniChar
* ubuf 
= NULL 
; 
2059             //apple specs say at least 32 
2060             n 
= wxMax( 32 , byteInLen 
) ; 
2061             tbuf 
= (wchar_t*) malloc( n 
* SIZEOF_WCHAR_T
) ; 
2063         ByteCount byteBufferLen 
= n 
* sizeof( UniChar 
) ; 
2064 #if SIZEOF_WCHAR_T == 4 
2065         ubuf 
= (UniChar
*) malloc( byteBufferLen 
+ 2 ) ; 
2067         ubuf 
= (UniChar
*) (buf 
? buf 
: tbuf
) ; 
2069         status 
= TECConvertText(m_MB2WC_converter
, (ConstTextPtr
) psz 
, byteInLen
, &byteInLen
, 
2070           (TextPtr
) ubuf 
, byteBufferLen
, &byteOutLen
); 
2071 #if SIZEOF_WCHAR_T == 4 
2072         // we have to terminate here, because n might be larger for the trailing zero, and if UniChar 
2073         // is not properly terminated we get random characters at the end 
2074         ubuf
[byteOutLen 
/ sizeof( UniChar 
) ] = 0 ; 
2075         wxMBConvUTF16BE converter 
; 
2076         res 
= converter
.MB2WC( (buf 
? buf 
: tbuf
) , (const char*)ubuf 
, n 
) ; 
2079         res 
= byteOutLen 
/ sizeof( UniChar 
) ; 
2084         if ( buf  
&& res 
< n
) 
2090     size_t WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
2092         OSStatus status 
= noErr 
; 
2093         ByteCount byteOutLen 
; 
2094         ByteCount byteInLen 
= wxWcslen(psz
) * SIZEOF_WCHAR_T 
; 
2100             //apple specs say at least 32 
2101             n 
= wxMax( 32 , ((byteInLen 
/ SIZEOF_WCHAR_T
) * 8) + SIZEOF_WCHAR_T 
); 
2102             tbuf 
= (char*) malloc( n 
) ; 
2105         ByteCount byteBufferLen 
= n 
; 
2106         UniChar
* ubuf 
= NULL 
; 
2107 #if SIZEOF_WCHAR_T == 4 
2108         wxMBConvUTF16BE converter 
; 
2109         size_t unicharlen 
= converter
.WC2MB( NULL 
, psz 
, 0 ) ; 
2110         byteInLen 
= unicharlen 
; 
2111         ubuf 
= (UniChar
*) malloc( byteInLen 
+ 2 ) ; 
2112         converter
.WC2MB( (char*) ubuf 
, psz
, unicharlen 
+ 2 ) ; 
2114         ubuf 
= (UniChar
*) psz 
; 
2116         status 
= TECConvertText(m_WC2MB_converter
, (ConstTextPtr
) ubuf 
, byteInLen
, &byteInLen
, 
2117             (TextPtr
) (buf 
? buf 
: tbuf
) , byteBufferLen
, &byteOutLen
); 
2118 #if SIZEOF_WCHAR_T == 4 
2124         size_t res 
= byteOutLen 
; 
2125         if ( buf  
&& res 
< n
) 
2129             //we need to double-trip to verify it didn't insert any ? in place 
2130             //of bogus characters 
2131             wxWCharBuffer 
wcBuf(n
); 
2132             size_t pszlen 
= wxWcslen(psz
); 
2133             if ( MB2WC(wcBuf
.data(), buf
, n
) == (size_t)-1 || 
2134                         wxWcslen(wcBuf
) != pszlen 
|| 
2135                         memcmp(wcBuf
, psz
, pszlen 
* sizeof(wchar_t)) != 0 ) 
2137                 // we didn't obtain the same thing we started from, hence 
2138                 // the conversion was lossy and we consider that it failed 
2147         { return m_MB2WC_converter 
!=  NULL 
&& m_WC2MB_converter 
!= NULL  
; } 
2150     TECObjectRef m_MB2WC_converter 
; 
2151     TECObjectRef m_WC2MB_converter 
; 
2153     TextEncodingBase m_char_encoding 
; 
2154     TextEncodingBase m_unicode_encoding 
; 
2157 #endif // defined(__WXMAC__) && defined(TARGET_CARBON) 
2159 // ============================================================================ 
2160 // wxEncodingConverter based conversion classes 
2161 // ============================================================================ 
2165 class wxMBConv_wxwin 
: public wxMBConv
 
2170         m_ok 
= m2w
.Init(m_enc
, wxFONTENCODING_UNICODE
) && 
2171                w2m
.Init(wxFONTENCODING_UNICODE
, m_enc
); 
2175     // temporarily just use wxEncodingConverter stuff, 
2176     // so that it works while a better implementation is built 
2177     wxMBConv_wxwin(const wxChar
* name
) 
2180             m_enc 
= wxFontMapper::Get()->CharsetToEncoding(name
, false); 
2182             m_enc 
= wxFONTENCODING_SYSTEM
; 
2187     wxMBConv_wxwin(wxFontEncoding enc
) 
2194     size_t MB2WC(wchar_t *buf
, const char *psz
, size_t WXUNUSED(n
)) const 
2196         size_t inbuf 
= strlen(psz
); 
2198             m2w
.Convert(psz
,buf
); 
2202     size_t WC2MB(char *buf
, const wchar_t *psz
, size_t WXUNUSED(n
)) const 
2204         const size_t inbuf 
= wxWcslen(psz
); 
2206             w2m
.Convert(psz
,buf
); 
2211     bool IsOk() const { return m_ok
; } 
2214     wxFontEncoding m_enc
; 
2215     wxEncodingConverter m2w
, w2m
; 
2217     // were we initialized successfully? 
2220     DECLARE_NO_COPY_CLASS(wxMBConv_wxwin
) 
2223 #endif // wxUSE_FONTMAP 
2225 // ============================================================================ 
2226 // wxCSConv implementation 
2227 // ============================================================================ 
2229 void wxCSConv::Init() 
2236 wxCSConv::wxCSConv(const wxChar 
*charset
) 
2245     m_encoding 
= wxFONTENCODING_SYSTEM
; 
2248 wxCSConv::wxCSConv(wxFontEncoding encoding
) 
2250     if ( encoding 
== wxFONTENCODING_MAX 
|| encoding 
== wxFONTENCODING_DEFAULT 
) 
2252         wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") ); 
2254         encoding 
= wxFONTENCODING_SYSTEM
; 
2259     m_encoding 
= encoding
; 
2262 wxCSConv::~wxCSConv() 
2267 wxCSConv::wxCSConv(const wxCSConv
& conv
) 
2272     SetName(conv
.m_name
); 
2273     m_encoding 
= conv
.m_encoding
; 
2276 wxCSConv
& wxCSConv::operator=(const wxCSConv
& conv
) 
2280     SetName(conv
.m_name
); 
2281     m_encoding 
= conv
.m_encoding
; 
2286 void wxCSConv::Clear() 
2295 void wxCSConv::SetName(const wxChar 
*charset
) 
2299         m_name 
= wxStrdup(charset
); 
2304 wxMBConv 
*wxCSConv::DoCreate() const 
2306     // check for the special case of ASCII or ISO8859-1 charset: as we have 
2307     // special knowledge of it anyhow, we don't need to create a special 
2308     // conversion object 
2309     if ( m_encoding 
== wxFONTENCODING_ISO8859_1 
) 
2311         // don't convert at all 
2315     // we trust OS to do conversion better than we can so try external 
2316     // conversion methods first 
2318     // the full order is: 
2319     //      1. OS conversion (iconv() under Unix or Win32 API) 
2320     //      2. hard coded conversions for UTF 
2321     //      3. wxEncodingConverter as fall back 
2327 #endif // !wxUSE_FONTMAP 
2329         wxString 
name(m_name
); 
2333             name 
= wxFontMapper::Get()->GetEncodingName(m_encoding
); 
2334 #endif // wxUSE_FONTMAP 
2336         wxMBConv_iconv 
*conv 
= new wxMBConv_iconv(name
); 
2342 #endif // HAVE_ICONV 
2344 #ifdef wxHAVE_WIN32_MB2WC 
2347         wxMBConv_win32 
*conv 
= m_name 
? new wxMBConv_win32(m_name
) 
2348                                       : new wxMBConv_win32(m_encoding
); 
2357 #endif // wxHAVE_WIN32_MB2WC 
2358 #if defined(__WXMAC__) 
2360         if ( m_name 
|| ( m_encoding 
< wxFONTENCODING_UTF16BE 
) ) 
2363             wxMBConv_mac 
*conv 
= m_name 
? new wxMBConv_mac(m_name
) 
2364                                         : new wxMBConv_mac(m_encoding
); 
2372 #if defined(__WXCOCOA__) 
2374         if ( m_name 
|| ( m_encoding 
<= wxFONTENCODING_UTF16 
) ) 
2377             wxMBConv_cocoa 
*conv 
= m_name 
? new wxMBConv_cocoa(m_name
) 
2378                                           : new wxMBConv_cocoa(m_encoding
); 
2387     wxFontEncoding enc 
= m_encoding
; 
2389     if ( enc 
== wxFONTENCODING_SYSTEM 
&& m_name 
) 
2391         // use "false" to suppress interactive dialogs -- we can be called from 
2392         // anywhere and popping up a dialog from here is the last thing we want to 
2394         enc 
= wxFontMapper::Get()->CharsetToEncoding(m_name
, false); 
2396 #endif // wxUSE_FONTMAP 
2400         case wxFONTENCODING_UTF7
: 
2401              return new wxMBConvUTF7
; 
2403         case wxFONTENCODING_UTF8
: 
2404              return new wxMBConvUTF8
; 
2406         case wxFONTENCODING_UTF16BE
: 
2407              return new wxMBConvUTF16BE
; 
2409         case wxFONTENCODING_UTF16LE
: 
2410              return new wxMBConvUTF16LE
; 
2412         case wxFONTENCODING_UTF32BE
: 
2413              return new wxMBConvUTF32BE
; 
2415         case wxFONTENCODING_UTF32LE
: 
2416              return new wxMBConvUTF32LE
; 
2419              // nothing to do but put here to suppress gcc warnings 
2426         wxMBConv_wxwin 
*conv 
= m_name 
? new wxMBConv_wxwin(m_name
) 
2427                                       : new wxMBConv_wxwin(m_encoding
); 
2433 #endif // wxUSE_FONTMAP 
2435     // NB: This is a hack to prevent deadlock. What could otherwise happen 
2436     //     in Unicode build: wxConvLocal creation ends up being here 
2437     //     because of some failure and logs the error. But wxLog will try to 
2438     //     attach timestamp, for which it will need wxConvLocal (to convert 
2439     //     time to char* and then wchar_t*), but that fails, tries to log 
2440     //     error, but wxLog has a (already locked) critical section that 
2441     //     guards static buffer. 
2442     static bool alreadyLoggingError 
= false; 
2443     if (!alreadyLoggingError
) 
2445         alreadyLoggingError 
= true; 
2446         wxLogError(_("Cannot convert from the charset '%s'!"), 
2450                          wxFontMapper::GetEncodingDescription(m_encoding
).c_str() 
2451 #else // !wxUSE_FONTMAP 
2452                          wxString::Format(_("encoding %s"), m_encoding
).c_str() 
2453 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP 
2455         alreadyLoggingError 
= false; 
2461 void wxCSConv::CreateConvIfNeeded() const 
2465         wxCSConv 
*self 
= (wxCSConv 
*)this; // const_cast 
2468         // if we don't have neither the name nor the encoding, use the default 
2469         // encoding for this system 
2470         if ( !m_name 
&& m_encoding 
== wxFONTENCODING_SYSTEM 
) 
2472             self
->m_name 
= wxStrdup(wxLocale::GetSystemEncodingName()); 
2474 #endif // wxUSE_INTL 
2476         self
->m_convReal 
= DoCreate(); 
2477         self
->m_deferred 
= false; 
2481 size_t wxCSConv::MB2WC(wchar_t *buf
, const char *psz
, size_t n
) const 
2483     CreateConvIfNeeded(); 
2486         return m_convReal
->MB2WC(buf
, psz
, n
); 
2489     size_t len 
= strlen(psz
); 
2493         for (size_t c 
= 0; c 
<= len
; c
++) 
2494             buf
[c
] = (unsigned char)(psz
[c
]); 
2500 size_t wxCSConv::WC2MB(char *buf
, const wchar_t *psz
, size_t n
) const 
2502     CreateConvIfNeeded(); 
2505         return m_convReal
->WC2MB(buf
, psz
, n
); 
2508     const size_t len 
= wxWcslen(psz
); 
2511         for (size_t c 
= 0; c 
<= len
; c
++) 
2515             buf
[c
] = (char)psz
[c
]; 
2520         for (size_t c 
= 0; c 
<= len
; c
++) 
2530 // ---------------------------------------------------------------------------- 
2532 // ---------------------------------------------------------------------------- 
2535     static wxMBConv_win32 wxConvLibcObj
; 
2536 #elif defined(__WXMAC__) && !defined(__MACH__) 
2537     static wxMBConv_mac wxConvLibcObj 
; 
2539     static wxMBConvLibc wxConvLibcObj
; 
2542 static wxCSConv 
wxConvLocalObj(wxFONTENCODING_SYSTEM
); 
2543 static wxCSConv 
wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1
); 
2544 static wxMBConvUTF7 wxConvUTF7Obj
; 
2545 static wxMBConvUTF8 wxConvUTF8Obj
; 
2548 WXDLLIMPEXP_DATA_BASE(wxMBConv
&) wxConvLibc 
= wxConvLibcObj
; 
2549 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvLocal 
= wxConvLocalObj
; 
2550 WXDLLIMPEXP_DATA_BASE(wxCSConv
&) wxConvISO8859_1 
= wxConvISO8859_1Obj
; 
2551 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7
&) wxConvUTF7 
= wxConvUTF7Obj
; 
2552 WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8
&) wxConvUTF8 
= wxConvUTF8Obj
; 
2553 WXDLLIMPEXP_DATA_BASE(wxMBConv 
*) wxConvCurrent 
= &wxConvLibcObj
; 
2555 #else // !wxUSE_WCHAR_T 
2557 // stand-ins in absence of wchar_t 
2558 WXDLLIMPEXP_DATA_BASE(wxMBConv
) wxConvLibc
, 
2563 #endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T