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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  11 #pragma implementation "encconv.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  23 #include "wx/encconv.h" 
  27 // conversion tables, generated by scripts in $(WXWIN)/misc/unictabl: 
  28 #if defined( __BORLANDC__ ) || defined(__DARWIN__) 
  29 #include "../common/unictabl.inc" 
  31 #include "unictabl.inc" 
  35 typedef wchar_t tchar
; 
  42 #define LINKAGEMODE __cdecl 
  47 #include "ATSUnicode.h" 
  48 #include "TextCommon.h" 
  49 #include "TextEncodingConverter.h" 
  51 #include "wx/fontutil.h" 
  52 #include "wx/mac/private.h"  // includes mac headers 
  54 wxUint16 gMacEncodings
[wxFONTENCODING_MACMAX
-wxFONTENCODING_MACMIN
+1][128] ; 
  55 bool gMacEncodingsInited
[wxFONTENCODING_MACMAX
-wxFONTENCODING_MACMIN
+1] ; 
  59 static wxUint16
* LINKAGEMODE 
GetEncTable(wxFontEncoding enc
) 
  62     if( enc 
>= wxFONTENCODING_MACMIN 
&& enc 
<= wxFONTENCODING_MACMAX 
) 
  64         int i 
= enc
-wxFONTENCODING_MACMIN 
; 
  65         if ( gMacEncodingsInited
[i
] == false ) 
  67             TECObjectRef converter 
; 
  68             TextEncodingBase code 
= wxMacGetSystemEncFromFontEnc( enc 
) ; 
  69                 TextEncodingBase unicode 
= CreateTextEncoding(kTextEncodingUnicodeDefault
,0,kUnicode16BitFormat
) ; 
  70             OSStatus status 
= TECCreateConverter(&converter
,code
,unicode
); 
  73             ByteCount byteInLen
, byteOutLen 
; 
  74             for( unsigned char c 
= 255 ; c 
>= 128 ; --c 
) 
  77                 status 
= TECConvertText(converter
, (ConstTextPtr
) &s 
, 1, &byteInLen
, 
  78                 (TextPtr
) &gMacEncodings
[i
][c
-128] , 2, &byteOutLen
); 
  80             status 
= TECDisposeConverter(converter
); 
  81             gMacEncodingsInited
[i
]=true;         
  83         return gMacEncodings
[i
] ; 
  87     for (int i 
= 0; encodings_list
[i
].table 
!= NULL
; i
++) 
  89         if (encodings_list
[i
].encoding 
== enc
) 
  90             return encodings_list
[i
].table
; 
 100 extern "C" int LINKAGEMODE 
CompareCharsetItems(const void *i1
, const void *i2
) 
 102     return ( ((CharsetItem
*)i1
) -> u 
- ((CharsetItem
*)i2
) -> u 
); 
 106 static CharsetItem
* LINKAGEMODE 
BuildReverseTable(wxUint16 
*tbl
) 
 108     CharsetItem 
*rev 
= new CharsetItem
[128]; 
 110     for (int i 
= 0; i 
< 128; i
++) 
 111         rev
