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
,
92 wxFONTENCODING_UTF16BE
,
93 wxFONTENCODING_UTF16LE
,
94 wxFONTENCODING_UTF32BE
,
95 wxFONTENCODING_UTF32LE
,
96 wxFONTENCODING_EUC_JP
,
97 wxFONTENCODING_DEFAULT
,
99 wxFONTENCODING_SHIFT_JIS
,
100 wxFONTENCODING_GB2312
,
103 // the descriptions for them
104 static const wxChar
* gs_encodingDescs
[] =
106 wxTRANSLATE( "Western European (ISO-8859-1)" ),
107 wxTRANSLATE( "Central European (ISO-8859-2)" ),
108 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
109 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
110 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
111 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
112 wxTRANSLATE( "Greek (ISO-8859-7)" ),
113 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
114 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
115 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
116 wxTRANSLATE( "Thai (ISO-8859-11)" ),
117 wxTRANSLATE( "Indian (ISO-8859-12)" ),
118 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
119 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
120 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
121 wxTRANSLATE( "KOI8-R" ),
122 wxTRANSLATE( "KOI8-U" ),
123 wxTRANSLATE( "Windows Thai (CP 874)" ),
124 wxTRANSLATE( "Windows Japanese (CP 932)" ),
125 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
126 wxTRANSLATE( "Windows Korean (CP 949)" ),
127 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
128 wxTRANSLATE( "Windows Central European (CP 1250)" ),
129 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
130 wxTRANSLATE( "Windows Western European (CP 1252)" ),
131 wxTRANSLATE( "Windows Greek (CP 1253)" ),
132 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
133 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
134 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
135 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
136 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
137 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
138 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
139 #ifdef WORDS_BIGENDIAN
140 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
141 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
142 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
143 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
144 #else // WORDS_BIGENDIAN
145 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
146 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
147 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
148 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
149 #endif // WORDS_BIGENDIAN
150 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
151 wxTRANSLATE( "US-ASCII" ),
152 wxTRANSLATE( "BIG5" ),
153 wxTRANSLATE( "SHIFT-JIS" ),
154 wxTRANSLATE( "GB-2312" ),
157 // and the internal names (these are not translated on purpose!)
158 static const wxChar
* gs_encodingNames
[WXSIZEOF(gs_encodingDescs
)][10] =
160 // names from the columns correspond to these OS:
161 // Linux Solaris and IRIX HP-UX AIX
162 { _T("ISO-8859-1"), _T("ISO8859-1"), _T("iso88591"), _T("8859-1"), wxT("iso_8859_1"), NULL
},
163 { _T("ISO-8859-2"), _T("ISO8859-2"), _T("iso88592"), _T("8859-2"), NULL
},
164 { _T("ISO-8859-3"), _T("ISO8859-3"), _T("iso88593"), _T("8859-3"), NULL
},
165 { _T("ISO-8859-4"), _T("ISO8859-4"), _T("iso88594"), _T("8859-4"), NULL
},
166 { _T("ISO-8859-5"), _T("ISO8859-5"), _T("iso88595"), _T("8859-5"), NULL
},
167 { _T("ISO-8859-6"), _T("ISO8859-6"), _T("iso88596"), _T("8859-6"), NULL
},
168 { _T("ISO-8859-7"), _T("ISO8859-7"), _T("iso88597"), _T("8859-7"), NULL
},
169 { _T("ISO-8859-8"), _T("ISO8859-8"), _T("iso88598"), _T("8859-8"), NULL
},
170 { _T("ISO-8859-9"), _T("ISO8859-9"), _T("iso88599"), _T("8859-9"), NULL
},
171 { _T("ISO-8859-10"), _T("ISO8859-10"), _T("iso885910"), _T("8859-10"), NULL
},
172 { _T("ISO-8859-11"), _T("ISO8859-11"), _T("iso885911"), _T("8859-11"), NULL
},
173 { _T("ISO-8859-12"), _T("ISO8859-12"), _T("iso885912"), _T("8859-12"), NULL
},
174 { _T("ISO-8859-13"), _T("ISO8859-13"), _T("iso885913"), _T("8859-13"), NULL
},
175 { _T("ISO-8859-14"), _T("ISO8859-14"), _T("iso885914"), _T("8859-14"), NULL
},
176 { _T("ISO-8859-15"), _T("ISO8859-15"), _T("iso885915"), _T("8859-15"), NULL
},
178 // although koi8-ru is not strictly speaking the same as koi8-r,
179 // they are similar enough to make mapping it to koi8 better than
180 // not recognizing it at all
181 { wxT( "KOI8-R" ), wxT( "KOI8-RU" ), NULL
},
182 { wxT( "KOI8-U" ), NULL
},
184 { wxT( "WINDOWS-874" ), wxT( "CP-874" ), NULL
},
185 { wxT( "WINDOWS-932" ), wxT( "CP-932" ), NULL
},
186 { wxT( "WINDOWS-936" ), wxT( "CP-936" ), NULL
},
187 { wxT( "WINDOWS-949" ), wxT( "CP-949" ), wxT( "EUC-KR" ), wxT( "eucKR" ), wxT( "euc_kr" ), NULL
},
188 { wxT( "WINDOWS-950" ), wxT( "CP-950" ), NULL
},
189 { wxT( "WINDOWS-1250" ),wxT( "CP-1250" ), NULL
},
190 { wxT( "WINDOWS-1251" ),wxT( "CP-1251" ), NULL
},
191 { wxT( "WINDOWS-1252" ),wxT( "CP-1252" ), wxT("IBM-1252"), NULL
},
192 { wxT( "WINDOWS-1253" ),wxT( "CP-1253" ), NULL
},
193 { wxT( "WINDOWS-1254" ),wxT( "CP-1254" ), NULL
},
194 { wxT( "WINDOWS-1255" ),wxT( "CP-1255" ), NULL
},
195 { wxT( "WINDOWS-1256" ),wxT( "CP-1256" ), NULL
},
196 { wxT( "WINDOWS-1257" ),wxT( "CP-1257" ), NULL
},
197 { wxT( "WINDOWS-437" ), wxT( "CP-437" ), NULL
},
199 { wxT( "UTF-7" ), wxT("utf7"), NULL
},
200 { wxT( "UTF-8" ), wxT("utf8"), NULL
},
201 #ifdef WORDS_BIGENDIAN
202 { wxT( "UTF-16BE" ), wxT("UCS-2BE"), wxT( "UTF-16" ), wxT("UCS-2"), wxT("UCS2"), NULL
},
203 { wxT( "UTF-16LE" ), wxT("UCS-2LE"), NULL
},
204 { wxT( "UTF-32BE" ), wxT( "UCS-4BE" ), wxT( "UTF-32" ), wxT( "UCS-4" ), wxT("UCS4"), NULL
},
205 { wxT( "UTF-32LE" ), wxT( "UCS-4LE" ), NULL
},
206 #else // WORDS_BIGENDIAN
207 { wxT( "UTF-16BE" ), wxT("UCS-2BE"), NULL
},
208 { wxT( "UTF-16LE" ), wxT("UCS-2LE"), wxT( "UTF-16" ), wxT("UCS-2"), wxT("UCS2"), NULL
},
209 { wxT( "UTF-32BE" ), wxT( "UCS-4BE" ), NULL
},
210 { wxT( "UTF-32LE" ), wxT( "UCS-4LE" ), wxT( "UTF-32" ), wxT( "UCS-4" ), wxT("UCS4"), NULL
},
211 #endif // WORDS_BIGENDIAN
213 { wxT( "EUC-JP" ), wxT( "eucJP" ), wxT( "euc_jp" ), wxT( "IBM-eucJP" ), NULL
},
215 // 646 is for Solaris, roman8 -- for HP-UX
216 { wxT( "US-ASCII" ), wxT( "ASCII" ), wxT("C"), wxT("POSIX"), wxT("ANSI_X3.4-1968"),
217 wxT("646"), wxT("roman8"), wxT( "" ), NULL
},
219 { wxT( "BIG5" ), wxT("big5"), NULL
},
220 { wxT( "SJIS" ), wxT( "SHIFT-JIS" ), wxT( "SHIFT_JIS" ), NULL
},
221 { wxT( "GB2312" ), NULL
},
224 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
225 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingNames
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
227 // ----------------------------------------------------------------------------
229 // ----------------------------------------------------------------------------
231 // clean up the font mapper object
232 class wxFontMapperModule
: public wxModule
235 wxFontMapperModule() : wxModule() { }
236 virtual bool OnInit() { return true; }
237 virtual void OnExit() { delete (wxFontMapperBase
*)wxFontMapperBase::Set(NULL
); }
239 DECLARE_DYNAMIC_CLASS(wxFontMapperModule
)
242 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule
, wxModule
)
245 // ============================================================================
246 // wxFontMapperBase implementation
247 // ============================================================================
249 wxFontMapper
*wxFontMapperBase::sm_instance
= NULL
;
251 // ----------------------------------------------------------------------------
253 // ----------------------------------------------------------------------------
255 wxFontMapperBase::wxFontMapperBase()
257 #if wxUSE_CONFIG && wxUSE_FILECONFIG
258 m_configDummy
= NULL
;
259 #endif // wxUSE_CONFIG
262 wxFontMapperBase::~wxFontMapperBase()
264 #if wxUSE_CONFIG && wxUSE_FILECONFIG
266 delete m_configDummy
;
267 #endif // wxUSE_CONFIG
270 bool wxFontMapperBase::IsWxFontMapper()
274 wxFontMapperBase
*wxFontMapperBase::Get()
278 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
281 sm_instance
= traits
->CreateFontMapper();
283 wxASSERT_MSG( sm_instance
,
284 _T("wxAppTraits::CreateFontMapper() failed") );
289 // last resort: we must create something because the existing code
290 // relies on always having a valid font mapper object
291 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
295 return (wxFontMapperBase
*)sm_instance
;
299 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
301 wxFontMapper
*old
= sm_instance
;
302 sm_instance
= mapper
;
306 #if wxUSE_CONFIG && wxUSE_FILECONFIG
308 // ----------------------------------------------------------------------------
309 // config usage customisation
310 // ----------------------------------------------------------------------------
313 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
315 return FONTMAPPER_ROOT_PATH
;
318 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
320 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
321 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
323 m_configRootPath
= prefix
;
326 // ----------------------------------------------------------------------------
327 // get config object and path for it
328 // ----------------------------------------------------------------------------
330 wxConfigBase
*wxFontMapperBase::GetConfig()
332 wxConfigBase
*config
= wxConfig::Get(false);
334 // If there is no global configuration, use an internal memory configuration
337 if ( !m_configDummy
)
338 m_configDummy
= new wxMemoryConfig
;
339 config
= m_configDummy
;
341 // FIXME: ideally, we should add keys from dummy config to a real one later,
342 // but it is a low-priority task because typical wxWin application
343 // either doesn't use wxConfig at all or creates wxConfig object in
344 // wxApp::OnInit(), before any real interaction with the user takes
351 const wxString
& wxFontMapperBase::GetConfigPath()
353 if ( !m_configRootPath
)
356 m_configRootPath
= GetDefaultConfigPath();
359 return m_configRootPath
;
362 // ----------------------------------------------------------------------------
364 // ----------------------------------------------------------------------------
366 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
368 wxConfigBase
*config
= GetConfig();
372 *pathOld
= config
->GetPath();
374 wxString path
= GetConfigPath();
375 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
377 path
+= wxCONFIG_PATH_SEPARATOR
;
380 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
381 wxT("should be a relative path") );
385 config
->SetPath(path
);
390 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
392 GetConfig()->SetPath(pathOld
);
397 // ----------------------------------------------------------------------------
398 // charset/encoding correspondence
399 // ----------------------------------------------------------------------------
402 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
403 bool WXUNUSED(interactive
))
405 int enc
= NonInteractiveCharsetToEncoding(charset
);
406 if ( enc
== wxFONTENCODING_UNKNOWN
)
408 // we should return wxFONTENCODING_SYSTEM from here for unknown
410 enc
= wxFONTENCODING_SYSTEM
;
413 return (wxFontEncoding
)enc
;
417 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
419 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
421 // we're going to modify it, make a copy
422 wxString cs
= charset
;
424 #if wxUSE_CONFIG && wxUSE_FILECONFIG
425 // first try the user-defined settings
426 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
429 wxConfigBase
*config
= GetConfig();
431 // do we have an encoding for this charset?
432 long value
= config
->Read(charset
, -1l);
435 if ( value
== wxFONTENCODING_UNKNOWN
)
437 // don't try to find it, in particular don't ask the user
441 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
443 encoding
= (wxFontEncoding
)value
;
447 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
448 value
, charset
.c_str());
452 if ( encoding
== wxFONTENCODING_SYSTEM
)
454 // may be we have an alias?
455 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
457 wxString alias
= config
->Read(charset
);
458 if ( !alias
.IsEmpty() )
460 // yes, we do - use it instead
465 #endif // wxUSE_CONFIG
467 // if didn't find it there, try to recognize it ourselves
468 if ( encoding
== wxFONTENCODING_SYSTEM
)
474 // discard the optional quotes
477 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
479 cs
= wxString(cs
.c_str(), cs
.length() - 1);
483 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); ++i
)
485 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
487 if ( cs
.CmpNoCase(*encName
) == 0 )
488 return gs_encodings
[i
];
494 if ( cs
.Left(3) == wxT("ISO") )
496 // the dash is optional (or, to be exact, it is not, but
497 // several brokenmails "forget" it)
498 const wxChar
*p
= cs
.c_str() + 3;
499 if ( *p
== wxT('-') )
502 // printf( "iso %s\n", (const char*) cs.ToAscii() );
505 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
507 // printf( "value %d\n", (int)value );
509 // make it 0 based and check that it is strictly positive in
510 // the process (no such thing as iso8859-0 encoding)
511 if ( (value
-- > 0) &&
512 (value
< wxFONTENCODING_ISO8859_MAX
-
513 wxFONTENCODING_ISO8859_1
) )
515 // it's a valid ISO8859 encoding
516 value
+= wxFONTENCODING_ISO8859_1
;
517 encoding
= (wxFontEncoding
)value
;
521 else if ( cs
.Left(4) == wxT("8859") )
523 const wxChar
*p
= cs
.c_str();
526 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
528 // printf( "value %d\n", (int)value );
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
) )
536 // it's a valid ISO8859 encoding
537 value
+= wxFONTENCODING_ISO8859_1
;
538 encoding
= (wxFontEncoding
)value
;
542 else // check for Windows charsets
545 if ( cs
.Left(7) == wxT("WINDOWS") )
549 else if ( cs
.Left(2) == wxT("CP") )
553 else // not a Windows encoding
560 const wxChar
*p
= cs
.c_str() + len
;
561 if ( *p
== wxT('-') )
565 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
570 if ( value
< wxFONTENCODING_CP12_MAX
-
571 wxFONTENCODING_CP1250
)
573 // a valid Windows code page
574 value
+= wxFONTENCODING_CP1250
;
575 encoding
= (wxFontEncoding
)value
;
582 encoding
= wxFONTENCODING_CP874
;
586 encoding
= wxFONTENCODING_CP932
;
590 encoding
= wxFONTENCODING_CP936
;
594 encoding
= wxFONTENCODING_CP949
;
598 encoding
= wxFONTENCODING_CP950
;
611 size_t wxFontMapperBase::GetSupportedEncodingsCount()
613 return WXSIZEOF(gs_encodings
);
617 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
619 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
620 _T("wxFontMapper::GetEncoding(): invalid index") );
622 return gs_encodings
[n
];
626 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
628 if ( encoding
== wxFONTENCODING_DEFAULT
)
630 return _("Default encoding");
633 const size_t count
= WXSIZEOF(gs_encodingDescs
);
635 for ( size_t i
= 0; i
< count
; i
++ )
637 if ( gs_encodings
[i
] == encoding
)
639 return wxGetTranslation(gs_encodingDescs
[i
]);
644 str
.Printf(_("Unknown encoding (%d)"), encoding
);
650 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
652 if ( encoding
== wxFONTENCODING_DEFAULT
)
657 const size_t count
= WXSIZEOF(gs_encodingNames
);
659 for ( size_t i
= 0; i
< count
; i
++ )
661 if ( gs_encodings
[i
] == encoding
)
663 return gs_encodingNames
[i
][0];
668 str
.Printf(_("unknown-%d"), encoding
);
674 const wxChar
** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding
)
676 static const wxChar
* dummy
[] = { NULL
};
678 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); i
++ )
680 if ( gs_encodings
[i
] == encoding
)
682 return gs_encodingNames
[i
];
690 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
692 const size_t count
= WXSIZEOF(gs_encodingNames
);
694 for ( size_t i
= 0; i
< count
; i
++ )
696 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
698 if ( name
.CmpNoCase(*encName
) == 0 )
699 return gs_encodings
[i
];
703 return wxFONTENCODING_MAX
;
706 #endif // wxUSE_FONTMAP