1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxEncodingConverter class for converting between different 
   5 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  17 #include "wx/encconv.h" 
  21 // conversion tables, generated by scripts in $(WXWIN)/misc/unictabl: 
  22 #if defined( __BORLANDC__ ) || defined(__DARWIN__) 
  23     #include "../common/unictabl.inc" 
  25     #include "unictabl.inc" 
  29     typedef wchar_t tchar
; 
  36 #include <Carbon/Carbon.h> 
  38 #include <ATSUnicode.h> 
  39 #include <TextCommon.h> 
  40 #include <TextEncodingConverter.h> 
  42     #include "wx/fontutil.h" 
  43     #include "wx/mac/private.h"  // includes mac headers 
  45     wxUint16 gMacEncodings
[wxFONTENCODING_MACMAX
-wxFONTENCODING_MACMIN
+1][128] ; 
  46     bool gMacEncodingsInited
[wxFONTENCODING_MACMAX
-wxFONTENCODING_MACMIN
+1] ; 
  50     #include "wx/msw/wince/missing.h"       // for bsearch() 
  53 static wxUint16
* GetEncTable(wxFontEncoding enc
) 
  56     if( enc 
>= wxFONTENCODING_MACMIN 
&& enc 
<= wxFONTENCODING_MACMAX 
) 
  58         int i 
= enc
-wxFONTENCODING_MACMIN 
; 
  59         if ( gMacEncodingsInited
[i
] == false ) 
  61             TECObjectRef converter 
; 
  62             TextEncodingBase code 
= wxMacGetSystemEncFromFontEnc( enc 
) ; 
  63             TextEncodingBase unicode 
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ; 
  64             OSStatus status 
= TECCreateConverter(&converter
,code
,unicode
); 
  67             ByteCount byteInLen
, byteOutLen 
; 
  68             for( unsigned char c 
= 255 ; c 
>= 128 ; --c 
) 
  71                 status 
= TECConvertText(converter
, (ConstTextPtr
) &s 
, 1, &byteInLen
, 
  72                 (TextPtr
) &gMacEncodings
[i
][c
-128] , 2, &byteOutLen
); 
  74             status 
= TECDisposeConverter(converter
); 
  75             gMacEncodingsInited
[i
]=true; 
  77         return gMacEncodings
[i
] ; 
  81     for (int i 
= 0; encodings_list
[i
].table 
!= NULL
; i
++) 
  83         if (encodings_list
[i
].encoding 
== enc
) 
  84             return encodings_list
[i
].table
; 
  94 extern "C" int wxCMPFUNC_CONV
 
  95 CompareCharsetItems(const void *i1
, const void *i2
) 
  97     return ( ((CharsetItem
*)i1
) -> u 
- ((CharsetItem
*)i2
) -> u 
); 
 101 static CharsetItem
* BuildReverseTable(wxUint16 
*tbl
) 
 103     CharsetItem 
*rev 
= new CharsetItem
[128]; 
 105     for (int i 
= 0; i 
< 128; i
++) 
 106         rev
