1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: common/fmapbase.cpp
3 // Purpose: wxFontMapperBase class implementation
4 // Author: Vadim Zeitlin
6 // Created: 21.06.2003 (extracted from common/fontmap.cpp)
8 // Copyright: (c) 1999-2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
35 #if defined(__WXMSW__)
36 #include "wx/msw/private.h" // includes windows.h for LOGFONT
37 #include "wx/msw/winundef.h"
40 #include "wx/fontmap.h"
41 #include "wx/fmappriv.h"
43 #include "wx/apptrait.h"
44 #include "wx/module.h"
46 // wxMemoryConfig uses wxFileConfig
47 #if wxUSE_CONFIG && wxUSE_FILECONFIG
48 #include "wx/config.h"
49 #include "wx/memconf.h"
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 // encodings supported by GetEncodingDescription
57 static wxFontEncoding gs_encodings
[] =
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
,
75 wxFONTENCODING_KOI8_U
,
80 wxFONTENCODING_CP1250
,
81 wxFONTENCODING_CP1251
,
82 wxFONTENCODING_CP1252
,
83 wxFONTENCODING_CP1253
,
84 wxFONTENCODING_CP1254
,
85 wxFONTENCODING_CP1255
,
86 wxFONTENCODING_CP1256
,
87 wxFONTENCODING_CP1257
,
92 wxFONTENCODING_UTF16BE
,
93 wxFONTENCODING_UTF16LE
,
95 wxFONTENCODING_UTF32BE
,
96 wxFONTENCODING_UTF32LE
,
97 wxFONTENCODING_EUC_JP
,
100 // the descriptions for them
101 static const wxChar
* gs_encodingDescs
[] =
103 wxTRANSLATE( "Western European (ISO-8859-1)" ),
104 wxTRANSLATE( "Central European (ISO-8859-2)" ),
105 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
106 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
107 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
108 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
109 wxTRANSLATE( "Greek (ISO-8859-7)" ),
110 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
111 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
112 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
113 wxTRANSLATE( "Thai (ISO-8859-11)" ),
114 wxTRANSLATE( "Indian (ISO-8859-12)" ),
115 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
116 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
117 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
118 wxTRANSLATE( "KOI8-R" ),
119 wxTRANSLATE( "KOI8-U" ),
120 wxTRANSLATE( "Windows Japanese (CP 932)" ),
121 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
122 wxTRANSLATE( "Windows Korean (CP 949)" ),
123 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
124 wxTRANSLATE( "Windows Central European (CP 1250)" ),
125 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
126 wxTRANSLATE( "Windows Western European (CP 1252)" ),
127 wxTRANSLATE( "Windows Greek (CP 1253)" ),
128 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
129 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
130 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
131 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
132 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
133 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
134 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
135 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
136 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
137 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
138 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
139 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
140 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
141 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
144 // and the internal names (these are not translated on purpose!)
145 static const wxChar
* gs_encodingNames
[] =
156 wxT( "iso-8859-10" ),
157 wxT( "iso-8859-11" ),
158 wxT( "iso-8859-12" ),
159 wxT( "iso-8859-13" ),
160 wxT( "iso-8859-14" ),
161 wxT( "iso-8859-15" ),
164 wxT( "windows-932" ),
165 wxT( "windows-936" ),
166 wxT( "windows-949" ),
167 wxT( "windows-950" ),
168 wxT( "windows-1250" ),
169 wxT( "windows-1251" ),
170 wxT( "windows-1252" ),
171 wxT( "windows-1253" ),
172 wxT( "windows-1254" ),
173 wxT( "windows-1255" ),
174 wxT( "windows-1256" ),
175 wxT( "windows-1257" ),
176 wxT( "windows-437" ),
188 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs
) == WXSIZEOF(gs_encodings
) &&
189 WXSIZEOF(gs_encodingNames
) == WXSIZEOF(gs_encodings
),
190 EncodingsArraysNotInSync
);
192 // ----------------------------------------------------------------------------
194 // ----------------------------------------------------------------------------
196 // clean up the font mapper object
197 class wxFontMapperModule
: public wxModule
200 wxFontMapperModule() : wxModule() { }
201 virtual bool OnInit() { return true; }
202 virtual void OnExit() { delete wxFontMapper::Set(NULL
); }
204 DECLARE_DYNAMIC_CLASS(wxFontMapperModule
)
207 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule
, wxModule
)
210 // ============================================================================
211 // wxFontMapperBase implementation
212 // ============================================================================
214 wxFontMapper
*wxFontMapperBase::sm_instance
= NULL
;
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
220 wxFontMapperBase::wxFontMapperBase()
222 #if wxUSE_CONFIG && wxUSE_FILECONFIG
224 m_configIsDummy
= false;
225 #endif // wxUSE_CONFIG
228 wxFontMapperBase::~wxFontMapperBase()
230 #if wxUSE_CONFIG && wxUSE_FILECONFIG
231 if ( m_configIsDummy
)
233 #endif // wxUSE_CONFIG
237 wxFontMapper
*wxFontMapperBase::Get()
241 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
244 sm_instance
= traits
->CreateFontMapper();
246 wxASSERT_MSG( sm_instance
,
247 _T("wxAppTraits::CreateFontMapper() failed") );
252 // last resort: we must create something because the existing code
253 // relies on always having a valid font mapper object
254 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
262 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
264 wxFontMapper
*old
= sm_instance
;
265 sm_instance
= mapper
;
269 #if wxUSE_CONFIG && wxUSE_FILECONFIG
271 // ----------------------------------------------------------------------------
272 // config usage customisation
273 // ----------------------------------------------------------------------------
276 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
278 return FONTMAPPER_ROOT_PATH
;
281 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
283 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
284 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
286 m_configRootPath
= prefix
;
289 // ----------------------------------------------------------------------------
290 // get config object and path for it
291 // ----------------------------------------------------------------------------
293 wxConfigBase
*wxFontMapperBase::GetConfig()
298 m_config
= wxConfig::Get(false /*don't create on demand*/ );
302 // we still want to have a config object because otherwise we would
303 // keep asking the user the same questions in the interactive mode,
304 // so create a dummy config which won't write to any files/registry
305 // but will allow us to remember the results of the questions at
306 // least during this run
307 m_config
= new wxMemoryConfig
;
308 m_configIsDummy
= true;
309 // VS: we can't call wxConfig::Set(m_config) here because that would
310 // disable automatic wxConfig instance creation if this code was
311 // called before wxApp::OnInit (this happens in wxGTK -- it sets
312 // default wxFont encoding in wxApp::Initialize())
316 if ( m_configIsDummy
&& wxConfig::Get(false) != NULL
)
318 // VS: in case we created dummy m_config (see above), we want to switch back
319 // to the real one as soon as one becomes available.
321 m_config
= wxConfig::Get(false);
322 m_configIsDummy
= false;
323 // FIXME: ideally, we should add keys from dummy config to the real one now,
324 // but it is a low-priority task because typical wxWin application
325 // either doesn't use wxConfig at all or creates wxConfig object in
326 // wxApp::OnInit(), before any real interaction with the user takes
333 const wxString
& wxFontMapperBase::GetConfigPath()
335 if ( !m_configRootPath
)
338 m_configRootPath
= GetDefaultConfigPath();
341 return m_configRootPath
;
344 // ----------------------------------------------------------------------------
346 // ----------------------------------------------------------------------------
348 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
350 wxConfigBase
*config
= GetConfig();
354 *pathOld
= config
->GetPath();
356 wxString path
= GetConfigPath();
357 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
359 path
+= wxCONFIG_PATH_SEPARATOR
;
362 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
363 wxT("should be a relative path") );
367 config
->SetPath(path
);
372 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
374 GetConfig()->SetPath(pathOld
);
379 // ----------------------------------------------------------------------------
380 // charset/encoding correspondence
381 // ----------------------------------------------------------------------------
384 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
385 bool WXUNUSED(interactive
))
387 int enc
= NonInteractiveCharsetToEncoding(charset
);
388 if ( enc
== wxFONTENCODING_UNKNOWN
)
390 // we should return wxFONTENCODING_SYSTEM from here for unknown
392 enc
= wxFONTENCODING_SYSTEM
;
395 return (wxFontEncoding
)enc
;
399 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
401 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
403 // we're going to modify it, make a copy
404 wxString cs
= charset
;
406 #if wxUSE_CONFIG && wxUSE_FILECONFIG
407 // first try the user-defined settings
408 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
411 wxConfigBase
*config
= GetConfig();
413 // do we have an encoding for this charset?
414 long value
= config
->Read(charset
, -1l);
417 if ( value
== wxFONTENCODING_UNKNOWN
)
419 // don't try to find it, in particular don't ask the user
423 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
425 encoding
= (wxFontEncoding
)value
;
429 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
430 value
, charset
.c_str());
434 if ( encoding
== wxFONTENCODING_SYSTEM
)
436 // may be we have an alias?
437 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
439 wxString alias
= config
->Read(charset
);
440 if ( !alias
.IsEmpty() )
442 // yes, we do - use it instead
447 #endif // wxUSE_CONFIG
449 // if didn't find it there, try to recognize it ourselves
450 if ( encoding
== wxFONTENCODING_SYSTEM
)
456 // discard the optional quotes
459 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
461 cs
= wxString(cs
.c_str(), cs
.length() - 1);
467 if ( cs
.empty() || cs
== _T("US-ASCII") )
469 encoding
= wxFONTENCODING_DEFAULT
;
471 else if ( cs
== wxT("UTF-7") )
473 encoding
= wxFONTENCODING_UTF7
;
475 else if ( cs
== wxT("UTF-8") )
477 encoding
= wxFONTENCODING_UTF8
;
479 else if ( cs
== wxT("UTF-16") )
481 encoding
= wxFONTENCODING_UTF16
;
483 else if ( cs
== wxT("UTF-16BE") )
485 encoding
= wxFONTENCODING_UTF16BE
;
487 else if ( cs
== wxT("UTF-16LE") )
489 encoding
= wxFONTENCODING_UTF16LE
;
491 else if ( cs
== wxT("UTF-32") || cs
== wxT("UCS-4") )
493 encoding
= wxFONTENCODING_UTF32
;
495 else if ( cs
== wxT("UTF-32BE") || cs
== wxT("UCS-4BE") )
497 encoding
= wxFONTENCODING_UTF32BE
;
499 else if ( cs
== wxT("UTF-32LE") || cs
== wxT("UCS-4LE") )
501 encoding
= wxFONTENCODING_UTF32LE
;
503 else if ( cs
== wxT("GB2312") )
505 encoding
= wxFONTENCODING_GB2312
;
507 else if ( cs
== wxT("BIG5") )
509 encoding
= wxFONTENCODING_BIG5
;
511 else if ( cs
== wxT("SJIS") ||
512 cs
== wxT("SHIFT_JIS") ||
513 cs
== wxT("SHIFT-JIS") )
515 encoding
= wxFONTENCODING_SHIFT_JIS
;
517 else if ( cs
== wxT("EUC-JP") ||
518 cs
== wxT("EUC_JP") )
520 encoding
= wxFONTENCODING_EUC_JP
;
522 else if ( cs
== wxT("EUC-KR") ||
523 cs
== wxT("EUC_KR") )
525 encoding
= wxFONTENCODING_CP949
;
527 else if ( cs
== wxT("KOI8-R") ||
528 cs
== wxT("KOI8-RU") )
530 // although koi8-ru is not strictly speaking the same as koi8-r,
531 // they are similar enough to make mapping it to koi8 better than
532 // not recognizing it at all
533 encoding
= wxFONTENCODING_KOI8
;
535 else if ( cs
== wxT("KOI8-U") )
537 encoding
= wxFONTENCODING_KOI8_U
;
539 else if ( cs
.Left(3) == wxT("ISO") )
541 // the dash is optional (or, to be exact, it is not, but
542 // several brokenmails "forget" it)
543 const wxChar
*p
= cs
.c_str() + 3;
544 if ( *p
== wxT('-') )
547 // printf( "iso %s\n", (const char*) cs.ToAscii() );
550 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
552 // printf( "value %d\n", (int)value );
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
) )
560 // it's a valid ISO8859 encoding
561 value
+= wxFONTENCODING_ISO8859_1
;
562 encoding
= (wxFontEncoding
)value
;
566 else if ( cs
.Left(4) == wxT("8859") )
568 const wxChar
*p
= cs
.c_str();
571 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
573 // printf( "value %d\n", (int)value );
575 // make it 0 based and check that it is strictly positive in
576 // the process (no such thing as iso8859-0 encoding)
577 if ( (value
-- > 0) &&
578 (value
< wxFONTENCODING_ISO8859_MAX
-
579 wxFONTENCODING_ISO8859_1
) )
581 // it's a valid ISO8859 encoding
582 value
+= wxFONTENCODING_ISO8859_1
;
583 encoding
= (wxFontEncoding
)value
;
587 else // check for Windows charsets
590 if ( cs
.Left(7) == wxT("WINDOWS") )
594 else if ( cs
.Left(2) == wxT("CP") )
598 else // not a Windows encoding
605 const wxChar
*p
= cs
.c_str() + len
;
606 if ( *p
== wxT('-') )
610 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
615 if ( value
< wxFONTENCODING_CP12_MAX
-
616 wxFONTENCODING_CP1250
)
618 // a valid Windows code page
619 value
+= wxFONTENCODING_CP1250
;
620 encoding
= (wxFontEncoding
)value
;
627 encoding
= wxFONTENCODING_CP932
;
631 encoding
= wxFONTENCODING_CP936
;
635 encoding
= wxFONTENCODING_CP949
;
639 encoding
= wxFONTENCODING_CP950
;
652 size_t wxFontMapperBase::GetSupportedEncodingsCount()
654 return WXSIZEOF(gs_encodings
);
658 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
660 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
661 _T("wxFontMapper::GetEncoding(): invalid index") );
663 return gs_encodings
[n
];
667 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
669 if ( encoding
== wxFONTENCODING_DEFAULT
)
671 return _("Default encoding");
674 const size_t count
= WXSIZEOF(gs_encodingDescs
);
676 for ( size_t i
= 0; i
< count
; i
++ )
678 if ( gs_encodings
[i
] == encoding
)
680 return wxGetTranslation(gs_encodingDescs
[i
]);
685 str
.Printf(_("Unknown encoding (%d)"), encoding
);
691 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
693 if ( encoding
== wxFONTENCODING_DEFAULT
)
698 const size_t count
= WXSIZEOF(gs_encodingNames
);
700 for ( size_t i
= 0; i
< count
; i
++ )
702 if ( gs_encodings
[i
] == encoding
)
704 return gs_encodingNames
[i
];
709 str
.Printf(_("unknown-%d"), encoding
);
715 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
717 const size_t count
= WXSIZEOF(gs_encodingNames
);
719 for ( size_t i
= 0; i
< count
; i
++ )
721 if ( gs_encodingNames
[i
] == name
)
723 return gs_encodings
[i
];
727 if ( name
== _("default") )
729 return wxFONTENCODING_DEFAULT
;
732 return wxFONTENCODING_MAX
;
735 #endif // wxUSE_FONTMAP