1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxEncodingConverter class for converting between different 
   5 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik 
   7 // Licence:     wxWindows Licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  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: 
  29 #include "../common/unictabl.inc" 
  31 #include "unictabl.inc" 
  35 typedef wchar_t tchar
; 
  40 static wxUint16
* LINKAGEMODE 
GetEncTable(wxFontEncoding enc
) 
  42     for (int i 
= 0; encodings_list
[i
].table 
!= NULL
; i
++) 
  44         if (encodings_list
[i
].encoding 
== enc
) 
  45             return encodings_list
[i
].table
; 
  57 extern "C" int LINKAGEMODE 
CompareCharsetItems(const void *i1
, const void *i2
) 
  59     return ( ((CharsetItem
*)i1
) -> u 
- ((CharsetItem
*)i2
) -> u 
); 
  63 static CharsetItem
* LINKAGEMODE 
BuildReverseTable(wxUint16 
*tbl
) 
  65     CharsetItem 
*rev 
= new CharsetItem
[128]; 
  67     for (int i 
= 0; i 
< 128; i
++) 
  68         rev
[i
].c 
= 128 + i
, rev
[i
].u 
= tbl
[i
]; 
  70     qsort(rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
  77 wxEncodingConverter::wxEncodingConverter() 
  80     m_UnicodeInput 
= m_UnicodeOutput 
= FALSE
; 
  86 bool wxEncodingConverter::Init(wxFontEncoding input_enc
, wxFontEncoding output_enc
, int method
) 
  89     wxUint16 
*in_tbl 
= NULL
, *out_tbl 
= NULL
; 
  91     if (m_Table
) {delete[] m_Table
; m_Table 
= NULL
;} 
  94     if (input_enc 
== wxFONTENCODING_UNICODE 
|| output_enc 
== wxFONTENCODING_UNICODE
) return FALSE
; 
  97     if (input_enc 
== output_enc
) {m_JustCopy 
= TRUE
; return TRUE
;} 
  99     m_UnicodeOutput 
= (output_enc 
== wxFONTENCODING_UNICODE
); 
 102     if (input_enc 
== wxFONTENCODING_UNICODE
) 
 104         if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return FALSE
; 
 106         m_Table 
= new tchar
[65536]; 
 107         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 108         for (i 
= 128; i 
< 65536; i
++)  m_Table
[i
] = (tchar
)'?'; 
 109                 // FIXME - this should be character that means `unicode to charset' impossible, not '?' 
 111         if (method 
== wxCONVERT_SUBSTITUTE
) 
 113             for (i 
= 0; i 
< encoding_unicode_fallback_count
; i
++) 
 114                 m_Table
[encoding_unicode_fallback
[i
].c
] = (tchar
) encoding_unicode_fallback
[i
].s
; 
 117         for (i 
= 0; i 
< 128; i
++) 
 118             m_Table
[out_tbl
[i
]] = (tchar
)(128 + i
); 
 120         m_UnicodeInput 
= TRUE
; 
 126         if ((in_tbl 
= GetEncTable(input_enc
)) == NULL
) return FALSE
; 
 127         if (output_enc 
!= wxFONTENCODING_UNICODE
) 
 128             if ((out_tbl 
= GetEncTable(output_enc
)) == NULL
) return FALSE
; 
 130         m_UnicodeInput 
= FALSE
; 
 132         m_Table 
= new tchar
[256]; 
 133         for (i 
= 0; i 
< 128; i
++)  m_Table
[i
] = (tchar
)i
; // 7bit ASCII 
 135         if (output_enc 
== wxFONTENCODING_UNICODE
) 
 137             for (i 
= 0; i 
< 128; i
++)  m_Table
[128 + i
] = (tchar
)in_tbl
[i
]; 
 142             CharsetItem 
*rev 
= BuildReverseTable(out_tbl
); 
 146             for (i 
= 0; i 
< 128; i
++) 
 149                 item 
= (CharsetItem
*) bsearch(&key
, rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
); 
 150                 if (item 
== NULL 
&& method 
== wxCONVERT_SUBSTITUTE
) 
 151                     item 
= (CharsetItem
*) bsearch(&key
, encoding_unicode_fallback
, 
 152                                 encoding_unicode_fallback_count
, sizeof(CharsetItem
), CompareCharsetItems
); 
 154                     m_Table
[128 + i
] = (tchar
)item 
-> c
; 
 157                     m_Table
[128 + i
] = (wchar_t)(128 + i
); 
 159                     m_Table
[128 + i
] = (char)(128 + i
); 
 171 void wxEncodingConverter::Convert(const char* input
, char* output
) 
 173     wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!")); 
 174     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 181         strcpy(output
, input
); 
 185     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 187     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 188         *(o
++) = (char)(m_Table
[(wxUint8
)*(i
++)]); 
 195 void wxEncodingConverter::Convert(const char* input
, wchar_t* output
) 
 197     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 198     wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!")); 
 205         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 206             *(o
++) = (wchar_t)(*(i
++)); 
 211     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 213     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 214         *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]); 
 220 void wxEncodingConverter::Convert(const wchar_t* input
, char* output
) 
 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 8-bit if input is const wchar_t*!")); 
 230         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 231             *(o
++) = (char)(*(i
++)); 
 236     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 238     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 239         *(o
++) = (char)(m_Table
[(wxUint16
)*(i
++)]); 
 245 void wxEncodingConverter::Convert(const wchar_t* input
, wchar_t* output
) 
 247     wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!")); 
 248     wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!")); 
 255         // wcscpy() is not guaranteed to exist 
 256         for (i 
= input
, o 
= output
; *i 
!= 0;) 
 262     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 264     for (i 
= input
, o 
= output
; *i 
!= 0;) 
 265         *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]); 
 269 #endif // wxUSE_WCHAR_T 
 272 wxString 