[i
].c 
= wxUint8(128 + i
), rev
[i
].u 
= tbl
[i
]; 
 108     qsort(rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
 115 wxEncodingConverter::wxEncodingConverter() 
 118     m_UnicodeInput 
= m_UnicodeOutput 
= false; 
 124 bool wxEncodingConverter::Init(wxFontEncoding input_enc
, wxFontEncoding output_enc
, int method
) 
 127     wxUint16 
*in_tbl
, *out_tbl 
= NULL
; 
 129     if (m_Table
) {delete[] m_Table
; m_Table 
= NULL
;} 
 132     if (input_enc 
== wxFONTENCODING_UNICODE 
|| output_enc 
== wxFONTENCODING_UNICODE
) return false; 
 135     if (input_enc 
== output_enc
) {m_JustCopy 
= true; return true;} 
 137     m_UnicodeOutput 
= (output_enc 
== wxFONTENCODING_UNICODE
); 
 140     if (input_enc 
== wxFONTENCODING_UNICODE
) 
 142         if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return false; 
 144         m_Table 
= new tchar
[65536]; 
 145         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 146         for (i 
= 128; i 
< 65536; i
++)  m_Table
[i
] = (tchar
)0; 
 148         if (method 
== wxCONVERT_SUBSTITUTE
) 
 150             for (i 
= 0; i 
< encoding_unicode_fallback_count
; i
++) 
 151                 m_Table
[encoding_unicode_fallback
[i
].c
] = (tchar
) encoding_unicode_fallback
[i
].s
; 
 154         for (i 
= 0; i 
< 128; i
++) 
 155             m_Table
[out_tbl
[i
]] = (tchar
)(128 + i
); 
 157         m_UnicodeInput 
= true; 
 159     else // input !Unicode 
 161         if ((in_tbl 
= GetEncTable(input_enc
)) == NULL
) return false; 
 162         if (output_enc 
!= wxFONTENCODING_UNICODE
) 
 163             if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return false; 
 165         m_UnicodeInput 
= false; 
 167         m_Table 
= new tchar
[256]; 
 168         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 170         if (output_enc 
== wxFONTENCODING_UNICODE
) 
 172             for (i 
= 0; i 
< 128; i
++)  m_Table
[128 + i
] = (tchar
)in_tbl
[i
]; 
 175         else // output !Unicode 
 177             CharsetItem 
*rev 
= BuildReverseTable(out_tbl
); 
 181             for (i 
= 0; i 
< 128; i
++) 
 184                 item 
= (CharsetItem
*) bsearch(&key
, rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
 185                 if (item 
== NULL 
&& method 
== wxCONVERT_SUBSTITUTE
) 
 186                     item 
= (CharsetItem
*) bsearch(&key
, encoding_unicode_fallback
, 
 187                                 encoding_unicode_fallback_count
, sizeof(CharsetItem
), CompareCharsetItems
); 
 189                     m_Table
[128 + i
] = (tchar
)item 
-> c
; 
 192                     m_Table
[128 + i
] = (wchar_t)(128 + i
); 
 194                     m_Table
[128 + i
] = (char)(128 + i
); 
 206 #define REPLACEMENT_CHAR  ((tchar)'?') 
 208 inline tchar 
GetTableValue(const tchar 
*table
, tchar value
, bool& repl
) 
 210     tchar r 
= table
[value
]; 
 211     if (r 
== 0 && value 
!= 0) 
 213         r 
= REPLACEMENT_CHAR
; 
 220 bool wxEncodingConverter::Convert(const char* input
, char* output
) const 
 222     wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!")); 
 223     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 230         strcpy(output
, input
); 
 234     wxCHECK_MSG(m_Table 
!= NULL
, false, 
 235                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 237     bool replaced 
= false; 
 239     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 240         *(o
++) = (char)(GetTableValue(m_Table
, (wxUint8
)*(i
++), replaced
)); 
 249 bool wxEncodingConverter::Convert(const char* input
, wchar_t* output
) const 
 251     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 252     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 259         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 260             *(o
++) = (wchar_t)(*(i
++)); 
 265     wxCHECK_MSG(m_Table 
!= NULL
, false, 
 266                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 268     bool replaced 
= false; 
 270     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 271         *(o
++) = (wchar_t)(GetTableValue(m_Table
, (wxUint8
)*(i
++), replaced
)); 
 279 bool wxEncodingConverter::Convert(const wchar_t* input
, char* output
) const 
 281     wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!")); 
 282     wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!")); 
 289         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 290             *(o
++) = (char)(*(i
++)); 
 295     wxCHECK_MSG(m_Table 
!= NULL
, false, 
 296                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 298     bool replaced 
= false; 
 300     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 301         *(o
++) = (char)(GetTableValue(m_Table
, (wxUint16
)*(i
++), replaced
)); 
 309 bool wxEncodingConverter::Convert(const wchar_t* input
, wchar_t* output
) const 
 311     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 312     wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!")); 
 319         // wcscpy() is not guaranteed to exist 
 320         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 326     wxCHECK_MSG(m_Table 
!= NULL
, false, 
 327                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 329     bool replaced 
= false; 
 331     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 332         *(o
++) = (wchar_t)(GetTableValue(m_Table
, (wxUint8
)*(i
++), replaced
)); 
 338 #endif // wxUSE_WCHAR_T 
 341 wxString 
wxEncodingConverter::Convert(const wxString
& input
) const 
 343     if (m_JustCopy
) return input
; 
 348     wxCHECK_MSG(m_Table 
!= NULL
, s
, 
 349                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 353         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 354             s 
<< (wxChar
)(m_Table
[(wxUint16
)*i
]); 
 358         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 359             s 
<< (wxChar
)(m_Table
[(wxUint8
)*i
]); 
 371 // Following tables describe classes of encoding equivalence. 
 374 #define STOP wxFONTENCODING_SYSTEM 
 376 #define NUM_OF_PLATFORMS  4 /*must conform to enum wxPLATFORM_XXXX !!!*/ 
 377 #define ENC_PER_PLATFORM  5 
 378            // max no. of encodings for one language used on one platform 
 379            // Anybody thinks 5 is not enough? ;-) 
 381 static wxFontEncoding
 
 382     EquivalentEncodings
[][NUM_OF_PLATFORMS
][ENC_PER_PLATFORM
+1] = { 
 384     // *** Please put more common encodings as first! *** 
 388         /* unix    */ {wxFONTENCODING_ISO8859_1
, wxFONTENCODING_ISO8859_15
, STOP
}, 
 389         /* windows */ {wxFONTENCODING_CP1252
, STOP
}, 
 391         /* mac     */ {wxFONTENCODING_MACROMAN
, STOP
} 
 396         /* unix    */ {wxFONTENCODING_ISO8859_2
, STOP
}, 
 397         /* windows */ {wxFONTENCODING_CP1250
, STOP
}, 
 399         /* mac     */ {wxFONTENCODING_MACCENTRALEUR
, STOP
} 
 404         /* unix    */ {wxFONTENCODING_ISO8859_13
, wxFONTENCODING_ISO8859_4
, STOP
}, 
 405         /* windows */ {wxFONTENCODING_CP1257
, STOP
}, 
 412         /* unix    */ {wxFONTENCODING_ISO8859_8
, STOP
}, 
 413         /* windows */ {wxFONTENCODING_CP1255
, STOP
}, 
 415         /* mac     */ {wxFONTENCODING_MACHEBREW
, STOP
} 
 420         /* unix    */ {wxFONTENCODING_ISO8859_7
, STOP
}, 
 421         /* windows */ {wxFONTENCODING_CP1253
, STOP
}, 
 423         /* mac     */ {wxFONTENCODING_MACGREEK
, STOP
} 
 428         /* unix    */ {wxFONTENCODING_ISO8859_6
, STOP
}, 
 429         /* windows */ {wxFONTENCODING_CP1256
, STOP
}, 
 431         /* mac     */ {wxFONTENCODING_MACARABIC
, STOP
} 
 436         /* unix    */ {wxFONTENCODING_ISO8859_9
, STOP
}, 
 437         /* windows */ {wxFONTENCODING_CP1254
, STOP
}, 
 439         /* mac     */ {wxFONTENCODING_MACTURKISH
, STOP
} 
 444         /* unix    */ {wxFONTENCODING_KOI8
, wxFONTENCODING_KOI8_U
, wxFONTENCODING_ISO8859_5
, STOP
}, 
 445         /* windows */ {wxFONTENCODING_CP1251
, STOP
}, 
 447         /* mac     */ {wxFONTENCODING_MACCYRILLIC
, STOP
} 
 450     {{STOP
},{STOP
},{STOP
},{STOP
}} /* Terminator */ 
 451     /* no, _not_ Arnold! */ 
 455 static bool FindEncoding(const wxFontEncodingArray
& arr
, wxFontEncoding f
) 
 457     for (wxFontEncodingArray::const_iterator it 
= arr
.begin(), en 
= arr
.end(); 
 464 wxFontEncodingArray 
wxEncodingConverter::GetPlatformEquivalents(wxFontEncoding enc
, int platform
) 
 466     if (platform 
== wxPLATFORM_CURRENT
) 
 468 #if defined(__WXMSW__) 
 469         platform 
= wxPLATFORM_WINDOWS
; 
 470 #elif defined(__WXGTK__) || defined(__WXMOTIF__) 
 471         platform 
= wxPLATFORM_UNIX
; 
 472 #elif defined(__WXPM__) 
 473         platform 
= wxPLATFORM_OS2
; 
 474 #elif defined(__WXMAC__) 
 475         platform 
= wxPLATFORM_MAC
; 
 481     wxFontEncodingArray arr
; 
 484     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 486         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 487             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 488                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 490                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 491                         if (*f 
== enc
) arr
.push_back(enc
); 
 492                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 493                         if (!FindEncoding(arr
, *f
)) arr
.push_back(*f
); 
 494                     i 
= NUM_OF_PLATFORMS
/*hack*/; break; 
 504 wxFontEncodingArray 
wxEncodingConverter::GetAllEquivalents(wxFontEncoding enc
) 
 508     wxFontEncodingArray arr
; 
 510     arr 
= GetPlatformEquivalents(enc
); // we want them to be first items in array 
 513     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 515         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 516             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 517                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 519                     for (j 
= 0; j 
< NUM_OF_PLATFORMS
; j
++) 
 520                         for (f 
= EquivalentEncodings
[clas
][j
]; *f 
!= STOP
; f
++) 
 521                             if (!FindEncoding(arr
, *f
)) arr
.push_back(*f
); 
 522                     i 
= NUM_OF_PLATFORMS
/*hack*/; break;