[i
].c 
= 128 + i
, rev
[i
].u 
= tbl
[i
]; 
 113     qsort(rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
 120 wxEncodingConverter::wxEncodingConverter() 
 123     m_UnicodeInput 
= m_UnicodeOutput 
= FALSE
; 
 129 bool wxEncodingConverter::Init(wxFontEncoding input_enc
, wxFontEncoding output_enc
, int method
) 
 132     wxUint16 
*in_tbl
, *out_tbl 
= NULL
; 
 134     if (m_Table
) {delete[] m_Table
; m_Table 
= NULL
;} 
 137     if (input_enc 
== wxFONTENCODING_UNICODE 
|| output_enc 
== wxFONTENCODING_UNICODE
) return FALSE
; 
 140     if (input_enc 
== output_enc
) {m_JustCopy 
= TRUE
; return TRUE
;} 
 142     m_UnicodeOutput 
= (output_enc 
== wxFONTENCODING_UNICODE
); 
 145     if (input_enc 
== wxFONTENCODING_UNICODE
) 
 147         if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return FALSE
; 
 149         m_Table 
= new tchar
[65536]; 
 150         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 151         for (i 
= 128; i 
< 65536; i
++)  m_Table
[i
] = (tchar
)'?'; 
 152                 // FIXME - this should be character that means `unicode to charset' impossible, not '?' 
 154         if (method 
== wxCONVERT_SUBSTITUTE
) 
 156             for (i 
= 0; i 
< encoding_unicode_fallback_count
; i
++) 
 157                 m_Table
[encoding_unicode_fallback
[i
].c
] = (tchar
) encoding_unicode_fallback
[i
].s
; 
 160         for (i 
= 0; i 
< 128; i
++) 
 161             m_Table
[out_tbl
[i
]] = (tchar
)(128 + i
); 
 163         m_UnicodeInput 
= TRUE
; 
 165     else // input !Unicode 
 167         if ((in_tbl 
= GetEncTable(input_enc
)) == NULL
) return FALSE
; 
 168         if (output_enc 
!= wxFONTENCODING_UNICODE
) 
 169             if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return FALSE
; 
 171         m_UnicodeInput 
= FALSE
; 
 173         m_Table 
= new tchar
[256]; 
 174         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 176         if (output_enc 
== wxFONTENCODING_UNICODE
) 
 178             for (i 
= 0; i 
< 128; i
++)  m_Table
[128 + i
] = (tchar
)in_tbl
[i
]; 
 181         // FIXME: write a substitute for bsearch 
 183         else // output !Unicode 
 185             CharsetItem 
*rev 
= BuildReverseTable(out_tbl
); 
 189             for (i 
= 0; i 
< 128; i
++) 
 192                 item 
= (CharsetItem
*) bsearch(&key
, rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
 193                 if (item 
== NULL 
&& method 
== wxCONVERT_SUBSTITUTE
) 
 194                     item 
= (CharsetItem
*) bsearch(&key
, encoding_unicode_fallback
, 
 195                                 encoding_unicode_fallback_count
, sizeof(CharsetItem
), CompareCharsetItems
); 
 197                     m_Table
[128 + i
] = (tchar
)item 
-> c
; 
 200                     m_Table
[128 + i
] = (wchar_t)(128 + i
); 
 202                     m_Table
[128 + i
] = (char)(128 + i
); 
 208 #endif // !__WXWINCE__ 
 216 void wxEncodingConverter::Convert(const char* input
, char* output
) const 
 218     wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!")); 
 219     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 226         strcpy(output
, input
); 
 230     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 232     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 233         *(o
++) = (char)(m_Table
[(wxUint8
)*(i
++)]); 
 240 void wxEncodingConverter::Convert(const char* input
, wchar_t* output
) const 
 242     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 243     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 250         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 251             *(o
++) = (wchar_t)(*(i
++)); 
 256     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 258     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 259         *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]); 
 265 void wxEncodingConverter::Convert(const wchar_t* input
, char* output
) const 
 267     wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!")); 
 268     wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!")); 
 275         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 276             *(o
++) = (char)(*(i
++)); 
 281     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 283     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 284         *(o
++) = (char)(m_Table
[(wxUint16
)*(i
++)]); 
 290 void wxEncodingConverter::Convert(const wchar_t* input
, wchar_t* output
) const 
 292     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 293     wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!")); 
 300         // wcscpy() is not guaranteed to exist 
 301         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 307     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 309     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 310         *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]); 
 314 #endif // wxUSE_WCHAR_T 
 317 wxString 