wxEncodingConverter::Convert(const wxString
& input
) 
 274     if (m_JustCopy
) return input
; 
 279     wxCHECK_RET(m_Table 
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!")); 
 283         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 284             s 
<< (wxChar
)(m_Table
[(wxUint16
)*i
]); 
 288         for (i 
= input
.c_str(); *i 
!= 0; i
++) 
 289             s 
<< (wxChar
)(m_Table
[(wxUint8
)*i
]); 
 301 // Following tables describe classes of encoding equivalence. 
 304 #define STOP wxFONTENCODING_SYSTEM 
 306 #define NUM_OF_PLATFORMS  4 /*must conform to enum wxPLATFORM_XXXX !!!*/ 
 307 #define ENC_PER_PLATFORM  5 
 308            // max no. of encodings for one language used on one platform 
 309            // Anybody thinks 5 is not enough? ;-) 
 311 static wxFontEncoding
 
 312     EquivalentEncodings
[][NUM_OF_PLATFORMS
][ENC_PER_PLATFORM
+1] = { 
 314     // *** Please put more common encodings as first! *** 
 318         /* unix    */ {wxFONTENCODING_ISO8859_1
, wxFONTENCODING_ISO8859_15
, STOP
}, 
 319         /* windows */ {wxFONTENCODING_CP1252
, STOP
}, 
 326         /* unix    */ {wxFONTENCODING_ISO8859_2
, STOP
}, 
 327         /* windows */ {wxFONTENCODING_CP1250
, STOP
}, 
 334         /* unix    */ {wxFONTENCODING_ISO8859_13
, wxFONTENCODING_ISO8859_4
, STOP
}, 
 335         /* windows */ {wxFONTENCODING_CP1257
, STOP
}, 
 342         /* unix    */ {wxFONTENCODING_ISO8859_8
, STOP
}, 
 343         /* windows */ {wxFONTENCODING_CP1255
, STOP
}, 
 350         /* unix    */ {wxFONTENCODING_ISO8859_7
, STOP
}, 
 351         /* windows */ {wxFONTENCODING_CP1253
, STOP
}, 
 358         /* unix    */ {wxFONTENCODING_ISO8859_6
, STOP
}, 
 359         /* windows */ {wxFONTENCODING_CP1256
, STOP
}, 
 366         /* unix    */ {wxFONTENCODING_ISO8859_9
, STOP
}, 
 367         /* windows */ {wxFONTENCODING_CP1254
, STOP
}, 
 374         /* unix    */ {wxFONTENCODING_KOI8
, wxFONTENCODING_ISO8859_5
, STOP
}, 
 375         /* windows */ {wxFONTENCODING_CP1251
, STOP
}, 
 380     {{STOP
},{STOP
},{STOP
},{STOP
}} /* Terminator */ 
 381     /* no, _not_ Arnold! */ 
 387 wxFontEncodingArray 
wxEncodingConverter::GetPlatformEquivalents(wxFontEncoding enc
, int platform
) 
 389     if (platform 
== wxPLATFORM_CURRENT
) 
 391 #if defined(__WXMSW__) 
 392         platform 
= wxPLATFORM_WINDOWS
; 
 393 #elif defined(__WXGTK__) || defined(__WXMOTIF__) 
 394         platform 
= wxPLATFORM_UNIX
; 
 395 #elif defined(__WXOS2__) 
 396         platform 
= wxPLATFORM_OS2
; 
 397 #elif defined(__WXMAC__) 
 398         platform 
= wxPLATFORM_MAC
; 
 404     wxFontEncodingArray arr
; 
 407     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 409         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 410             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 411                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 413                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 414                         if (*f 
== enc
) arr
.Add(enc
); 
 415                     for (f 
= EquivalentEncodings
[clas
][platform
]; *f 
!= STOP
; f
++) 
 416                         if (arr
.Index(*f
) == wxNOT_FOUND
) arr
.Add(*f
); 
 417                     i 
= NUM_OF_PLATFORMS
/*hack*/; break; 
 427 wxFontEncodingArray 
wxEncodingConverter::GetAllEquivalents(wxFontEncoding enc
) 
 431     wxFontEncodingArray arr
; 
 433     arr 
= GetPlatformEquivalents(enc
); // we want them to be first items in array 
 436     while (EquivalentEncodings
[clas
][0][0] != STOP
) 
 438         for (i 
= 0; i 
< NUM_OF_PLATFORMS
; i
++) 
 439             for (e 
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++) 
 440                 if (EquivalentEncodings
[clas
][i
][e
] == enc
) 
 442                     for (j 
= 0; j 
< NUM_OF_PLATFORMS
; j
++) 
 443                         for (f 
= EquivalentEncodings
[clas
][j
]; *f 
!= STOP
; f
++) 
 444                             if (arr
.Index(*f
) == wxNOT_FOUND
) arr
.Add(*f
); 
 445                     i 
= NUM_OF_PLATFORMS
/*hack*/; break; 
 453 #endif // wxUSE_FONTMAP