]> git.saurik.com Git - wxWidgets.git/blob - src/common/fmapbase.cpp
Fix assert when editing an item in multi-selection wxTreeCtrl.
[wxWidgets.git] / src / common / fmapbase.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fmapbase.cpp
3 // Purpose: wxFontMapperBase class implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 21.06.2003 (extracted from common/fontmap.cpp)
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999-2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_FONTMAP
28
29 #ifndef WX_PRECOMP
30 #include "wx/app.h"
31 #include "wx/log.h"
32 #include "wx/intl.h"
33 #include "wx/module.h"
34 #include "wx/wxcrtvararg.h"
35 #endif //WX_PRECOMP
36
37 #if defined(__WXMSW__)
38 #include "wx/msw/private.h" // includes windows.h for LOGFONT
39 #include "wx/msw/winundef.h"
40 #endif
41
42 #include "wx/fontmap.h"
43 #include "wx/fmappriv.h"
44
45 #include "wx/apptrait.h"
46
47 // wxMemoryConfig uses wxFileConfig
48 #if wxUSE_CONFIG && wxUSE_FILECONFIG
49 #include "wx/config.h"
50 #include "wx/memconf.h"
51 #endif
52
53 // ----------------------------------------------------------------------------
54 // constants
55 // ----------------------------------------------------------------------------
56
57 // encodings supported by GetEncodingDescription
58 static const wxFontEncoding gs_encodings[] =
59 {
60 wxFONTENCODING_ISO8859_1,
61 wxFONTENCODING_ISO8859_2,
62 wxFONTENCODING_ISO8859_3,
63 wxFONTENCODING_ISO8859_4,
64 wxFONTENCODING_ISO8859_5,
65 wxFONTENCODING_ISO8859_6,
66 wxFONTENCODING_ISO8859_7,
67 wxFONTENCODING_ISO8859_8,
68 wxFONTENCODING_ISO8859_9,
69 wxFONTENCODING_ISO8859_10,
70 wxFONTENCODING_ISO8859_11,
71 wxFONTENCODING_ISO8859_12,
72 wxFONTENCODING_ISO8859_13,
73 wxFONTENCODING_ISO8859_14,
74 wxFONTENCODING_ISO8859_15,
75 wxFONTENCODING_KOI8,
76 wxFONTENCODING_KOI8_U,
77 wxFONTENCODING_CP866,
78 wxFONTENCODING_CP874,
79 wxFONTENCODING_CP932,
80 wxFONTENCODING_CP936,
81 wxFONTENCODING_CP949,
82 wxFONTENCODING_CP950,
83 wxFONTENCODING_CP1250,
84 wxFONTENCODING_CP1251,
85 wxFONTENCODING_CP1252,
86 wxFONTENCODING_CP1253,
87 wxFONTENCODING_CP1254,
88 wxFONTENCODING_CP1255,
89 wxFONTENCODING_CP1256,
90 wxFONTENCODING_CP1257,
91 wxFONTENCODING_CP437,
92 wxFONTENCODING_UTF7,
93 wxFONTENCODING_UTF8,
94 wxFONTENCODING_UTF16BE,
95 wxFONTENCODING_UTF16LE,
96 wxFONTENCODING_UTF32BE,
97 wxFONTENCODING_UTF32LE,
98 wxFONTENCODING_EUC_JP,
99 wxFONTENCODING_DEFAULT,
100 wxFONTENCODING_ISO2022_JP,
101
102 wxFONTENCODING_MACROMAN,
103 wxFONTENCODING_MACJAPANESE,
104 wxFONTENCODING_MACCHINESETRAD,
105 wxFONTENCODING_MACKOREAN,
106 wxFONTENCODING_MACARABIC,
107 wxFONTENCODING_MACHEBREW,
108 wxFONTENCODING_MACGREEK,
109 wxFONTENCODING_MACCYRILLIC,
110 wxFONTENCODING_MACDEVANAGARI,
111 wxFONTENCODING_MACGURMUKHI,
112 wxFONTENCODING_MACGUJARATI,
113 wxFONTENCODING_MACORIYA,
114 wxFONTENCODING_MACBENGALI,
115 wxFONTENCODING_MACTAMIL,
116 wxFONTENCODING_MACTELUGU,
117 wxFONTENCODING_MACKANNADA,
118 wxFONTENCODING_MACMALAJALAM,
119 wxFONTENCODING_MACSINHALESE,
120 wxFONTENCODING_MACBURMESE,
121 wxFONTENCODING_MACKHMER,
122 wxFONTENCODING_MACTHAI,
123 wxFONTENCODING_MACLAOTIAN,
124 wxFONTENCODING_MACGEORGIAN,
125 wxFONTENCODING_MACARMENIAN,
126 wxFONTENCODING_MACCHINESESIMP,
127 wxFONTENCODING_MACTIBETAN,
128 wxFONTENCODING_MACMONGOLIAN,
129 wxFONTENCODING_MACETHIOPIC,
130 wxFONTENCODING_MACCENTRALEUR,
131 wxFONTENCODING_MACVIATNAMESE,
132 wxFONTENCODING_MACARABICEXT,
133 wxFONTENCODING_MACSYMBOL,
134 wxFONTENCODING_MACDINGBATS,
135 wxFONTENCODING_MACTURKISH,
136 wxFONTENCODING_MACCROATIAN,
137 wxFONTENCODING_MACICELANDIC,
138 wxFONTENCODING_MACROMANIAN,
139 wxFONTENCODING_MACCELTIC,
140 wxFONTENCODING_MACGAELIC,
141 wxFONTENCODING_MACKEYBOARD
142 };
143
144 // the descriptions for them
145 static const char* const gs_encodingDescs[] =
146 {
147 wxTRANSLATE( "Western European (ISO-8859-1)" ),
148 wxTRANSLATE( "Central European (ISO-8859-2)" ),
149 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
150 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
151 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
152 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
153 wxTRANSLATE( "Greek (ISO-8859-7)" ),
154 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
155 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
156 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
157 wxTRANSLATE( "Thai (ISO-8859-11)" ),
158 wxTRANSLATE( "Indian (ISO-8859-12)" ),
159 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
160 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
161 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
162 wxTRANSLATE( "KOI8-R" ),
163 wxTRANSLATE( "KOI8-U" ),
164 wxTRANSLATE( "Windows/DOS OEM Cyrillic (CP 866)" ),
165 wxTRANSLATE( "Windows Thai (CP 874)" ),
166 wxTRANSLATE( "Windows Japanese (CP 932) or Shift-JIS" ),
167 wxTRANSLATE( "Windows Chinese Simplified (CP 936) or GB-2312" ),
168 wxTRANSLATE( "Windows Korean (CP 949)" ),
169 wxTRANSLATE( "Windows Chinese Traditional (CP 950) or Big-5" ),
170 wxTRANSLATE( "Windows Central European (CP 1250)" ),
171 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
172 wxTRANSLATE( "Windows Western European (CP 1252)" ),
173 wxTRANSLATE( "Windows Greek (CP 1253)" ),
174 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
175 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
176 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
177 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
178 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
179 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
180 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
181 #ifdef WORDS_BIGENDIAN
182 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
183 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
184 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
185 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
186 #else // WORDS_BIGENDIAN
187 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
188 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
189 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
190 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
191 #endif // WORDS_BIGENDIAN
192 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
193 wxTRANSLATE( "US-ASCII" ),
194 wxTRANSLATE( "ISO-2022-JP" ),
195
196 wxTRANSLATE( "MacRoman" ),
197 wxTRANSLATE( "MacJapanese" ),
198 wxTRANSLATE( "MacChineseTrad" ),
199 wxTRANSLATE( "MacKorean" ),
200 wxTRANSLATE( "MacArabic" ),
201 wxTRANSLATE( "MacHebrew" ),
202 wxTRANSLATE( "MacGreek" ),
203 wxTRANSLATE( "MacCyrillic" ),
204 wxTRANSLATE( "MacDevanagari" ),
205 wxTRANSLATE( "MacGurmukhi" ),
206 wxTRANSLATE( "MacGujarati" ),
207 wxTRANSLATE( "MacOriya" ),
208 wxTRANSLATE( "MacBengali" ),
209 wxTRANSLATE( "MacTamil" ),
210 wxTRANSLATE( "MacTelugu" ),
211 wxTRANSLATE( "MacKannada" ),
212 wxTRANSLATE( "MacMalayalam" ),
213 wxTRANSLATE( "MacSinhalese" ),
214 wxTRANSLATE( "MacBurmese" ),
215 wxTRANSLATE( "MacKhmer" ),
216 wxTRANSLATE( "MacThai" ),
217 wxTRANSLATE( "MacLaotian" ),
218 wxTRANSLATE( "MacGeorgian" ),
219 wxTRANSLATE( "MacArmenian" ),
220 wxTRANSLATE( "MacChineseSimp" ),
221 wxTRANSLATE( "MacTibetan" ),
222 wxTRANSLATE( "MacMongolian" ),
223 wxTRANSLATE( "MacEthiopic" ),
224 wxTRANSLATE( "MacCentralEurRoman" ),
225 wxTRANSLATE( "MacVietnamese" ),
226 wxTRANSLATE( "MacExtArabic" ),
227 wxTRANSLATE( "MacSymbol" ),
228 wxTRANSLATE( "MacDingbats" ),
229 wxTRANSLATE( "MacTurkish" ),
230 wxTRANSLATE( "MacCroatian" ),
231 wxTRANSLATE( "MacIcelandic" ),
232 wxTRANSLATE( "MacRomanian" ),
233 wxTRANSLATE( "MacCeltic" ),
234 wxTRANSLATE( "MacGaelic" ),
235 wxTRANSLATE( "MacKeyboardGlyphs" )
236 };
237
238 // and the internal names (these are not translated on purpose!)
239 static const wxChar* const gs_encodingNames[][9] =
240 {
241 // names from the columns correspond to these OS:
242 // Linux Solaris and IRIX HP-UX AIX
243 { wxT("ISO-8859-1"), wxT("ISO8859-1"), wxT("iso88591"), wxT("8859-1"), wxT("iso_8859_1"), NULL },
244 { wxT("ISO-8859-2"), wxT("ISO8859-2"), wxT("iso88592"), wxT("8859-2"), NULL },
245 { wxT("ISO-8859-3"), wxT("ISO8859-3"), wxT("iso88593"), wxT("8859-3"), NULL },
246 { wxT("ISO-8859-4"), wxT("ISO8859-4"), wxT("iso88594"), wxT("8859-4"), NULL },
247 { wxT("ISO-8859-5"), wxT("ISO8859-5"), wxT("iso88595"), wxT("8859-5"), NULL },
248 { wxT("ISO-8859-6"), wxT("ISO8859-6"), wxT("iso88596"), wxT("8859-6"), NULL },
249 { wxT("ISO-8859-7"), wxT("ISO8859-7"), wxT("iso88597"), wxT("8859-7"), NULL },
250 { wxT("ISO-8859-8"), wxT("ISO8859-8"), wxT("iso88598"), wxT("8859-8"), NULL },
251 { wxT("ISO-8859-9"), wxT("ISO8859-9"), wxT("iso88599"), wxT("8859-9"), NULL },
252 { wxT("ISO-8859-10"), wxT("ISO8859-10"), wxT("iso885910"), wxT("8859-10"), NULL },
253 { wxT("ISO-8859-11"), wxT("ISO8859-11"), wxT("iso885911"), wxT("8859-11"), NULL },
254 { wxT("ISO-8859-12"), wxT("ISO8859-12"), wxT("iso885912"), wxT("8859-12"), NULL },
255 { wxT("ISO-8859-13"), wxT("ISO8859-13"), wxT("iso885913"), wxT("8859-13"), NULL },
256 { wxT("ISO-8859-14"), wxT("ISO8859-14"), wxT("iso885914"), wxT("8859-14"), NULL },
257 { wxT("ISO-8859-15"), wxT("ISO8859-15"), wxT("iso885915"), wxT("8859-15"), NULL },
258
259 // although koi8-ru is not strictly speaking the same as koi8-r,
260 // they are similar enough to make mapping it to koi8 better than
261 // not recognizing it at all
262 { wxT( "KOI8-R" ), wxT( "KOI8-RU" ), NULL },
263 { wxT( "KOI8-U" ), NULL },
264
265 { wxT( "WINDOWS-866" ), wxT( "CP866" ), NULL },
266
267 { wxT( "WINDOWS-874" ), wxT( "CP874" ), wxT( "MS874" ), wxT( "IBM-874" ), NULL },
268 { wxT( "WINDOWS-932" ), wxT( "CP932" ), wxT( "MS932" ), wxT( "IBM-932" ), wxT( "SJIS" ), wxT( "SHIFT-JIS" ), wxT( "SHIFT_JIS" ), NULL },
269 { wxT( "WINDOWS-936" ), wxT( "CP936" ), wxT( "MS936" ), wxT( "IBM-936" ), wxT( "GB2312" ), NULL },
270 { wxT( "WINDOWS-949" ), wxT( "CP949" ), wxT( "MS949" ), wxT( "IBM-949" ), wxT( "EUC-KR" ), wxT( "eucKR" ), wxT( "euc_kr" ), NULL },
271 { wxT( "WINDOWS-950" ), wxT( "CP950" ), wxT( "MS950" ), wxT( "IBM-950" ), wxT( "BIG5" ), wxT( "BIG-5" ), wxT( "BIG-FIVE" ), NULL },
272 { wxT( "WINDOWS-1250" ),wxT( "CP1250" ),wxT( "MS1250" ),wxT( "IBM-1250" ),NULL },
273 { wxT( "WINDOWS-1251" ),wxT( "CP1251" ),wxT( "MS1251" ),wxT( "IBM-1251" ),NULL },
274 { wxT( "WINDOWS-1252" ),wxT( "CP1252" ),wxT( "MS1252" ),wxT( "IBM-1252" ),NULL },
275 { wxT( "WINDOWS-1253" ),wxT( "CP1253" ),wxT( "MS1253" ),wxT( "IBM-1253" ),NULL },
276 { wxT( "WINDOWS-1254" ),wxT( "CP1254" ),wxT( "MS1254" ),wxT( "IBM-1254" ),NULL },
277 { wxT( "WINDOWS-1255" ),wxT( "CP1255" ),wxT( "MS1255" ),wxT( "IBM-1255" ),NULL },
278 { wxT( "WINDOWS-1256" ),wxT( "CP1256" ),wxT( "MS1256" ),wxT( "IBM-1256" ),NULL },
279 { wxT( "WINDOWS-1257" ),wxT( "CP1257" ),wxT( "MS1257" ),wxT( "IBM-1257" ),NULL },
280 { wxT( "WINDOWS-437" ), wxT( "CP437" ), wxT( "MS437" ), wxT( "IBM-437" ), NULL },
281
282 { wxT( "UTF-7" ), wxT("UTF7"), NULL },
283 { wxT( "UTF-8" ), wxT("UTF8"), NULL },
284 #ifdef WORDS_BIGENDIAN
285 { wxT( "UTF-16BE" ), wxT("UTF16BE"), wxT("UCS-2BE"), wxT("UCS2BE"), wxT("UTF-16"), wxT("UTF16"), wxT("UCS-2"), wxT("UCS2"), NULL },
286 { wxT( "UTF-16LE" ), wxT("UTF16LE"), wxT("UCS-2LE"), wxT("UCS2LE"), NULL },
287 { wxT( "UTF-32BE" ), wxT("UTF32BE"), wxT("UCS-4BE" ), wxT("UTF-32"), wxT("UTF32"), wxT("UCS-4"), wxT("UCS4"), NULL },
288 { wxT( "UTF-32LE" ), wxT("UTF32LE"), wxT("UCS-4LE"), wxT("UCS4LE"), NULL },
289 #else // WORDS_BIGENDIAN
290 { wxT("UTF-16BE"), wxT("UTF16BE"), wxT("UCS-2BE"), wxT("UCS2BE"), NULL },
291 { wxT("UTF-16LE"), wxT("UTF16LE"), wxT("UCS-2LE"), wxT("UTF-16"), wxT("UTF16"), wxT("UCS-2"), wxT("UCS2"), NULL },
292 { wxT("UTF-32BE"), wxT("UTF32BE"), wxT("UCS-4BE"), wxT("UCS4BE"), NULL },
293 { wxT("UTF-32LE"), wxT("UTF32LE"), wxT("UCS-4LE"), wxT("UCS4LE"), wxT("UTF-32"), wxT("UTF32"), wxT("UCS-4"), wxT("UCS4"), NULL },
294 #endif // WORDS_BIGENDIAN
295
296 { wxT( "EUC-JP" ), wxT( "eucJP" ), wxT( "euc_jp" ), wxT( "IBM-eucJP" ), NULL },
297
298 // 646 is for Solaris, roman8 -- for HP-UX
299 { wxT( "US-ASCII" ), wxT( "ASCII" ), wxT("C"), wxT("POSIX"), wxT("ANSI_X3.4-1968"),
300 wxT("646"), wxT("roman8"), wxT( "" ), NULL },
301
302 { wxT( "ISO-2022-JP" ), NULL },
303
304
305 { wxT( "MacRoman" ), NULL },
306 { wxT( "MacJapanese" ), NULL },
307 { wxT( "MacChineseTrad" ), NULL },
308 { wxT( "MacKorean" ), NULL },
309 { wxT( "MacArabic" ), NULL },
310 { wxT( "MacHebrew" ), NULL },
311 { wxT( "MacGreek" ), NULL },
312 { wxT( "MacCyrillic" ), NULL },
313 { wxT( "MacDevanagari" ), NULL },
314 { wxT( "MacGurmukhi" ), NULL },
315 { wxT( "MacGujarati" ), NULL },
316 { wxT( "MacOriya" ), NULL },
317 { wxT( "MacBengali" ), NULL },
318 { wxT( "MacTamil" ), NULL },
319 { wxT( "MacTelugu" ), NULL },
320 { wxT( "MacKannada" ), NULL },
321 { wxT( "MacMalayalam" ), NULL },
322 { wxT( "MacSinhalese" ), NULL },
323 { wxT( "MacBurmese" ), NULL },
324 { wxT( "MacKhmer" ), NULL },
325 { wxT( "MacThai" ), NULL },
326 { wxT( "MacLaotian" ), NULL },
327 { wxT( "MacGeorgian" ), NULL },
328 { wxT( "MacArmenian" ), NULL },
329 { wxT( "MacChineseSimp" ), NULL },
330 { wxT( "MacTibetan" ), NULL },
331 { wxT( "MacMongolian" ), NULL },
332 { wxT( "MacEthiopic" ), NULL },
333 { wxT( "MacCentralEurRoman" ), NULL },
334 { wxT( "MacVietnamese" ), NULL },
335 { wxT( "MacExtArabic" ), NULL },
336 { wxT( "MacSymbol" ), NULL },
337 { wxT( "MacDingbats" ), NULL },
338 { wxT( "MacTurkish" ), NULL },
339 { wxT( "MacCroatian" ), NULL },
340 { wxT( "MacIcelandic" ), NULL },
341 { wxT( "MacRomanian" ), NULL },
342 { wxT( "MacCeltic" ), NULL },
343 { wxT( "MacGaelic" ), NULL },
344 { wxT( "MacKeyboardGlyphs" ), NULL }
345 };
346
347 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs) == WXSIZEOF(gs_encodings), EncodingsArraysNotInSync );
348 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingNames) == WXSIZEOF(gs_encodings), EncodingsArraysNotInSync );
349
350 // ----------------------------------------------------------------------------
351 // private classes
352 // ----------------------------------------------------------------------------
353
354 // clean up the font mapper object
355 class wxFontMapperModule : public wxModule
356 {
357 public:
358 wxFontMapperModule() : wxModule() { }
359
360 virtual bool OnInit()
361 {
362 // a dummy wxFontMapperBase object could have been created during the
363 // program startup before wxApp was created, we have to delete it to
364 // allow creating the real font mapper next time it is needed now that
365 // we can create it (when the modules are initialized, wxApp object
366 // already exists)
367 wxFontMapperBase *fm = wxFontMapperBase::Get();
368 if ( fm && fm->IsDummy() )
369 wxFontMapperBase::Reset();
370
371 return true;
372 }
373
374 virtual void OnExit()
375 {
376 wxFontMapperBase::Reset();
377 }
378
379 DECLARE_DYNAMIC_CLASS(wxFontMapperModule)
380 };
381
382 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule, wxModule)
383
384
385 // ============================================================================
386 // wxFontMapperBase implementation
387 // ============================================================================
388
389 wxFontMapper *wxFontMapperBase::sm_instance = NULL;
390
391 // ----------------------------------------------------------------------------
392 // ctor and dtor
393 // ----------------------------------------------------------------------------
394
395 wxFontMapperBase::wxFontMapperBase()
396 {
397 #if wxUSE_CONFIG && wxUSE_FILECONFIG
398 m_configDummy = NULL;
399 #endif // wxUSE_CONFIG
400 }
401
402 wxFontMapperBase::~wxFontMapperBase()
403 {
404 #if wxUSE_CONFIG && wxUSE_FILECONFIG
405 if ( m_configDummy )
406 delete m_configDummy;
407 #endif // wxUSE_CONFIG
408 }
409
410 /* static */
411 wxFontMapperBase *wxFontMapperBase::Get()
412 {
413 if ( !sm_instance )
414 {
415 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
416 if ( traits )
417 {
418 sm_instance = traits->CreateFontMapper();
419
420 wxASSERT_MSG( sm_instance,
421 wxT("wxAppTraits::CreateFontMapper() failed") );
422 }
423
424 if ( !sm_instance )
425 {
426 // last resort: we must create something because the existing code
427 // relies on always having a valid font mapper object
428 sm_instance = (wxFontMapper *)new wxFontMapperBase;
429 }
430 }
431
432 return (wxFontMapperBase*)sm_instance;
433 }
434
435 /* static */
436 wxFontMapper *wxFontMapperBase::Set(wxFontMapper *mapper)
437 {
438 wxFontMapper *old = sm_instance;
439 sm_instance = mapper;
440 return old;
441 }
442
443 /* static */
444 void wxFontMapperBase::Reset()
445 {
446 if ( sm_instance )
447 {
448 // we need a cast as wxFontMapper is not fully declared here and so the
449 // compiler can't know that it derives from wxFontMapperBase (but
450 // run-time behaviour will be correct because the dtor is virtual)
451 delete (wxFontMapperBase *)sm_instance;
452 sm_instance = NULL;
453 }
454 }
455
456 #if wxUSE_CONFIG && wxUSE_FILECONFIG
457
458 // ----------------------------------------------------------------------------
459 // config usage customisation
460 // ----------------------------------------------------------------------------
461
462
463 static wxString gs_defaultConfigPath(FONTMAPPER_ROOT_PATH);
464
465 /* static */
466 const wxString& wxFontMapperBase::GetDefaultConfigPath()
467 {
468 // NB: we return const wxString& and not wxString for compatibility
469 // with 2.8 that returned const wxChar*
470 return gs_defaultConfigPath;
471 }
472
473 void wxFontMapperBase::SetConfigPath(const wxString& prefix)
474 {
475 wxCHECK_RET( !prefix.empty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
476 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
477
478 m_configRootPath = prefix;
479 }
480
481 // ----------------------------------------------------------------------------
482 // get config object and path for it
483 // ----------------------------------------------------------------------------
484
485 wxConfigBase *wxFontMapperBase::GetConfig()
486 {
487 wxConfigBase *config = wxConfig::Get(false);
488
489 // If there is no global configuration, use an internal memory configuration
490 if ( !config )
491 {
492 if ( !m_configDummy )
493 m_configDummy = new wxMemoryConfig;
494 config = m_configDummy;
495
496 // FIXME: ideally, we should add keys from dummy config to a real one later,
497 // but it is a low-priority task because typical wxWin application
498 // either doesn't use wxConfig at all or creates wxConfig object in
499 // wxApp::OnInit(), before any real interaction with the user takes
500 // place...
501 }
502
503 return config;
504 }
505
506 const wxString& wxFontMapperBase::GetConfigPath()
507 {
508 if ( !m_configRootPath )
509 {
510 // use the default
511 m_configRootPath = GetDefaultConfigPath();
512 }
513
514 return m_configRootPath;
515 }
516
517 // ----------------------------------------------------------------------------
518 // config helpers
519 // ----------------------------------------------------------------------------
520
521 bool wxFontMapperBase::ChangePath(const wxString& pathNew, wxString *pathOld)
522 {
523 wxConfigBase *config = GetConfig();
524 if ( !config )
525 return false;
526
527 *pathOld = config->GetPath();
528
529 wxString path = GetConfigPath();
530 if ( path.empty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
531 {
532 path += wxCONFIG_PATH_SEPARATOR;
533 }
534
535 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
536 wxT("should be a relative path") );
537
538 path += pathNew;
539
540 config->SetPath(path);
541
542 return true;
543 }
544
545 void wxFontMapperBase::RestorePath(const wxString& pathOld)
546 {
547 GetConfig()->SetPath(pathOld);
548 }
549
550 #endif
551
552 // ----------------------------------------------------------------------------
553 // charset/encoding correspondence
554 // ----------------------------------------------------------------------------
555
556 wxFontEncoding
557 wxFontMapperBase::CharsetToEncoding(const wxString& charset,
558 bool WXUNUSED(interactive))
559 {
560 int enc = NonInteractiveCharsetToEncoding(charset);
561 if ( enc == wxFONTENCODING_UNKNOWN )
562 {
563 // we should return wxFONTENCODING_SYSTEM from here for unknown
564 // encodings
565 enc = wxFONTENCODING_SYSTEM;
566 }
567
568 return (wxFontEncoding)enc;
569 }
570
571 int
572 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString& charset)
573 {
574 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
575
576 // we're going to modify it, make a copy
577 wxString cs = charset;
578
579 #if wxUSE_CONFIG && wxUSE_FILECONFIG
580 // first try the user-defined settings
581 wxFontMapperPathChanger path(this, FONTMAPPER_CHARSET_PATH);
582 if ( path.IsOk() )
583 {
584 wxConfigBase *config = GetConfig();
585
586 // do we have an encoding for this charset?
587 long value = config->Read(charset, -1l);
588 if ( value != -1 )
589 {
590 if ( value == wxFONTENCODING_UNKNOWN )
591 {
592 // don't try to find it, in particular don't ask the user
593 return value;
594 }
595
596 if ( value >= 0 && value <= wxFONTENCODING_MAX )
597 {
598 encoding = (wxFontEncoding)value;
599 }
600 else
601 {
602 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
603 value, charset.c_str());
604 }
605 }
606
607 if ( encoding == wxFONTENCODING_SYSTEM )
608 {
609 // may be we have an alias?
610 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
611
612 wxString alias = config->Read(charset);
613 if ( !alias.empty() )
614 {
615 // yes, we do - use it instead
616 cs = alias;
617 }
618 }
619 }
620 #endif // wxUSE_CONFIG
621
622 // if didn't find it there, try to recognize it ourselves
623 if ( encoding == wxFONTENCODING_SYSTEM )
624 {
625 // trim any spaces
626 cs.Trim(true);
627 cs.Trim(false);
628
629 // discard the optional quotes
630 if ( !cs.empty() )
631 {
632 if ( cs[0u] == wxT('"') && cs.Last() == wxT('"') )
633 {
634 cs = wxString(cs.c_str(), cs.length() - 1);
635 }
636 }
637
638 for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); ++i )
639 {
640 for ( const wxChar* const* encName = gs_encodingNames[i]; *encName; ++encName )
641 {
642 if ( cs.CmpNoCase(*encName) == 0 )
643 return gs_encodings[i];
644 }
645 }
646
647 cs.MakeUpper();
648
649 if ( cs.Left(3) == wxT("ISO") )
650 {
651 // the dash is optional (or, to be exact, it is not, but
652 // several broken programs "forget" it)
653 const wxChar *p = cs.c_str() + 3;
654 if ( *p == wxT('-') )
655 p++;
656
657 unsigned int value;
658 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
659 {
660 // make it 0 based and check that it is strictly positive in
661 // the process (no such thing as iso8859-0 encoding)
662 if ( (value-- > 0) &&
663 (value < wxFONTENCODING_ISO8859_MAX -
664 wxFONTENCODING_ISO8859_1) )
665 {
666 // it's a valid ISO8859 encoding
667 value += wxFONTENCODING_ISO8859_1;
668 encoding = (wxFontEncoding)value;
669 }
670 }
671 }
672 else if ( cs.Left(4) == wxT("8859") )
673 {
674 const wxChar *p = cs.c_str();
675
676 unsigned int value;
677 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
678 {
679 // make it 0 based and check that it is strictly positive in
680 // the process (no such thing as iso8859-0 encoding)
681 if ( (value-- > 0) &&
682 (value < wxFONTENCODING_ISO8859_MAX -
683 wxFONTENCODING_ISO8859_1) )
684 {
685 // it's a valid ISO8859 encoding
686 value += wxFONTENCODING_ISO8859_1;
687 encoding = (wxFontEncoding)value;
688 }
689 }
690 }
691 else // check for Windows charsets
692 {
693 size_t len;
694 if ( cs.Left(7) == wxT("WINDOWS") )
695 {
696 len = 7;
697 }
698 else if ( cs.Left(2) == wxT("CP") )
699 {
700 len = 2;
701 }
702 else // not a Windows encoding
703 {
704 len = 0;
705 }
706
707 if ( len )
708 {
709 const wxChar *p = cs.c_str() + len;
710 if ( *p == wxT('-') )
711 p++;
712
713 unsigned int value;
714 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
715 {
716 if ( value >= 1250 )
717 {
718 value -= 1250;
719 if ( value < wxFONTENCODING_CP12_MAX -
720 wxFONTENCODING_CP1250 )
721 {
722 // a valid Windows code page
723 value += wxFONTENCODING_CP1250;
724 encoding = (wxFontEncoding)value;
725 }
726 }
727
728 switch ( value )
729 {
730 case 866:
731 encoding = wxFONTENCODING_CP866;
732 break;
733
734 case 874:
735 encoding = wxFONTENCODING_CP874;
736 break;
737
738 case 932:
739 encoding = wxFONTENCODING_CP932;
740 break;
741
742 case 936:
743 encoding = wxFONTENCODING_CP936;
744 break;
745
746 case 949:
747 encoding = wxFONTENCODING_CP949;
748 break;
749
750 case 950:
751 encoding = wxFONTENCODING_CP950;
752 break;
753 }
754 }
755 }
756 }
757 //else: unknown
758 }
759
760 return encoding;
761 }
762
763 /* static */
764 size_t wxFontMapperBase::GetSupportedEncodingsCount()
765 {
766 return WXSIZEOF(gs_encodings);
767 }
768
769 /* static */
770 wxFontEncoding wxFontMapperBase::GetEncoding(size_t n)
771 {
772 wxCHECK_MSG( n < WXSIZEOF(gs_encodings), wxFONTENCODING_SYSTEM,
773 wxT("wxFontMapper::GetEncoding(): invalid index") );
774
775 return gs_encodings[n];
776 }
777
778 /* static */
779 wxString wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding)
780 {
781 if ( encoding == wxFONTENCODING_DEFAULT )
782 {
783 return _("Default encoding");
784 }
785
786 const size_t count = WXSIZEOF(gs_encodingDescs);
787
788 for ( size_t i = 0; i < count; i++ )
789 {
790 if ( gs_encodings[i] == encoding )
791 {
792 return wxGetTranslation(gs_encodingDescs[i]);
793 }
794 }
795
796 wxString str;
797 str.Printf(_("Unknown encoding (%d)"), encoding);
798
799 return str;
800 }
801
802 /* static */
803 wxString wxFontMapperBase::GetEncodingName(wxFontEncoding encoding)
804 {
805 if ( encoding == wxFONTENCODING_DEFAULT )
806 {
807 return _("default");
808 }
809
810 const size_t count = WXSIZEOF(gs_encodingNames);
811
812 for ( size_t i = 0; i < count; i++ )
813 {
814 if ( gs_encodings[i] == encoding )
815 {
816 return gs_encodingNames[i][0];
817 }
818 }
819
820 wxString str;
821 str.Printf(_("unknown-%d"), encoding);
822
823 return str;
824 }
825
826 /* static */
827 const wxChar** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding)
828 {
829 static const wxChar* const dummy[] = { NULL };
830
831 for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); i++ )
832 {
833 if ( gs_encodings[i] == encoding )
834 {
835 return const_cast<const wxChar**>(gs_encodingNames[i]);
836 }
837 }
838
839 return const_cast<const wxChar**>(dummy);
840 }
841
842 /* static */
843 wxFontEncoding wxFontMapperBase::GetEncodingFromName(const wxString& name)
844 {
845 const size_t count = WXSIZEOF(gs_encodingNames);
846
847 for ( size_t i = 0; i < count; i++ )
848 {
849 for ( const wxChar* const* encName = gs_encodingNames[i]; *encName; ++encName )
850 {
851 if ( name.CmpNoCase(*encName) == 0 )
852 return gs_encodings[i];
853 }
854 }
855
856 return wxFONTENCODING_MAX;
857 }
858
859 #endif // wxUSE_FONTMAP