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