use UTF8-encoded char* strings in UTF8 build instead of wchar_t* if the current local...
[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 /* static */
341 const wxChar *wxFontMapperBase::GetDefaultConfigPath()
342 {
343 return FONTMAPPER_ROOT_PATH;
344 }
345
346 void wxFontMapperBase::SetConfigPath(const wxString& prefix)
347 {
348 wxCHECK_RET( !prefix.empty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
349 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
350
351 m_configRootPath = prefix;
352 }
353
354 // ----------------------------------------------------------------------------
355 // get config object and path for it
356 // ----------------------------------------------------------------------------
357
358 wxConfigBase *wxFontMapperBase::GetConfig()
359 {
360 wxConfigBase *config = wxConfig::Get(false);
361
362 // If there is no global configuration, use an internal memory configuration
363 if ( !config )
364 {
365 if ( !m_configDummy )
366 m_configDummy = new wxMemoryConfig;
367 config = m_configDummy;
368
369 // FIXME: ideally, we should add keys from dummy config to a real one later,
370 // but it is a low-priority task because typical wxWin application
371 // either doesn't use wxConfig at all or creates wxConfig object in
372 // wxApp::OnInit(), before any real interaction with the user takes
373 // place...
374 }
375
376 return config;
377 }
378
379 const wxString& wxFontMapperBase::GetConfigPath()
380 {
381 if ( !m_configRootPath )
382 {
383 // use the default
384 m_configRootPath = GetDefaultConfigPath();
385 }
386
387 return m_configRootPath;
388 }
389
390 // ----------------------------------------------------------------------------
391 // config helpers
392 // ----------------------------------------------------------------------------
393
394 bool wxFontMapperBase::ChangePath(const wxString& pathNew, wxString *pathOld)
395 {
396 wxConfigBase *config = GetConfig();
397 if ( !config )
398 return false;
399
400 *pathOld = config->GetPath();
401
402 wxString path = GetConfigPath();
403 if ( path.empty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
404 {
405 path += wxCONFIG_PATH_SEPARATOR;
406 }
407
408 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
409 wxT("should be a relative path") );
410
411 path += pathNew;
412
413 config->SetPath(path);
414
415 return true;
416 }
417
418 void wxFontMapperBase::RestorePath(const wxString& pathOld)
419 {
420 GetConfig()->SetPath(pathOld);
421 }
422
423 #endif
424
425 // ----------------------------------------------------------------------------
426 // charset/encoding correspondence
427 // ----------------------------------------------------------------------------
428
429 wxFontEncoding
430 wxFontMapperBase::CharsetToEncoding(const wxString& charset,
431 bool WXUNUSED(interactive))
432 {
433 int enc = NonInteractiveCharsetToEncoding(charset);
434 if ( enc == wxFONTENCODING_UNKNOWN )
435 {
436 // we should return wxFONTENCODING_SYSTEM from here for unknown
437 // encodings
438 enc = wxFONTENCODING_SYSTEM;
439 }
440
441 return (wxFontEncoding)enc;
442 }
443
444 int
445 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString& charset)
446 {
447 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
448
449 // we're going to modify it, make a copy
450 wxString cs = charset;
451
452 #if wxUSE_CONFIG && wxUSE_FILECONFIG
453 // first try the user-defined settings
454 wxFontMapperPathChanger path(this, FONTMAPPER_CHARSET_PATH);
455 if ( path.IsOk() )
456 {
457 wxConfigBase *config = GetConfig();
458
459 // do we have an encoding for this charset?
460 long value = config->Read(charset, -1l);
461 if ( value != -1 )
462 {
463 if ( value == wxFONTENCODING_UNKNOWN )
464 {
465 // don't try to find it, in particular don't ask the user
466 return value;
467 }
468
469 if ( value >= 0 && value <= wxFONTENCODING_MAX )
470 {
471 encoding = (wxFontEncoding)value;
472 }
473 else
474 {
475 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
476 value, charset.c_str());
477 }
478 }
479
480 if ( encoding == wxFONTENCODING_SYSTEM )
481 {
482 // may be we have an alias?
483 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
484
485 wxString alias = config->Read(charset);
486 if ( !alias.empty() )
487 {
488 // yes, we do - use it instead
489 cs = alias;
490 }
491 }
492 }
493 #endif // wxUSE_CONFIG
494
495 // if didn't find it there, try to recognize it ourselves
496 if ( encoding == wxFONTENCODING_SYSTEM )
497 {
498 // trim any spaces
499 cs.Trim(true);
500 cs.Trim(false);
501
502 // discard the optional quotes
503 if ( !cs.empty() )
504 {
505 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
506 {
507 cs = wxString(cs.c_str(), cs.length() - 1);
508 }
509 }
510
511 // check for known encoding name
512 const wxFontEncoding e = GetEncodingFromName(cs);
513 if ( e != wxFONTENCODING_MAX )
514 return e;
515
516 // deal with general encoding names of the form FOO-xxx
517 cs.MakeUpper();
518
519 if ( cs.Left(3) == wxT("ISO") )
520 {
521 // the dash is optional (or, to be exact, it is not, but many
522 // broken programs "forget" it in the output they generate)
523 const wxChar *p = cs.c_str() + 3;
524 if ( *p == wxT('-') )
525 p++;
526
527 unsigned int value;
528 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
529 {
530 // make it 0 based and check that it is strictly positive in
531 // the process (no such thing as iso8859-0 encoding)
532 if ( (value-- > 0) &&
533 (value < wxFONTENCODING_ISO8859_MAX -
534 wxFONTENCODING_ISO8859_1) )
535 {
536 // it's a valid ISO8859 encoding
537 value += wxFONTENCODING_ISO8859_1;
538 encoding = (wxFontEncoding)value;
539 }
540 }
541 }
542 else if ( cs.Left(4) == wxT("8859") )
543 {
544 const wxChar *p = cs.c_str();
545
546 unsigned int value;
547 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
548 {
549 // make it 0 based and check that it is strictly positive in
550 // the process (no such thing as iso8859-0 encoding)
551 if ( (value-- > 0) &&
552 (value < wxFONTENCODING_ISO8859_MAX -
553 wxFONTENCODING_ISO8859_1) )
554 {
555 // it's a valid ISO8859 encoding
556 value += wxFONTENCODING_ISO8859_1;
557 encoding = (wxFontEncoding)value;
558 }
559 }
560 }
561 else // check for Windows charsets
562 {
563 size_t len;
564 if ( cs.Left(7) == wxT("WINDOWS") )
565 {
566 len = 7;
567 }
568 else if ( cs.Left(2) == wxT("CP") )
569 {
570 len = 2;
571 }
572 else // not a Windows encoding
573 {
574 len = 0;
575 }
576
577 if ( len )
578 {
579 const wxChar *p = cs.c_str() + len;
580 if ( *p == wxT('-') )
581 p++;
582
583 unsigned int value;
584 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
585 {
586 if ( value >= 1250 )
587 {
588 value -= 1250;
589 if ( value < wxFONTENCODING_CP12_MAX -
590 wxFONTENCODING_CP1250 )
591 {
592 // a valid Windows code page
593 value += wxFONTENCODING_CP1250;
594 encoding = (wxFontEncoding)value;
595 }
596 }
597
598 switch ( value )
599 {
600 case 866:
601 encoding = wxFONTENCODING_CP866;
602 break;
603
604 case 874:
605 encoding = wxFONTENCODING_CP874;
606 break;
607
608 case 932:
609 encoding = wxFONTENCODING_CP932;
610 break;
611
612 case 936:
613 encoding = wxFONTENCODING_CP936;
614 break;
615
616 case 949:
617 encoding = wxFONTENCODING_CP949;
618 break;
619
620 case 950:
621 encoding = wxFONTENCODING_CP950;
622 break;
623 }
624 }
625 }
626 }
627 //else: unknown
628 }
629
630 return encoding;
631 }
632
633 /* static */
634 size_t wxFontMapperBase::GetSupportedEncodingsCount()
635 {
636 return WXSIZEOF(gs_encodings);
637 }
638
639 /* static */
640 wxFontEncoding wxFontMapperBase::GetEncoding(size_t n)
641 {
642 wxCHECK_MSG( n < WXSIZEOF(gs_encodings), wxFONTENCODING_SYSTEM,
643 _T("wxFontMapper::GetEncoding(): invalid index") );
644
645 return gs_encodings[n];
646 }
647
648 /* static */
649 wxString wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding)
650 {
651 if ( encoding == wxFONTENCODING_DEFAULT )
652 {
653 return _("Default encoding");
654 }
655
656 const size_t count = WXSIZEOF(gs_encodingDescs);
657
658 for ( size_t i = 0; i < count; i++ )
659 {
660 if ( gs_encodings[i] == encoding )
661 {
662 return wxGetTranslation(gs_encodingDescs[i]);
663 }
664 }
665
666 wxString str;
667 str.Printf(_("Unknown encoding (%d)"), encoding);
668
669 return str;
670 }
671
672 /* static */
673 wxString wxFontMapperBase::GetEncodingName(wxFontEncoding encoding)
674 {
675 if ( encoding == wxFONTENCODING_DEFAULT )
676 {
677 return _("default");
678 }
679
680 const size_t count = WXSIZEOF(gs_encodingNames);
681
682 for ( size_t i = 0; i < count; i++ )
683 {
684 if ( gs_encodings[i] == encoding )
685 {
686 return gs_encodingNames[i][0];
687 }
688 }
689
690 wxString str;
691 str.Printf(_("unknown-%d"), encoding);
692
693 return str;
694 }
695
696 /* static */
697 const wxChar** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding)
698 {
699 static const wxChar* dummy[] = { NULL };
700
701 for ( size_t i = 0; i < WXSIZEOF(gs_encodingNames); i++ )
702 {
703 if ( gs_encodings[i] == encoding )
704 {
705 return gs_encodingNames[i];
706 }
707 }
708
709 return dummy;
710 }
711
712 /* static */
713 wxFontEncoding wxFontMapperBase::GetEncodingFromName(const wxString& name)
714 {
715 const size_t count = WXSIZEOF(gs_encodingNames);
716
717 // many charsets use hyphens in their names but some systems use the
718 // same names without hyphens (e.g. "UTF-8" and "UTF8" are both common)
719 // so to avoid bloating gs_encodingNames array too much recognize both
720 // versions with and without hyphens here
721 wxString nameNoHyphens(name);
722 if ( !nameNoHyphens.Replace(_T("-"), _T("")) )
723 {
724 // no replacement has been done, no need to compare twice
725 nameNoHyphens.clear();
726 }
727
728
729 for ( size_t i = 0; i < count; i++ )
730 {
731 for ( const wxChar** encName = gs_encodingNames[i]; *encName; ++encName )
732 {
733 if ( name.CmpNoCase(*encName) == 0 ||
734 (!nameNoHyphens.empty() &&
735 nameNoHyphens.CmpNoCase(*encName) == 0) )
736 {
737 return gs_encodings[i];
738 }
739 }
740 }
741
742 return wxFONTENCODING_MAX;
743 }
744
745 #endif // wxUSE_FONTMAP