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