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"
30 // conversion tables, generated by scripts in $(WXWIN)/misc/unictabl:
32 #include "../common/unictabl.inc"
34 #include "unictabl.inc"
38 typedef wchar_t tchar
;
43 static wxUint16
* LINKAGEMODE
GetEncTable(wxFontEncoding enc
)
45 for (int i
= 0; encodings_list
[i
].table
!= NULL
; i
++)
47 if (encodings_list
[i
].encoding
== enc
)
48 return encodings_list
[i
].table
;
60 extern "C" int LINKAGEMODE
CompareCharsetItems(const void *i1
, const void *i2
)
62 return ( ((CharsetItem
*)i1
) -> u
- ((CharsetItem
*)i2
) -> u
);
66 static CharsetItem
* LINKAGEMODE
BuildReverseTable(wxUint16
*tbl
)
68 CharsetItem
*rev
= new CharsetItem
[128];
70 for (int i
= 0; i
< 128; i
++)
71 rev
[i
].c
= 128 + i
, rev
[i
].u
= tbl
[i
];
73 qsort(rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
);
80 wxEncodingConverter::wxEncodingConverter()
83 m_UnicodeInput
= m_UnicodeOutput
= FALSE
;
89 bool wxEncodingConverter::Init(wxFontEncoding input_enc
, wxFontEncoding output_enc
, int method
)
92 wxUint16
*in_tbl
= NULL
, *out_tbl
= NULL
;
94 if (m_Table
) {delete[] m_Table
; m_Table
= NULL
;}
97 if (input_enc
== wxFONTENCODING_UNICODE
|| output_enc
== wxFONTENCODING_UNICODE
) return FALSE
;
100 if (input_enc
== output_enc
) {m_JustCopy
= TRUE
; return TRUE
;}
102 m_UnicodeOutput
= (output_enc
== wxFONTENCODING_UNICODE
);
105 if (input_enc
== wxFONTENCODING_UNICODE
)
107 if ((out_tbl
= GetEncTable(output_enc
)) == NULL
) return FALSE
;
109 m_Table
= new tchar
[65536];
110 for (i
= 0; i
< 128; i
++) m_Table
[i
] = (tchar
)i
; // 7bit ASCII
111 for (i
= 128; i
< 65536; i
++) m_Table
[i
] = (tchar
)'?';
112 // FIXME - this should be character that means `unicode to charset' impossible, not '?'
114 if (method
== wxCONVERT_SUBSTITUTE
)
116 for (i
= 0; i
< encoding_unicode_fallback_count
; i
++)
117 m_Table
[encoding_unicode_fallback
[i
].c
] = (tchar
) encoding_unicode_fallback
[i
].s
;
120 for (i
= 0; i
< 128; i
++)
121 m_Table
[out_tbl
[i
]] = (tchar
)(128 + i
);
123 m_UnicodeInput
= TRUE
;
129 if ((in_tbl
= GetEncTable(input_enc
)) == NULL
) return FALSE
;
130 if (output_enc
!= wxFONTENCODING_UNICODE
)
131 if ((out_tbl
= GetEncTable(output_enc
)) == NULL
) return FALSE
;
133 m_UnicodeInput
= FALSE
;
135 m_Table
= new tchar
[256];
136 for (i
= 0; i
< 128; i
++) m_Table
[i
] = (tchar
)i
; // 7bit ASCII
138 if (output_enc
== wxFONTENCODING_UNICODE
)
140 for (i
= 0; i
< 128; i
++) m_Table
[128 + i
] = (tchar
)in_tbl
[i
];
145 CharsetItem
*rev
= BuildReverseTable(out_tbl
);
149 for (i
= 0; i
< 128; i
++)
152 item
= (CharsetItem
*) bsearch(&key
, rev
, 128, sizeof(CharsetItem
), CompareCharsetItems
);
153 if (item
== NULL
&& method
== wxCONVERT_SUBSTITUTE
)
154 item
= (CharsetItem
*) bsearch(&key
, encoding_unicode_fallback
,
155 encoding_unicode_fallback_count
, sizeof(CharsetItem
), CompareCharsetItems
);
157 m_Table
[128 + i
] = (tchar
)item
-> c
;
160 m_Table
[128 + i
] = (wchar_t)(128 + i
);
162 m_Table
[128 + i
] = (char)(128 + i
);
174 void wxEncodingConverter::Convert(const char* input
, char* output
)
176 wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!"));
177 wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!"));
184 strcpy(output
, input
);
188 wxCHECK_RET(m_Table
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!"));
190 for (i
= input
, o
= output
; *i
!= 0;)
191 *(o
++) = (char)(m_Table
[(wxUint8
)*(i
++)]);
198 void wxEncodingConverter::Convert(const char* input
, wchar_t* output
)
200 wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!"));
201 wxASSERT_MSG(!m_UnicodeInput
, wxT("You cannot convert from unicode if input is const char*!"));
208 for (i
= input
, o
= output
; *i
!= 0;)
209 *(o
++) = (wchar_t)(*(i
++));
214 wxCHECK_RET(m_Table
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!"));
216 for (i
= input
, o
= output
; *i
!= 0;)
217 *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]);
223 void wxEncodingConverter::Convert(const wchar_t* input
, char* output
)
225 wxASSERT_MSG(!m_UnicodeOutput
, wxT("You cannot convert to unicode if output is const char*!"));
226 wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!"));
233 for (i
= input
, o
= output
; *i
!= 0;)
234 *(o
++) = (char)(*(i
++));
239 wxCHECK_RET(m_Table
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!"));
241 for (i
= input
, o
= output
; *i
!= 0;)
242 *(o
++) = (char)(m_Table
[(wxUint16
)*(i
++)]);
248 void wxEncodingConverter::Convert(const wchar_t* input
, wchar_t* output
)
250 wxASSERT_MSG(m_UnicodeOutput
, wxT("You cannot convert to 8-bit if output is const wchar_t*!"));
251 wxASSERT_MSG(m_UnicodeInput
, wxT("You cannot convert from 8-bit if input is const wchar_t*!"));
258 // wcscpy() is not guaranteed to exist
259 for (i
= input
, o
= output
; *i
!= 0;)
265 wxCHECK_RET(m_Table
!= NULL
, wxT("You must call wxEncodingConverter::Init() before actually converting!"));
267 for (i
= input
, o
= output
; *i
!= 0;)
268 *(o
++) = (wchar_t)(m_Table
[(wxUint8
)*(i
++)]);
272 #endif // wxUSE_WCHAR_T
275 wxString
wxEncodingConverter::Convert(const wxString
& input
)
277 if (m_JustCopy
) return input
;
282 wxCHECK_MSG(m_Table
!= NULL
, s
,
283 wxT("You must call wxEncodingConverter::Init() before actually converting!"));
287 for (i
= input
.c_str(); *i
!= 0; i
++)
288 s
<< (wxChar
)(m_Table
[(wxUint16
)*i
]);
292 for (i
= input
.c_str(); *i
!= 0; i
++)
293 s
<< (wxChar
)(m_Table
[(wxUint8
)*i
]);
305 // Following tables describe classes of encoding equivalence.
308 #define STOP wxFONTENCODING_SYSTEM
310 #define NUM_OF_PLATFORMS 4 /*must conform to enum wxPLATFORM_XXXX !!!*/
311 #define ENC_PER_PLATFORM 5
312 // max no. of encodings for one language used on one platform
313 // Anybody thinks 5 is not enough? ;-)
315 static wxFontEncoding
316 EquivalentEncodings
[][NUM_OF_PLATFORMS
][ENC_PER_PLATFORM
+1] = {
318 // *** Please put more common encodings as first! ***
322 /* unix */ {wxFONTENCODING_ISO8859_1
, wxFONTENCODING_ISO8859_15
, STOP
},
323 /* windows */ {wxFONTENCODING_CP1252
, STOP
},
330 /* unix */ {wxFONTENCODING_ISO8859_2
, STOP
},
331 /* windows */ {wxFONTENCODING_CP1250
, STOP
},
338 /* unix */ {wxFONTENCODING_ISO8859_13
, wxFONTENCODING_ISO8859_4
, STOP
},
339 /* windows */ {wxFONTENCODING_CP1257
, STOP
},
346 /* unix */ {wxFONTENCODING_ISO8859_8
, STOP
},
347 /* windows */ {wxFONTENCODING_CP1255
, STOP
},
354 /* unix */ {wxFONTENCODING_ISO8859_7
, STOP
},
355 /* windows */ {wxFONTENCODING_CP1253
, STOP
},
362 /* unix */ {wxFONTENCODING_ISO8859_6
, STOP
},
363 /* windows */ {wxFONTENCODING_CP1256
, STOP
},
370 /* unix */ {wxFONTENCODING_ISO8859_9
, STOP
},
371 /* windows */ {wxFONTENCODING_CP1254
, STOP
},
378 /* unix */ {wxFONTENCODING_KOI8
, wxFONTENCODING_ISO8859_5
, STOP
},
379 /* windows */ {wxFONTENCODING_CP1251
, STOP
},
384 {{STOP
},{STOP
},{STOP
},{STOP
}} /* Terminator */
385 /* no, _not_ Arnold! */
391 wxFontEncodingArray
wxEncodingConverter::GetPlatformEquivalents(wxFontEncoding enc
, int platform
)
393 if (platform
== wxPLATFORM_CURRENT
)
395 #if defined(__WXMSW__)
396 platform
= wxPLATFORM_WINDOWS
;
397 #elif defined(__WXGTK__) || defined(__WXMOTIF__)
398 platform
= wxPLATFORM_UNIX
;
399 #elif defined(__WXOS2__)
400 platform
= wxPLATFORM_OS2
;
401 #elif defined(__WXMAC__)
402 platform
= wxPLATFORM_MAC
;
408 wxFontEncodingArray arr
;
411 while (EquivalentEncodings
[clas
][0][0] != STOP
)
413 for (i
= 0; i
< NUM_OF_PLATFORMS
; i
++)
414 for (e
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++)
415 if (EquivalentEncodings
[clas
][i
][e
] == enc
)
417 for (f
= EquivalentEncodings
[clas
][platform
]; *f
!= STOP
; f
++)
418 if (*f
== enc
) arr
.Add(enc
);
419 for (f
= EquivalentEncodings
[clas
][platform
]; *f
!= STOP
; f
++)
420 if (arr
.Index(*f
) == wxNOT_FOUND
) arr
.Add(*f
);
421 i
= NUM_OF_PLATFORMS
/*hack*/; break;
431 wxFontEncodingArray
wxEncodingConverter::GetAllEquivalents(wxFontEncoding enc
)
435 wxFontEncodingArray arr
;
437 arr
= GetPlatformEquivalents(enc
); // we want them to be first items in array
440 while (EquivalentEncodings
[clas
][0][0] != STOP
)
442 for (i
= 0; i
< NUM_OF_PLATFORMS
; i
++)
443 for (e
= 0; EquivalentEncodings
[clas
][i
][e
] != STOP
; e
++)
444 if (EquivalentEncodings
[clas
][i
][e
] == enc
)
446 for (j
= 0; j
< NUM_OF_PLATFORMS
; j
++)
447 for (f
= EquivalentEncodings
[clas
][j
]; *f
!= STOP
; f
++)
448 if (arr
.Index(*f
) == wxNOT_FOUND
) arr
.Add(*f
);
449 i
= NUM_OF_PLATFORMS
/*hack*/; break;
457 #endif // wxUSE_FONTMAP