OSX regrouping
[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 // License: wxWindows license
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 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_CP874,
78 wxFONTENCODING_CP932,
79 wxFONTENCODING_CP936,
80 wxFONTENCODING_CP949,
81 wxFONTENCODING_CP950,
82 wxFONTENCODING_CP1250,
83 wxFONTENCODING_CP1251,
84 wxFONTENCODING_CP1252,
85 wxFONTENCODING_CP1253,
86 wxFONTENCODING_CP1254,
87 wxFONTENCODING_CP1255,
88 wxFONTENCODING_CP1256,
89 wxFONTENCODING_CP1257,
90 wxFONTENCODING_CP437,
91 wxFONTENCODING_UTF7,
92 wxFONTENCODING_UTF8,
93 wxFONTENCODING_UTF16BE,
94 wxFONTENCODING_UTF16LE,
95 wxFONTENCODING_UTF32BE,
96 wxFONTENCODING_UTF32LE,
97 wxFONTENCODING_EUC_JP,
98 wxFONTENCODING_DEFAULT,
99 wxFONTENCODING_BIG5,
100 wxFONTENCODING_SHIFT_JIS,
101 wxFONTENCODING_GB2312,
102 wxFONTENCODING_ISO2022_JP,
103 };
104
105 // the descriptions for them
106 static const char* gs_encodingDescs[] =
107 {
108 wxTRANSLATE( "Western European (ISO-8859-1)" ),
109 wxTRANSLATE( "Central European (ISO-8859-2)" ),
110 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
111 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
112 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
113 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
114 wxTRANSLATE( "Greek (ISO-8859-7)" ),
115 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
116 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
117 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
118 wxTRANSLATE( "Thai (ISO-8859-11)" ),
119 wxTRANSLATE( "Indian (ISO-8859-12)" ),
120 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
121 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
122 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
123 wxTRANSLATE( "KOI8-R" ),
124 wxTRANSLATE( "KOI8-U" ),
125 wxTRANSLATE( "Windows Thai (CP 874)" ),
126 wxTRANSLATE( "Windows Japanese (CP 932)" ),
127 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
128 wxTRANSLATE( "Windows Korean (CP 949)" ),
129 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
130 wxTRANSLATE( "Windows Central European (CP 1250)" ),
131 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
132 wxTRANSLATE( "Windows Western European (CP 1252)" ),
133 wxTRANSLATE( "Windows Greek (CP 1253)" ),
134 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
135 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
136 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
137 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
138 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
139 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
140 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
141 #ifdef WORDS_BIGENDIAN
142 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
143 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
144 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
145 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
146 #else // WORDS_BIGENDIAN
147 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
148 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
149 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
150 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
151 #endif // WORDS_BIGENDIAN
152 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
153 wxTRANSLATE( "US-ASCII" ),
154 wxTRANSLATE( "BIG5" ),
155 wxTRANSLATE( "SHIFT-JIS" ),
156 wxTRANSLATE( "GB-2312" ),
157 wxTRANSLATE( "ISO-2022-JP" ),
158 };
159
160 // and the internal names (these are not translated on purpose!)
161 static const wxChar* gs_encodingNames[WXSIZEOF(gs_encodingDescs)][9] =
162 {
163 // names from the columns correspond to these OS:
164 // Linux Solaris and IRIX HP-UX AIX
165 { _T("ISO-8859-1"), _T("ISO8859-1"), _T("iso88591"), _T("8859-1"), wxT("iso_8859_1"), NULL },
166 { _T("ISO-8859-2"), _T("ISO8859-2"), _T("iso88592"), _T("8859-2"), NULL },
167 { _T("ISO-8859-3"), _T("ISO8859-3"), _T("iso88593"), _T("8859-3"), NULL },
168 { _T("ISO-8859-4"), _T("ISO8859-4"), _T("iso88594"), _T("8859-4"), NULL },
169 { _T("ISO-8859-5"), _T("ISO8859-5"), _T("iso88595"), _T("8859-5"), NULL },
170 { _T("ISO-8859-6"), _T("ISO8859-6"), _T("iso88596"), _T("8859-6"), NULL },
171 { _T("ISO-8859-7"), _T("ISO8859-7"), _T("iso88597"), _T("8859-7"), NULL },
172 { _T("ISO-8859-8"), _T("ISO8859-8"), _T("iso88598"), _T("8859-8"), NULL },
173 { _T("ISO-8859-9"), _T("ISO8859-9"), _T("iso88599"), _T("8859-9"), NULL },
174 { _T("ISO-8859-10"), _T("ISO8859-10"), _T("iso885910"), _T("8859-10"), NULL },
175 { _T("ISO-8859-11"), _T("ISO8859-11"), _T("iso885911"), _T("8859-11"), NULL },
176 { _T("ISO-8859-12"), _T("ISO8859-12"), _T("iso885912"), _T("8859-12"), NULL },
177 { _T("ISO-8859-13"), _T("ISO8859-13"), _T("iso885913"), _T("8859-13"), NULL },
178 { _T("ISO-8859-14"), _T("ISO8859-14"), _T("iso885914"), _T("8859-14"), NULL },
179 { _T("ISO-8859-15"), _T("ISO8859-15"), _T("iso885915"), _T("8859-15"), NULL },
180
181 // although koi8-ru is not strictly speaking the same as koi8-r,
182 // they are similar enough to make mapping it to koi8 better than
183 // not recognizing it at all
184 { wxT( "KOI8-R" ), wxT( "KOI8-RU" ), NULL },
185 { wxT( "KOI8-U" ), NULL },
186
187 { wxT( "WINDOWS-874" ), wxT( "CP874" ), wxT( "MS874" ), wxT( "IBM-874" ), NULL },
188 { wxT( "WINDOWS-932" ), wxT( "CP932" ), wxT( "MS932" ), wxT( "IBM-932" ), NULL },
189 { wxT( "WINDOWS-936" ), wxT( "CP936" ), wxT( "MS936" ), wxT( "IBM-936" ), NULL },
190 { wxT( "WINDOWS-949" ), wxT( "CP949" ), wxT( "MS949" ), wxT( "IBM-949" ), wxT( "EUC-KR" ), wxT( "eucKR" ), wxT( "euc_kr" ), NULL },
191 { wxT( "WINDOWS-950" ), wxT( "CP950" ), wxT( "MS950" ), wxT( "IBM-950" ), NULL },
192 { wxT( "WINDOWS-1250" ),wxT( "CP1250" ),wxT( "MS1250" ),wxT( "IBM-1250" ),NULL },
193 { wxT( "WINDOWS-1251" ),wxT( "CP1251" ),wxT( "MS1251" ),wxT( "IBM-1251" ),NULL },
194 { wxT( "WINDOWS-1252" ),wxT( "CP1252" ),wxT( "MS1252" ),wxT( "IBM-1252" ),NULL },
195 { wxT( "WINDOWS-1253" ),wxT( "CP1253" ),wxT( "MS1253" ),wxT( "IBM-1253" ),NULL },
196 { wxT( "WINDOWS-1254" ),wxT( "CP1254" ),wxT( "MS1254" ),wxT( "IBM-1254" ),NULL },
197 { wxT( "WINDOWS-1255" ),wxT( "CP1255" ),wxT( "MS1255" ),wxT( "IBM-1255" ),NULL },
198 { wxT( "WINDOWS-1256" ),wxT( "CP1256" ),wxT( "MS1256" ),wxT( "IBM-1256" ),NULL },
199 { wxT( "WINDOWS-1257" ),wxT( "CP1257" ),wxT( "MS1257" ),wxT( "IBM-1257" ),NULL },
200 { wxT( "WINDOWS-437" ), wxT( "CP437" ), wxT( "MS437" ), wxT( "IBM-437" ), NULL },
201
202 { wxT( "UTF-7" ), wxT("UTF7"), NULL },
203 { wxT( "UTF-8" ), wxT("UTF8"), NULL },
204 #ifdef WORDS_BIGENDIAN
205 { wxT( "UTF-16BE" ), wxT("UTF16BE"), wxT("UCS-2BE"), wxT("UCS2BE"), wxT("UTF-16"), wxT("UTF16"), wxT("UCS-2"), wxT("UCS2"), NULL },
206 { wxT( "UTF-16LE" ), wxT("UTF16LE"), wxT("UCS-2LE"), wxT("UCS2LE"), NULL },
207 { wxT( "UTF-32BE" ), wxT("UTF32BE"), wxT("UCS-4BE" ), wxT("UTF-32"), wxT("UTF32"), wxT("UCS-4"), wxT("UCS4"), NULL },
208 { wxT( "UTF-32LE" ), wxT("UTF32LE"), wxT("UCS-4LE"), wxT("UCS4LE"), NULL },
209 #else // WORDS_BIGENDIAN
210 { wxT("UTF-16BE"), wxT("UTF16BE"), wxT("UCS-2BE"), wxT("UCS2BE"), NULL },
211 { wxT("UTF-16LE"), wxT("UTF16LE"), wxT("UCS-2LE"), wxT("UTF-16"), wxT("UTF16"), wxT("UCS-2"), wxT("UCS2"), NULL },
212 { wxT("UTF-32BE"), wxT("UTF32BE"), wxT("UCS-4BE"), wxT("UCS4BE"), NULL },
213 { wxT("UTF-32LE"), wxT("UTF32LE"), wxT("UCS-4LE"), wxT("UCS4LE"), wxT("UTF-32"), wxT("UTF32"), wxT("UCS-4"), wxT("UCS4"), NULL },
214 #endif // WORDS_BIGENDIAN
215
216 { wxT( "EUC-JP" ), wxT( "eucJP" ), wxT( "euc_jp" ), wxT( "IBM-eucJP" ), NULL },
217
218 // 646 is for Solaris, roman8 -- for HP-UX
219 { wxT( "US-ASCII" ), wxT( "ASCII" ), wxT("C"), wxT("POSIX"), wxT("ANSI_X3.4-1968"),
220 wxT("646"), wxT("roman8"), wxT( "" ), NULL },
221
222 { wxT( "BIG5" ), wxT("big5"), NULL },
223 { wxT( "SJIS" ), wxT( "SHIFT-JIS" ), wxT( "SHIFT_JIS" ), NULL },
224 { wxT( "GB2312" ), NULL },
225 { wxT( "ISO-2022-JP" ), NULL },
226 };
227
228 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs) == WXSIZEOF(gs_encodings), EncodingsArraysNotInSync );
229 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingNames) == WXSIZEOF(gs_encodings), EncodingsArraysNotInSync );
230
231 // ----------------------------------------------------------------------------
232 // private classes
233 // ----------------------------------------------------------------------------
234
235 // clean up the font mapper object
236 class wxFontMapperModule : public wxModule
237 {
238 public:
239 wxFontMapperModule() : wxModule() { }
240
241 virtual bool OnInit()
242 {
243 // a dummy wxFontMapperBase object could have been created during the
244 // program startup before wxApp was created, we have to delete it to
245 // allow creating the real font mapper next time it is needed now that
246 // we can create it (when the modules are initialized, wxApp object
247 // already exists)
248 wxFontMapperBase *fm = wxFontMapperBase::Get();
249 if ( fm && fm->IsDummy() )
250 wxFontMapperBase::Reset();
251
252 return true;
253 }
254
255 virtual void OnExit()
256 {
257 wxFontMapperBase::Reset();
258 }
259
260 DECLARE_DYNAMIC_CLASS(wxFontMapperModule)
261 };
262
263 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule, wxModule)
264
265
266 // ============================================================================
267 // wxFontMapperBase implementation
268 // ============================================================================
269
270 wxFontMapper *wxFontMapperBase::sm_instance = NULL;
271
272 // ----------------------------------------------------------------------------
273 // ctor and dtor
274 // ----------------------------------------------------------------------------
275
276 wxFontMapperBase::wxFontMapperBase()
277 {
278 #if wxUSE_CONFIG && wxUSE_FILECONFIG
279 m_configDummy = NULL;
280 #endif // wxUSE_CONFIG
281 }
282
283 wxFontMapperBase::~wxFontMapperBase()
284 {
285 #if wxUSE_CONFIG && wxUSE_FILECONFIG
286 if ( m_configDummy )
287 delete m_configDummy;
288 #endif // wxUSE_CONFIG
289 }
290
291 /* static */
292 wxFontMapperBase *wxFontMapperBase::Get()
293 {
294 if ( !sm_instance )
295 {
296 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
297 if ( traits )
298 {
299 sm_instance = traits->CreateFontMapper();
300
301 wxASSERT_MSG( sm_instance,
302 _T("wxAppTraits::CreateFontMapper() failed") );
303 }
304
305 if ( !sm_instance )
306 {
307 // last resort: we must create something because the existing code
308 // relies on always having a valid font mapper object
309 sm_instance = (wxFontMapper *)new wxFontMapperBase;
310 }
311 }
312
313 return (wxFontMapperBase*)sm_instance;
314 }
315
316 /* static */
317 wxFontMapper *wxFontMapperBase::Set(wxFontMapper *mapper)
318 {
319 wxFontMapper *old = sm_instance;
320 sm_instance = mapper;
321 return old;
322 }
323
324 /* static */
325 void wxFontMapperBase::Reset()
326 {
327 if ( sm_instance )
328 {
329 // we need a cast as wxFontMapper is not fully declared here and so the
330 // compiler can't know that it derives from wxFontMapperBase (but
331 // run-time behaviour will be correct because the dtor is virtual)
332 delete (wxFontMapperBase *)sm_instance;
333 sm_instance = NULL;
334 }
335 }
336
337 #if wxUSE_CONFIG && wxUSE_FILECONFIG
338
339 // ----------------------------------------------------------------------------
340 // config usage customisation
341 // ----------------------------------------------------------------------------
342
343
344 static wxString gs_defaultConfigPath(FONTMAPPER_ROOT_PATH);
345
346 /* static */
347 const wxString& wxFontMapperBase::GetDefaultConfigPath()
348 {
349 // NB: we return const wxString& and not wxString for compatibility
350 // with 2.8 that returned const wxChar*
351 return gs_defaultConfigPath;
352 }
353
354 void wxFontMapperBase::SetConfigPath(const wxString& prefix)
355 {
356 wxCHECK_RET( !prefix.empty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
357 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
358
359 m_configRootPath = prefix;
360 }
361
362 // ----------------------------------------------------------------------------
363 // get config object and path for it
364 // ----------------------------------------------------------------------------
365
366 wxConfigBase *wxFontMapperBase::GetConfig()
367 {
368 wxConfigBase *config = wxConfig::Get(false);
369
370 // If there is no global configuration, use an internal memory configuration
371 if ( !config )
372 {
373 if ( !m_configDummy )
374 m_configDummy = new wxMemoryConfig;
375 config = m_configDummy;
376
377 // FIXME: ideally, we should add keys from dummy config to a real one later,
378 // but it is a low-priority task because typical wxWin application
379 // either doesn't use wxConfig at all or creates wxConfig object in
380 // wxApp::OnInit(), before any real interaction with the user takes
381 // place...
382 }
383
384 return config;
385 }
386
387 const wxString& wxFontMapperBase::GetConfigPath()
388 {
389 if ( !m_configRootPath )
390 {
391 // use the default
392 m_configRootPath = GetDefaultConfigPath();
393 }
394
395 return m_configRootPath;
396 }
397
398 // ----------------------------------------------------------------------------
399 // config helpers
400 // ----------------------------------------------------------------------------
401
402 bool wxFontMapperBase::ChangePath(const wxString& pathNew, wxString *pathOld)
403 {
404 wxConfigBase *config = GetConfig();
405 if ( !config )
406 return false;
407
408 *pathOld = config->GetPath();
409
410 wxString path = GetConfigPath();
411 if ( path.empty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
412 {
413 path += wxCONFIG_PATH_SEPARATOR;
414 }
415
416 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
417 wxT("should be a relative path") );
418
419 path += pathNew;
420
421 config->SetPath(path);
422
423 return true;
424 }
425
426 void wxFontMapperBase::RestorePath(const wxString& pathOld)
427 {
428 GetConfig()->SetPath(pathOld);
429 }
430
431 #endif
432
433 // ----------------------------------------------------------------------------
434 // charset/encoding correspondence
435 // ----------------------------------------------------------------------------
436
437 wxFontEncoding
438 wxFontMapperBase::CharsetToEncoding(const wxString& charset,
439 bool WXUNUSED(interactive))
440 {
441 int enc = NonInteractiveCharsetToEncoding(charset);
442 if ( enc == wxFONTENCODING_UNKNOWN )
443 {
444 // we should return wxFONTENCODING_SYSTEM from here for unknown
445 // encodings
446 enc = wxFONTENCODING_SYSTEM;
447 }
448
449 return (wxFontEncoding)enc;
450 }
451
452 int
453 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString& charset)
454 {
455 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
456
457 // we're going to modify it, make a copy
458 wxString cs = charset;
459
460 #if wxUSE_CONFIG && wxUSE_FILECONFIG
461 // first try the user-defined settings
462 wxFontMapperPathChanger path(this, FONTMAPPER_CHARSET_PATH);
463 if ( path.IsOk() )
464 {
465 wxConfigBase *config = GetConfig();
466
467 // do we have an encoding for this charset?
468 long value = config->Read(charset, -1l);
469 if ( value != -1 )
470 {
471 if ( value == wxFONTENCODING_UNKNOWN )
472 {
473 // don't try to find it, in particular don't ask the user
474 return value;
475 }
476
477 if ( value >= 0 && value <= wxFONTENCODING_MAX )
478 {
479 encoding = (wxFontEncoding)value;
480 }
481 else
482 {
483 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
484 value, charset.c_str());
485 }
486 }
487
488 if ( encoding == wxFONTENCODING_SYSTEM )
489 {
490 // may be we have an alias?
491 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
492
493 wxString alias = config->Read(charset);
494 if ( !alias.empty() )
495 {
496 // yes, we do - use it instead
497 cs = alias;
498 }
499 }
500 }
501 #endif // wxUSE_CONFIG
502
503 // if didn't find it there, try to recognize it ourselves
504 if ( encoding == wxFONTENCODING_SYSTEM )
505 {
506 // trim any spaces
507 cs.Trim(true);
508 cs.Trim(false);
509
510 // discard the optional quotes
511 if ( !cs.empty() )
512 {
513 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
514 {
515 cs = wxString(cs.c_str(), cs.length() - 1);
516 }
517 }
518
519 for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); ++i )
520 {
521 for ( const wxChar** encName = gs_encodingNames[i]; *encName; ++encName )
522 {
523 if ( cs.CmpNoCase(*encName) == 0 )
524 return gs_encodings[i];
525 }
526 }
527
528 cs.MakeUpper();
529
530 if ( cs.Left(3) == wxT("ISO") )
531 {
532 // the dash is optional (or, to be exact, it is not, but
533 // several broken programs "forget" it)
534 const wxChar *p = cs.c_str() + 3;
535 if ( *p == wxT('-') )
536 p++;
537
538 unsigned int value;
539 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
540 {
541 // make it 0 based and check that it is strictly positive in
542 // the process (no such thing as iso8859-0 encoding)
543 if ( (value-- > 0) &&
544 (value < wxFONTENCODING_ISO8859_MAX -
545 wxFONTENCODING_ISO8859_1) )
546 {
547 // it's a valid ISO8859 encoding
548 value += wxFONTENCODING_ISO8859_1;
549 encoding = (wxFontEncoding)value;
550 }
551 }
552 }
553 else if ( cs.Left(4) == wxT("8859") )
554 {
555 const wxChar *p = cs.c_str();
556
557 unsigned int value;
558 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
559 {
560 // make it 0 based and check that it is strictly positive in
561 // the process (no such thing as iso8859-0 encoding)
562 if ( (value-- > 0) &&
563 (value < wxFONTENCODING_ISO8859_MAX -
564 wxFONTENCODING_ISO8859_1) )
565 {
566 // it's a valid ISO8859 encoding
567 value += wxFONTENCODING_ISO8859_1;
568 encoding = (wxFontEncoding)value;
569 }
570 }
571 }
572 else // check for Windows charsets
573 {
574 size_t len;
575 if ( cs.Left(7) == wxT("WINDOWS") )
576 {
577 len = 7;
578 }
579 else if ( cs.Left(2) == wxT("CP") )
580 {
581 len = 2;
582 }
583 else // not a Windows encoding
584 {
585 len = 0;
586 }
587
588 if ( len )
589 {
590 const wxChar *p = cs.c_str() + len;
591 if ( *p == wxT('-') )
592 p++;
593
594 unsigned int value;
595 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
596 {
597 if ( value >= 1250 )
598 {
599 value -= 1250;
600 if ( value < wxFONTENCODING_CP12_MAX -
601 wxFONTENCODING_CP1250 )
602 {
603 // a valid Windows code page
604 value += wxFONTENCODING_CP1250;
605 encoding = (wxFontEncoding)value;
606 }
607 }
608
609 switch ( value )
610 {
611 case 866:
612 encoding = wxFONTENCODING_CP866;
613 break;
614
615 case 874:
616 encoding = wxFONTENCODING_CP874;
617 break;
618
619 case 932:
620 encoding = wxFONTENCODING_CP932;
621 break;
622
623 case 936:
624 encoding = wxFONTENCODING_CP936;
625 break;
626
627 case 949:
628 encoding = wxFONTENCODING_CP949;
629 break;
630
631 case 950:
632 encoding = wxFONTENCODING_CP950;
633 break;
634 }
635 }
636 }
637 }
638 //else: unknown
639 }
640
641 return encoding;
642 }
643
644 /* static */
645 size_t wxFontMapperBase::GetSupportedEncodingsCount()
646 {
647 return WXSIZEOF(gs_encodings);
648 }
649
650 /* static */
651 wxFontEncoding wxFontMapperBase::GetEncoding(size_t n)
652 {
653 wxCHECK_MSG( n < WXSIZEOF(gs_encodings), wxFONTENCODING_SYSTEM,
654 _T("wxFontMapper::GetEncoding(): invalid index") );
655
656 return gs_encodings[n];
657 }
658
659 /* static */
660 wxString wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding)
661 {
662 if ( encoding == wxFONTENCODING_DEFAULT )
663 {
664 return _("Default encoding");
665 }
666
667 const size_t count = WXSIZEOF(gs_encodingDescs);
668
669 for ( size_t i = 0; i < count; i++ )
670 {
671 if ( gs_encodings[i] == encoding )
672 {
673 return wxGetTranslation(gs_encodingDescs[i]);
674 }
675 }
676
677 wxString str;
678 str.Printf(_("Unknown encoding (%d)"), encoding);
679
680 return str;
681 }
682
683 /* static */
684 wxString wxFontMapperBase::GetEncodingName(wxFontEncoding encoding)
685 {
686 if ( encoding == wxFONTENCODING_DEFAULT )
687 {
688 return _("default");
689 }
690
691 const size_t count = WXSIZEOF(gs_encodingNames);
692
693 for ( size_t i = 0; i < count; i++ )
694 {
695 if ( gs_encodings[i] == encoding )
696 {
697 return gs_encodingNames[i][0];
698 }
699 }
700
701 wxString str;
702 str.Printf(_("unknown-%d"), encoding);
703
704 return str;
705 }
706
707 /* static */
708 const wxChar** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding)
709 {
710 static const wxChar* dummy[] = { NULL };
711
712 for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); i++ )
713 {
714 if ( gs_encodings[i] == encoding )
715 {
716 return gs_encodingNames[i];
717 }
718 }
719
720 return dummy;
721 }
722
723 /* static */
724 wxFontEncoding wxFontMapperBase::GetEncodingFromName(const wxString& name)
725 {
726 const size_t count = WXSIZEOF(gs_encodingNames);
727
728 for ( size_t i = 0; i < count; i++ )
729 {
730 for ( const wxChar** encName = gs_encodingNames[i]; *encName; ++encName )
731 {
732 if ( name.CmpNoCase(*encName) == 0 )
733 return gs_encodings[i];
734 }
735 }
736
737 return wxFONTENCODING_MAX;
738 }
739
740 #endif // wxUSE_FONTMAP