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: fmapbase.cpp 43063 2006-11-04 20:48:04Z VZ $
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 #endif //WX_PRECOMP
35 
36 #if defined(__WXMSW__)
37     #include  "wx/msw/private.h"  // includes windows.h for LOGFONT
38     #include  "wx/msw/winundef.h"
39 #endif
40 
41 #include "wx/fontmap.h"
42 #include "wx/fmappriv.h"
43 
44 #include "wx/apptrait.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:
wxFontMapperModule()235     wxFontMapperModule() : wxModule() { }
236 
OnInit()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 
OnExit()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 
wxFontMapperBase()272 wxFontMapperBase::wxFontMapperBase()
273 {
274 #if wxUSE_CONFIG && wxUSE_FILECONFIG
275     m_configDummy = NULL;
276 #endif // wxUSE_CONFIG
277 }
278 
~wxFontMapperBase()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 */
Get()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 */
Set(wxFontMapper * mapper)313 wxFontMapper *wxFontMapperBase::Set(wxFontMapper *mapper)
314 {
315     wxFontMapper *old = sm_instance;
316     sm_instance = mapper;
317     return old;
318 }
319 
320 /* static */
Reset()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 */
GetDefaultConfigPath()340 const wxChar *wxFontMapperBase::GetDefaultConfigPath()
341 {
342     return FONTMAPPER_ROOT_PATH;
343 }
344 
SetConfigPath(const wxString & prefix)345 void wxFontMapperBase::SetConfigPath(const wxString& prefix)
346 {
347     wxCHECK_RET( !prefix.empty() && 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 
GetConfig()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 
GetConfigPath()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 
ChangePath(const wxString & pathNew,wxString * pathOld)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.empty() || 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 
RestorePath(const wxString & pathOld)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
CharsetToEncoding(const wxString & charset,bool WXUNUSED (interactive))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
NonInteractiveCharsetToEncoding(const wxString & charset)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.empty() )
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 866:
609                             encoding = wxFONTENCODING_CP866;
610                             break;
611 
612                         case 874:
613                             encoding = wxFONTENCODING_CP874;
614                             break;
615 
616                         case 932:
617                             encoding = wxFONTENCODING_CP932;
618                             break;
619 
620                         case 936:
621                             encoding = wxFONTENCODING_CP936;
622                             break;
623 
624                         case 949:
625                             encoding = wxFONTENCODING_CP949;
626                             break;
627 
628                         case 950:
629                             encoding = wxFONTENCODING_CP950;
630                             break;
631                     }
632                 }
633             }
634         }
635         //else: unknown
636     }
637 
638     return encoding;
639 }
640 
641 /* static */
GetSupportedEncodingsCount()642 size_t wxFontMapperBase::GetSupportedEncodingsCount()
643 {
644     return WXSIZEOF(gs_encodings);
645 }
646 
647 /* static */
GetEncoding(size_t n)648 wxFontEncoding wxFontMapperBase::GetEncoding(size_t n)
649 {
650     wxCHECK_MSG( n < WXSIZEOF(gs_encodings), wxFONTENCODING_SYSTEM,
651                     _T("wxFontMapper::GetEncoding(): invalid index") );
652 
653     return gs_encodings[n];
654 }
655 
656 /* static */
GetEncodingDescription(wxFontEncoding encoding)657 wxString wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding)
658 {
659     if ( encoding == wxFONTENCODING_DEFAULT )
660     {
661         return _("Default encoding");
662     }
663 
664     const size_t count = WXSIZEOF(gs_encodingDescs);
665 
666     for ( size_t i = 0; i < count; i++ )
667     {
668         if ( gs_encodings[i] == encoding )
669         {
670             return wxGetTranslation(gs_encodingDescs[i]);
671         }
672     }
673 
674     wxString str;
675     str.Printf(_("Unknown encoding (%d)"), encoding);
676 
677     return str;
678 }
679 
680 /* static */
GetEncodingName(wxFontEncoding encoding)681 wxString wxFontMapperBase::GetEncodingName(wxFontEncoding encoding)
682 {
683     if ( encoding == wxFONTENCODING_DEFAULT )
684     {
685         return _("default");
686     }
687 
688     const size_t count = WXSIZEOF(gs_encodingNames);
689 
690     for ( size_t i = 0; i < count; i++ )
691     {
692         if ( gs_encodings[i] == encoding )
693         {
694             return gs_encodingNames[i][0];
695         }
696     }
697 
698     wxString str;
699     str.Printf(_("unknown-%d"), encoding);
700 
701     return str;
702 }
703 
704 /* static */
GetAllEncodingNames(wxFontEncoding encoding)705 const wxChar** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding)
706 {
707     static const wxChar* dummy[] = { NULL };
708 
709     for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); i++ )
710     {
711         if ( gs_encodings[i] == encoding )
712         {
713             return gs_encodingNames[i];
714         }
715     }
716 
717     return dummy;
718 }
719 
720 /* static */
GetEncodingFromName(const wxString & name)721 wxFontEncoding wxFontMapperBase::GetEncodingFromName(const wxString& name)
722 {
723     const size_t count = WXSIZEOF(gs_encodingNames);
724 
725     for ( size_t i = 0; i < count; i++ )
726     {
727         for ( const wxChar** encName = gs_encodingNames[i]; *encName; ++encName )
728         {
729             if ( name.CmpNoCase(*encName) == 0 )
730                 return gs_encodings[i];
731         }
732     }
733 
734     return wxFONTENCODING_MAX;
735 }
736 
737 #endif // wxUSE_FONTMAP
738