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 (wxFontMapperBase
*)wxFontMapperBase::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
236 bool wxFontMapperBase::IsWxFontMapper()
240 wxFontMapperBase
*wxFontMapperBase::Get()
244 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
247 sm_instance
= traits
->CreateFontMapper();
249 wxASSERT_MSG( sm_instance
,
250 _T("wxAppTraits::CreateFontMapper() failed") );
255 // last resort: we must create something because the existing code
256 // relies on always having a valid font mapper object
257 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
261 return (wxFontMapperBase
*)sm_instance
;
265 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
267 wxFontMapper
*old
= sm_instance
;
268 sm_instance
= mapper
;
272 #if wxUSE_CONFIG && wxUSE_FILECONFIG
274 // ----------------------------------------------------------------------------
275 // config usage customisation
276 // ----------------------------------------------------------------------------
279 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
281 return FONTMAPPER_ROOT_PATH
;
284 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
286 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
287 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
289 m_configRootPath
= prefix
;
292 // ----------------------------------------------------------------------------
293 // get config object and path for it
294 // ----------------------------------------------------------------------------
296 wxConfigBase
*wxFontMapperBase::GetConfig()
301 m_config
= wxConfig::Get(false /*don't create on demand*/ );
305 // we still want to have a config object because otherwise we would
306 // keep asking the user the same questions in the interactive mode,
307 // so create a dummy config which won't write to any files/registry
308 // but will allow us to remember the results of the questions at
309 // least during this run
310 m_config
= new wxMemoryConfig
;
311 m_configIsDummy
= true;
312 // VS: we can't call wxConfig::Set(m_config) here because that would
313 // disable automatic wxConfig instance creation if this code was
314 // called before wxApp::OnInit (this happens in wxGTK -- it sets
315 // default wxFont encoding in wxApp::Initialize())
319 if ( m_configIsDummy
&& wxConfig::Get(false) != NULL
)
321 // VS: in case we created dummy m_config (see above), we want to switch back
322 // to the real one as soon as one becomes available.
324 m_config
= wxConfig::Get(false);
325 m_configIsDummy
= false;
326 // FIXME: ideally, we should add keys from dummy config to the real one now,
327 // but it is a low-priority task because typical wxWin application
328 // either doesn't use wxConfig at all or creates wxConfig object in
329 // wxApp::OnInit(), before any real interaction with the user takes
336 const wxString
& wxFontMapperBase::GetConfigPath()
338 if ( !m_configRootPath
)
341 m_configRootPath
= GetDefaultConfigPath();
344 return m_configRootPath
;
347 // ----------------------------------------------------------------------------
349 // ----------------------------------------------------------------------------
351 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
353 wxConfigBase
*config
= GetConfig();
357 *pathOld
= config
->GetPath();
359 wxString path
= GetConfigPath();
360 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
362 path
+= wxCONFIG_PATH_SEPARATOR
;
365 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
366 wxT("should be a relative path") );
370 config
->SetPath(path
);
375 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
377 GetConfig()->SetPath(pathOld
);
382 // ----------------------------------------------------------------------------
383 // charset/encoding correspondence
384 // ----------------------------------------------------------------------------
387 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
388 bool WXUNUSED(interactive
))
390 int enc
= NonInteractiveCharsetToEncoding(charset
);
391 if ( enc
== wxFONTENCODING_UNKNOWN
)
393 // we should return wxFONTENCODING_SYSTEM from here for unknown
395 enc
= wxFONTENCODING_SYSTEM
;
398 return (wxFontEncoding
)enc
;
402 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
404 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
406 // we're going to modify it, make a copy
407 wxString cs
= charset
;
409 #if wxUSE_CONFIG && wxUSE_FILECONFIG
410 // first try the user-defined settings
411 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
414 wxConfigBase
*config
= GetConfig();
416 // do we have an encoding for this charset?
417 long value
= config
->Read(charset
, -1l);
420 if ( value
== wxFONTENCODING_UNKNOWN
)
422 // don't try to find it, in particular don't ask the user
426 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
428 encoding
= (wxFontEncoding
)value
;
432 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
433 value
, charset
.c_str());
437 if ( encoding
== wxFONTENCODING_SYSTEM
)
439 // may be we have an alias?
440 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
442 wxString alias
= config
->Read(charset
);
443 if ( !alias
.IsEmpty() )
445 // yes, we do - use it instead
450 #endif // wxUSE_CONFIG
452 // if didn't find it there, try to recognize it ourselves
453 if ( encoding
== wxFONTENCODING_SYSTEM
)
459 // discard the optional quotes
462 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
464 cs
= wxString(cs
.c_str(), cs
.length() - 1);
470 if ( cs
.empty() || cs
== _T("US-ASCII") )
472 encoding
= wxFONTENCODING_DEFAULT
;
474 else if ( cs
== wxT("UTF-7") )
476 encoding
= wxFONTENCODING_UTF7
;
478 else if ( cs
== wxT("UTF-8") )
480 encoding
= wxFONTENCODING_UTF8
;
482 else if ( cs
== wxT("UTF-16") )
484 encoding
= wxFONTENCODING_UTF16
;
486 else if ( cs
== wxT("UTF-16BE") )
488 encoding
= wxFONTENCODING_UTF16BE
;
490 else if ( cs
== wxT("UTF-16LE") )
492 encoding
= wxFONTENCODING_UTF16LE
;
494 else if ( cs
== wxT("UTF-32") || cs
== wxT("UCS-4") )
496 encoding
= wxFONTENCODING_UTF32
;
498 else if ( cs
== wxT("UTF-32BE") || cs
== wxT("UCS-4BE") )
500 encoding
= wxFONTENCODING_UTF32BE
;
502 else if ( cs
== wxT("UTF-32LE") || cs
== wxT("UCS-4LE") )
504 encoding
= wxFONTENCODING_UTF32LE
;
506 else if ( cs
== wxT("GB2312") )
508 encoding
= wxFONTENCODING_GB2312
;
510 else if ( cs
== wxT("BIG5") )
512 encoding
= wxFONTENCODING_BIG5
;
514 else if ( cs
== wxT("SJIS") ||
515 cs
== wxT("SHIFT_JIS") ||
516 cs
== wxT("SHIFT-JIS") )
518 encoding
= wxFONTENCODING_SHIFT_JIS
;
520 else if ( cs
== wxT("EUC-JP") ||
521 cs
== wxT("EUC_JP") )
523 encoding
= wxFONTENCODING_EUC_JP
;
525 else if ( cs
== wxT("EUC-KR") ||
526 cs
== wxT("EUC_KR") )
528 encoding
= wxFONTENCODING_CP949
;
530 else if ( cs
== wxT("KOI8-R") ||
531 cs
== wxT("KOI8-RU") )
533 // although koi8-ru is not strictly speaking the same as koi8-r,
534 // they are similar enough to make mapping it to koi8 better than
535 // not recognizing it at all
536 encoding
= wxFONTENCODING_KOI8
;
538 else if ( cs
== wxT("KOI8-U") )
540 encoding
= wxFONTENCODING_KOI8_U
;
542 else if ( cs
.Left(3) == wxT("ISO") )
544 // the dash is optional (or, to be exact, it is not, but
545 // several brokenmails "forget" it)
546 const wxChar
*p
= cs
.c_str() + 3;
547 if ( *p
== wxT('-') )
550 // printf( "iso %s\n", (const char*) cs.ToAscii() );
553 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
555 // printf( "value %d\n", (int)value );
557 // make it 0 based and check that it is strictly positive in
558 // the process (no such thing as iso8859-0 encoding)
559 if ( (value
-- > 0) &&
560 (value
< wxFONTENCODING_ISO8859_MAX
-
561 wxFONTENCODING_ISO8859_1
) )
563 // it's a valid ISO8859 encoding
564 value
+= wxFONTENCODING_ISO8859_1
;
565 encoding
= (wxFontEncoding
)value
;
569 else if ( cs
.Left(4) == wxT("8859") )
571 const wxChar
*p
= cs
.c_str();
574 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
576 // printf( "value %d\n", (int)value );
578 // make it 0 based and check that it is strictly positive in
579 // the process (no such thing as iso8859-0 encoding)
580 if ( (value
-- > 0) &&
581 (value
< wxFONTENCODING_ISO8859_MAX
-
582 wxFONTENCODING_ISO8859_1
) )
584 // it's a valid ISO8859 encoding
585 value
+= wxFONTENCODING_ISO8859_1
;
586 encoding
= (wxFontEncoding
)value
;
590 else // check for Windows charsets
593 if ( cs
.Left(7) == wxT("WINDOWS") )
597 else if ( cs
.Left(2) == wxT("CP") )
601 else // not a Windows encoding
608 const wxChar
*p
= cs
.c_str() + len
;
609 if ( *p
== wxT('-') )
613 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
618 if ( value
< wxFONTENCODING_CP12_MAX
-
619 wxFONTENCODING_CP1250
)
621 // a valid Windows code page
622 value
+= wxFONTENCODING_CP1250
;
623 encoding
= (wxFontEncoding
)value
;
630 encoding
= wxFONTENCODING_CP932
;
634 encoding
= wxFONTENCODING_CP936
;
638 encoding
= wxFONTENCODING_CP949
;
642 encoding
= wxFONTENCODING_CP950
;
655 size_t wxFontMapperBase::GetSupportedEncodingsCount()
657 return WXSIZEOF(gs_encodings
);
661 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
663 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
664 _T("wxFontMapper::GetEncoding(): invalid index") );
666 return gs_encodings
[n
];
670 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
672 if ( encoding
== wxFONTENCODING_DEFAULT
)
674 return _("Default encoding");
677 const size_t count
= WXSIZEOF(gs_encodingDescs
);
679 for ( size_t i
= 0; i
< count
; i
++ )
681 if ( gs_encodings
[i
] == encoding
)
683 return wxGetTranslation(gs_encodingDescs
[i
]);
688 str
.Printf(_("Unknown encoding (%d)"), encoding
);
694 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
696 if ( encoding
== wxFONTENCODING_DEFAULT
)
701 const size_t count
= WXSIZEOF(gs_encodingNames
);
703 for ( size_t i
= 0; i
< count
; i
++ )
705 if ( gs_encodings
[i
] == encoding
)
707 return gs_encodingNames
[i
];
712 str
.Printf(_("unknown-%d"), encoding
);
718 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
720 const size_t count
= WXSIZEOF(gs_encodingNames
);
722 for ( size_t i
= 0; i
< count
; i
++ )
724 if ( gs_encodingNames
[i
] == name
)
726 return gs_encodings
[i
];
730 if ( name
== _("default") )
732 return wxFONTENCODING_DEFAULT
;
735 return wxFONTENCODING_MAX
;
738 #endif // wxUSE_FONTMAP