wxEncodingConverter::Convert(const wxString
& input
) const 
 319     if (m_JustCopy
) return input
; 
 324     wxCHECK_MSG(m_Table 
!= NULL
, s
, 
 325                 wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 329         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 330             s 
<< (wxChar
)(m_Table
[(wxUint16
)*i
]); 
 334         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 335             s 
<< (wxChar
)(m_Table
[(wxUint8
)*i
]); 
 347 // Following tables describe classes of encoding equivalence. 
 350 #define STOP wxFONTENCODING_SYSTEM 
 352 #define NUM_OF_PLATFORMS  4 /*must conform to enum wxPLATFORM_XXXX !!!*/ 
 353 #define ENC_PER_PLATFORM  5 
 354            // max no. of encodings for one language used on one platform 
 355            // Anybody thinks 5 is not enough? ;-) 
 357 static wxFontEncoding
 
 358     EquivalentEncodings
[][NUM_OF_PLATFORMS
][ENC_PER_PLATFORM
+1] = { 
 360     // *** Please put more common encodings as first! *** 
 364         /* unix    */ {wxFONTENCODING_ISO8859_1
, wxFONTENCODING_ISO8859_15
, STOP
}, 
 365         /* windows */ {wxFONTENCODING_CP1252
, STOP
}, 
 367         /* mac     */ {wxFONTENCODING_MACROMAN
, STOP
} 
 372         /* unix    */ {wxFONTENCODING_ISO8859_2
, STOP
}, 
 373         /* windows */ {wxFONTENCODING_CP1250
, STOP
}, 
 375         /* mac     */ {wxFONTENCODING_MACCENTRALEUR
, STOP
} 
 380         /* unix    */ {wxFONTENCODING_ISO8859_13
, wxFONTENCODING_ISO8859_4
, STOP
}, 
 381         /* windows */ {wxFONTENCODING_CP1257
, STOP
}, 
 388         /* unix    */ {wxFONTENCODING_ISO8859_8
, STOP
}, 
 389         /* windows */ {wxFONTENCODING_CP1255
, STOP
}, 
 391         /* mac     */ {wxFONTENCODING_MACHEBREW
, STOP
} 
 396         /* unix    */ {wxFONTENCODING_ISO8859_7
, STOP
}, 
 397         /* windows */ {wxFONTENCODING_CP1253
, STOP
}, 
 399         /* mac     */ {wxFONTENCODING_MACGREEK
, STOP
} 
 404         /* unix    */ {wxFONTENCODING_ISO8859_6
, STOP
}, 
 405         /* windows */ {wxFONTENCODING_CP1256
, STOP
}, 
 407         /* mac     */ {wxFONTENCODING_MACARABIC
, STOP
} 
 412         /* unix    */ {wxFONTENCODING_ISO8859_9
, STOP
}, 
 413         /* windows */ {wxFONTENCODING_CP1254
, STOP
}, 
 415         /* mac     */ {wxFONTENCODING_MACTURKISH
, STOP
} 
 420         /* unix    */ {wxFONTENCODING_KOI8
, wxFONTENCODING_ISO8859_5
, STOP
}, 
 421         /* windows */ {wxFONTENCODING_CP1251
, STOP
}, 
 423         /* mac     */ {wxFONTENCODING_MACCYRILLIC
, STOP
} 
 426     {{STOP
},{STOP
},{STOP
},{STOP
}} /* Terminator */ 
 427     /* no, _not_ Arnold! */ 
 431 static bool FindEncoding(const wxFontEncodingArray
& arr
, wxFontEncoding f
) 
 433     for (wxFontEncodingArray::const_iterator it 
= arr
.begin(), en 
= arr
.end(); 
 440 wxFontEncodingArray 
wxEncodingConverter::GetPlatformEquivalents(wxFontEncoding enc
, int platform
) 
 442     if (platform 
== wxPLATFORM_CURRENT
) 
 444 #if defined(__WXMSW__) 
 445         platform 
= wxPLATFORM_WINDOWS
; 
 446 #elif defined(__WXGTK__) || defined(__WXMOTIF__) 
 447         platform 
= wxPLATFORM_UNIX
; 
 448 #elif defined(__WXOS2__) 
 449         platform 
= wxPLATFORM_OS2
; 
 450 #elif defined(__WXMAC__) 
 451         platform 
= wxPLATFORM_MAC
; 
 457     wxFontEncodingArray arr
; 
 460     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 462         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 463             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 464                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 466                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 467                         if (*f 
== enc
) arr
.push_back(enc
); 
 468                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 469                         if (!FindEncoding(arr
, *f
)) arr
.push_back(*f
); 
 470                     i 
= NUM_OF_PLATFORMS
/*hack*/; break; 
 480 wxFontEncodingArray 
wxEncodingConverter::GetAllEquivalents(wxFontEncoding enc
) 
 484     wxFontEncodingArray arr
; 
 486     arr 
= GetPlatformEquivalents(enc
); // we want them to be first items in array 
 489     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 491         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 492             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 493                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 495                     for (j 
= 0; j 
< NUM_OF_PLATFORMS
; j
++) 
 496                         for (f 
= EquivalentEncodings
[clas
][j
]; *f 
!= STOP
; f
++) 
 497                             if (!FindEncoding(arr
, *f
)) arr
.push_back(*f
); 
 498                     i 
= NUM_OF_PLATFORMS
/*hack*/; break; 
 506 #endif // wxUSE_FONTMAP