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
,
81 wxFONTENCODING_CP1250
,
82 wxFONTENCODING_CP1251
,
83 wxFONTENCODING_CP1252
,
84 wxFONTENCODING_CP1253
,
85 wxFONTENCODING_CP1254
,
86 wxFONTENCODING_CP1255
,
87 wxFONTENCODING_CP1256
,
88 wxFONTENCODING_CP1257
,
93 wxFONTENCODING_UTF16BE
,
94 wxFONTENCODING_UTF16LE
,
96 wxFONTENCODING_UTF32BE
,
97 wxFONTENCODING_UTF32LE
,
98 wxFONTENCODING_EUC_JP
,
101 // the descriptions for them
102 static const wxChar
* gs_encodingDescs
[] =
104 wxTRANSLATE( "Western European (ISO-8859-1)" ),
105 wxTRANSLATE( "Central European (ISO-8859-2)" ),
106 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
107 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
108 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
109 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
110 wxTRANSLATE( "Greek (ISO-8859-7)" ),
111 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
112 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
113 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
114 wxTRANSLATE( "Thai (ISO-8859-11)" ),
115 wxTRANSLATE( "Indian (ISO-8859-12)" ),
116 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
117 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
118 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
119 wxTRANSLATE( "KOI8-R" ),
120 wxTRANSLATE( "KOI8-U" ),
121 wxTRANSLATE( "Windows Thai (CP 874)" ),
122 wxTRANSLATE( "Windows Japanese (CP 932)" ),
123 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
124 wxTRANSLATE( "Windows Korean (CP 949)" ),
125 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
126 wxTRANSLATE( "Windows Central European (CP 1250)" ),
127 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
128 wxTRANSLATE( "Windows Western European (CP 1252)" ),
129 wxTRANSLATE( "Windows Greek (CP 1253)" ),
130 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
131 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
132 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
133 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
134 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
135 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
136 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
137 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
138 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
139 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
140 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
141 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
142 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
143 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
146 // and the internal names (these are not translated on purpose!)
147 static const wxChar
* gs_encodingNames
[] =
158 wxT( "iso-8859-10" ),
159 wxT( "iso-8859-11" ),
160 wxT( "iso-8859-12" ),
161 wxT( "iso-8859-13" ),
162 wxT( "iso-8859-14" ),
163 wxT( "iso-8859-15" ),
166 wxT( "windows-874" ),
167 wxT( "windows-932" ),
168 wxT( "windows-936" ),
169 wxT( "windows-949" ),
170 wxT( "windows-950" ),
171 wxT( "windows-1250" ),
172 wxT( "windows-1251" ),
173 wxT( "windows-1252" ),
174 wxT( "windows-1253" ),
175 wxT( "windows-1254" ),
176 wxT( "windows-1255" ),
177 wxT( "windows-1256" ),
178 wxT( "windows-1257" ),
179 wxT( "windows-437" ),
191 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs
) == WXSIZEOF(gs_encodings
) &&
192 WXSIZEOF(gs_encodingNames
) == WXSIZEOF(gs_encodings
),
193 EncodingsArraysNotInSync
);
195 // ----------------------------------------------------------------------------
197 // ----------------------------------------------------------------------------
199 // clean up the font mapper object
200 class wxFontMapperModule
: public wxModule
203 wxFontMapperModule() : wxModule() { }
204 virtual bool OnInit() { return true; }
205 virtual void OnExit() { delete (wxFontMapperBase
*)wxFontMapperBase::Set(NULL
); }
207 DECLARE_DYNAMIC_CLASS(wxFontMapperModule
)
210 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule
, wxModule
)
213 // ============================================================================
214 // wxFontMapperBase implementation
215 // ============================================================================
217 wxFontMapper
*wxFontMapperBase::sm_instance
= NULL
;
219 // ----------------------------------------------------------------------------
221 // ----------------------------------------------------------------------------
223 wxFontMapperBase::wxFontMapperBase()
225 #if wxUSE_CONFIG && wxUSE_FILECONFIG
227 m_configIsDummy
= false;
228 #endif // wxUSE_CONFIG
231 wxFontMapperBase::~wxFontMapperBase()
233 #if wxUSE_CONFIG && wxUSE_FILECONFIG
234 if ( m_configIsDummy
)
236 #endif // wxUSE_CONFIG
239 bool wxFontMapperBase::IsWxFontMapper()
243 wxFontMapperBase
*wxFontMapperBase::Get()
247 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
250 sm_instance
= traits
->CreateFontMapper();
252 wxASSERT_MSG( sm_instance
,
253 _T("wxAppTraits::CreateFontMapper() failed") );
258 // last resort: we must create something because the existing code
259 // relies on always having a valid font mapper object
260 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
264 return (wxFontMapperBase
*)sm_instance
;
268 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
270 wxFontMapper
*old
= sm_instance
;
271 sm_instance
= mapper
;
275 #if wxUSE_CONFIG && wxUSE_FILECONFIG
277 // ----------------------------------------------------------------------------
278 // config usage customisation
279 // ----------------------------------------------------------------------------
282 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
284 return FONTMAPPER_ROOT_PATH
;
287 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
289 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
290 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
292 m_configRootPath
= prefix
;
295 // ----------------------------------------------------------------------------
296 // get config object and path for it
297 // ----------------------------------------------------------------------------
299 wxConfigBase
*wxFontMapperBase::GetConfig()
304 m_config
= wxConfig::Get(false /*don't create on demand*/ );
308 // we still want to have a config object because otherwise we would
309 // keep asking the user the same questions in the interactive mode,
310 // so create a dummy config which won't write to any files/registry
311 // but will allow us to remember the results of the questions at
312 // least during this run
313 m_config
= new wxMemoryConfig
;
314 m_configIsDummy
= true;
315 // VS: we can't call wxConfig::Set(m_config) here because that would
316 // disable automatic wxConfig instance creation if this code was
317 // called before wxApp::OnInit (this happens in wxGTK -- it sets
318 // default wxFont encoding in wxApp::Initialize())
322 if ( m_configIsDummy
&& wxConfig::Get(false) != NULL
)
324 // VS: in case we created dummy m_config (see above), we want to switch back
325 // to the real one as soon as one becomes available.
327 m_config
= wxConfig::Get(false);
328 m_configIsDummy
= false;
329 // FIXME: ideally, we should add keys from dummy config to the real one now,
330 // but it is a low-priority task because typical wxWin application
331 // either doesn't use wxConfig at all or creates wxConfig object in
332 // wxApp::OnInit(), before any real interaction with the user takes
339 const wxString
& wxFontMapperBase::GetConfigPath()
341 if ( !m_configRootPath
)
344 m_configRootPath
= GetDefaultConfigPath();
347 return m_configRootPath
;
350 // ----------------------------------------------------------------------------
352 // ----------------------------------------------------------------------------
354 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
356 wxConfigBase
*config
= GetConfig();
360 *pathOld
= config
->GetPath();
362 wxString path
= GetConfigPath();
363 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
365 path
+= wxCONFIG_PATH_SEPARATOR
;
368 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
369 wxT("should be a relative path") );
373 config
->SetPath(path
);
378 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
380 GetConfig()->SetPath(pathOld
);
385 // ----------------------------------------------------------------------------
386 // charset/encoding correspondence
387 // ----------------------------------------------------------------------------
390 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
391 bool WXUNUSED(interactive
))
393 int enc
= NonInteractiveCharsetToEncoding(charset
);
394 if ( enc
== wxFONTENCODING_UNKNOWN
)
396 // we should return wxFONTENCODING_SYSTEM from here for unknown
398 enc
= wxFONTENCODING_SYSTEM
;
401 return (wxFontEncoding
)enc
;
405 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
407 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
409 // we're going to modify it, make a copy
410 wxString cs
= charset
;
412 #if wxUSE_CONFIG && wxUSE_FILECONFIG
413 // first try the user-defined settings
414 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
417 wxConfigBase
*config
= GetConfig();
419 // do we have an encoding for this charset?
420 long value
= config
->Read(charset
, -1l);
423 if ( value
== wxFONTENCODING_UNKNOWN
)
425 // don't try to find it, in particular don't ask the user
429 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
431 encoding
= (wxFontEncoding
)value
;
435 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
436 value
, charset
.c_str());
440 if ( encoding
== wxFONTENCODING_SYSTEM
)
442 // may be we have an alias?
443 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
445 wxString alias
= config
->Read(charset
);
446 if ( !alias
.IsEmpty() )
448 // yes, we do - use it instead
453 #endif // wxUSE_CONFIG
455 // if didn't find it there, try to recognize it ourselves
456 if ( encoding
== wxFONTENCODING_SYSTEM
)
462 // discard the optional quotes
465 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
467 cs
= wxString(cs
.c_str(), cs
.length() - 1);
473 if ( cs
.empty() || cs
== _T("US-ASCII") )
475 encoding
= wxFONTENCODING_DEFAULT
;
477 else if ( cs
== wxT("UTF-7") )
479 encoding
= wxFONTENCODING_UTF7
;
481 else if ( cs
== wxT("UTF-8") )
483 encoding
= wxFONTENCODING_UTF8
;
485 else if ( cs
== wxT("UTF-16") )
487 encoding
= wxFONTENCODING_UTF16
;
489 else if ( cs
== wxT("UTF-16BE") )
491 encoding
= wxFONTENCODING_UTF16BE
;
493 else if ( cs
== wxT("UTF-16LE") )
495 encoding
= wxFONTENCODING_UTF16LE
;
497 else if ( cs
== wxT("UTF-32") || cs
== wxT("UCS-4") )
499 encoding
= wxFONTENCODING_UTF32
;
501 else if ( cs
== wxT("UTF-32BE") || cs
== wxT("UCS-4BE") )
503 encoding
= wxFONTENCODING_UTF32BE
;
505 else if ( cs
== wxT("UTF-32LE") || cs
== wxT("UCS-4LE") )
507 encoding
= wxFONTENCODING_UTF32LE
;
509 else if ( cs
== wxT("GB2312") )
511 encoding
= wxFONTENCODING_GB2312
;
513 else if ( cs
== wxT("BIG5") )
515 encoding
= wxFONTENCODING_BIG5
;
517 else if ( cs
== wxT("SJIS") ||
518 cs
== wxT("SHIFT_JIS") ||
519 cs
== wxT("SHIFT-JIS") )
521 encoding
= wxFONTENCODING_SHIFT_JIS
;
523 else if ( cs
== wxT("EUC-JP") ||
524 cs
== wxT("EUC_JP") ||
527 encoding
= wxFONTENCODING_EUC_JP
;
529 else if ( cs
== wxT("EUC-KR") ||
530 cs
== wxT("EUC_KR") )
532 encoding
= wxFONTENCODING_CP949
;
534 else if ( cs
== wxT("KOI8-R") ||
535 cs
== wxT("KOI8-RU") )
537 // although koi8-ru is not strictly speaking the same as koi8-r,
538 // they are similar enough to make mapping it to koi8 better than
539 // not recognizing it at all
540 encoding
= wxFONTENCODING_KOI8
;
542 else if ( cs
== wxT("KOI8-U") )
544 encoding
= wxFONTENCODING_KOI8_U
;
546 else if ( cs
.Left(3) == wxT("ISO") )
548 // the dash is optional (or, to be exact, it is not, but
549 // several brokenmails "forget" it)
550 const wxChar
*p
= cs
.c_str() + 3;
551 if ( *p
== wxT('-') )
554 // printf( "iso %s\n", (const char*) cs.ToAscii() );
557 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
559 // printf( "value %d\n", (int)value );
561 // make it 0 based and check that it is strictly positive in
562 // the process (no such thing as iso8859-0 encoding)
563 if ( (value
-- > 0) &&
564 (value
< wxFONTENCODING_ISO8859_MAX
-
565 wxFONTENCODING_ISO8859_1
) )
567 // it's a valid ISO8859 encoding
568 value
+= wxFONTENCODING_ISO8859_1
;
569 encoding
= (wxFontEncoding
)value
;
573 else if ( cs
.Left(4) == wxT("8859") )
575 const wxChar
*p
= cs
.c_str();
578 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
580 // printf( "value %d\n", (int)value );
582 // make it 0 based and check that it is strictly positive in
583 // the process (no such thing as iso8859-0 encoding)
584 if ( (value
-- > 0) &&
585 (value
< wxFONTENCODING_ISO8859_MAX
-
586 wxFONTENCODING_ISO8859_1
) )
588 // it's a valid ISO8859 encoding
589 value
+= wxFONTENCODING_ISO8859_1
;
590 encoding
= (wxFontEncoding
)value
;
594 else // check for Windows charsets
597 if ( cs
.Left(7) == wxT("WINDOWS") )
601 else if ( cs
.Left(2) == wxT("CP") )
605 else // not a Windows encoding
612 const wxChar
*p
= cs
.c_str() + len
;
613 if ( *p
== wxT('-') )
617 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
622 if ( value
< wxFONTENCODING_CP12_MAX
-
623 wxFONTENCODING_CP1250
)
625 // a valid Windows code page
626 value
+= wxFONTENCODING_CP1250
;
627 encoding
= (wxFontEncoding
)value
;
634 encoding
= wxFONTENCODING_CP874
;
638 encoding
= wxFONTENCODING_CP932
;
642 encoding
= wxFONTENCODING_CP936
;
646 encoding
= wxFONTENCODING_CP949
;
650 encoding
= wxFONTENCODING_CP950
;
663 size_t wxFontMapperBase::GetSupportedEncodingsCount()
665 return WXSIZEOF(gs_encodings
);
669 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
671 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
672 _T("wxFontMapper::GetEncoding(): invalid index") );
674 return gs_encodings
[n
];
678 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
680 if ( encoding
== wxFONTENCODING_DEFAULT
)
682 return _("Default encoding");
685 const size_t count
= WXSIZEOF(gs_encodingDescs
);
687 for ( size_t i
= 0; i
< count
; i
++ )
689 if ( gs_encodings
[i
] == encoding
)
691 return wxGetTranslation(gs_encodingDescs
[i
]);
696 str
.Printf(_("Unknown encoding (%d)"), encoding
);
702 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
704 if ( encoding
== wxFONTENCODING_DEFAULT
)
709 const size_t count
= WXSIZEOF(gs_encodingNames
);
711 for ( size_t i
= 0; i
< count
; i
++ )
713 if ( gs_encodings
[i
] == encoding
)
715 return gs_encodingNames
[i
];
720 str
.Printf(_("unknown-%d"), encoding
);
726 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
728 const size_t count
= WXSIZEOF(gs_encodingNames
);
730 for ( size_t i
= 0; i
< count
; i
++ )
732 if ( gs_encodingNames
[i
] == name
)
734 return gs_encodings
[i
];
738 if ( name
== _("default") )
740 return wxFONTENCODING_DEFAULT
;
743 return wxFONTENCODING_MAX
;
746 #endif // wxUSE_FONTMAP