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") )
526 encoding
= wxFONTENCODING_EUC_JP
;
528 else if ( cs
== wxT("EUC-KR") ||
529 cs
== wxT("EUC_KR") )
531 encoding
= wxFONTENCODING_CP949
;
533 else if ( cs
== wxT("KOI8-R") ||
534 cs
== wxT("KOI8-RU") )
536 // although koi8-ru is not strictly speaking the same as koi8-r,
537 // they are similar enough to make mapping it to koi8 better than
538 // not recognizing it at all
539 encoding
= wxFONTENCODING_KOI8
;
541 else if ( cs
== wxT("KOI8-U") )
543 encoding
= wxFONTENCODING_KOI8_U
;
545 else if ( cs
.Left(3) == wxT("ISO") )
547 // the dash is optional (or, to be exact, it is not, but
548 // several brokenmails "forget" it)
549 const wxChar
*p
= cs
.c_str() + 3;
550 if ( *p
== wxT('-') )
553 // printf( "iso %s\n", (const char*) cs.ToAscii() );
556 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
558 // printf( "value %d\n", (int)value );
560 // make it 0 based and check that it is strictly positive in
561 // the process (no such thing as iso8859-0 encoding)
562 if ( (value
-- > 0) &&
563 (value
< wxFONTENCODING_ISO8859_MAX
-
564 wxFONTENCODING_ISO8859_1
) )
566 // it's a valid ISO8859 encoding
567 value
+= wxFONTENCODING_ISO8859_1
;
568 encoding
= (wxFontEncoding
)value
;
572 else if ( cs
.Left(4) == wxT("8859") )
574 const wxChar
*p
= cs
.c_str();
577 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
579 // printf( "value %d\n", (int)value );
581 // make it 0 based and check that it is strictly positive in
582 // the process (no such thing as iso8859-0 encoding)
583 if ( (value
-- > 0) &&
584 (value
< wxFONTENCODING_ISO8859_MAX
-
585 wxFONTENCODING_ISO8859_1
) )
587 // it's a valid ISO8859 encoding
588 value
+= wxFONTENCODING_ISO8859_1
;
589 encoding
= (wxFontEncoding
)value
;
593 else // check for Windows charsets
596 if ( cs
.Left(7) == wxT("WINDOWS") )
600 else if ( cs
.Left(2) == wxT("CP") )
604 else // not a Windows encoding
611 const wxChar
*p
= cs
.c_str() + len
;
612 if ( *p
== wxT('-') )
616 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
621 if ( value
< wxFONTENCODING_CP12_MAX
-
622 wxFONTENCODING_CP1250
)
624 // a valid Windows code page
625 value
+= wxFONTENCODING_CP1250
;
626 encoding
= (wxFontEncoding
)value
;
633 encoding
= wxFONTENCODING_CP874
;
637 encoding
= wxFONTENCODING_CP932
;
641 encoding
= wxFONTENCODING_CP936
;
645 encoding
= wxFONTENCODING_CP949
;
649 encoding
= wxFONTENCODING_CP950
;
662 size_t wxFontMapperBase::GetSupportedEncodingsCount()
664 return WXSIZEOF(gs_encodings
);
668 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
670 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
671 _T("wxFontMapper::GetEncoding(): invalid index") );
673 return gs_encodings
[n
];
677 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
679 if ( encoding
== wxFONTENCODING_DEFAULT
)
681 return _("Default encoding");
684 const size_t count
= WXSIZEOF(gs_encodingDescs
);
686 for ( size_t i
= 0; i
< count
; i
++ )
688 if ( gs_encodings
[i
] == encoding
)
690 return wxGetTranslation(gs_encodingDescs
[i
]);
695 str
.Printf(_("Unknown encoding (%d)"), encoding
);
701 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
703 if ( encoding
== wxFONTENCODING_DEFAULT
)
708 const size_t count
= WXSIZEOF(gs_encodingNames
);
710 for ( size_t i
= 0; i
< count
; i
++ )
712 if ( gs_encodings
[i
] == encoding
)
714 return gs_encodingNames
[i
];
719 str
.Printf(_("unknown-%d"), encoding
);
725 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
727 const size_t count
= WXSIZEOF(gs_encodingNames
);
729 for ( size_t i
= 0; i
< count
; i
++ )
731 if ( gs_encodingNames
[i
] == name
)
733 return gs_encodings
[i
];
737 if ( name
== _("default") )
739 return wxFONTENCODING_DEFAULT
;
742 return wxFONTENCODING_MAX
;
745 #endif // wxUSE_FONTMAP