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
,
99 wxFONTENCODING_DEFAULT
,
101 wxFONTENCODING_SHIFT_JIS
,
102 wxFONTENCODING_GB2312
,
105 // the descriptions for them
106 static const wxChar
* gs_encodingDescs
[] =
108 wxTRANSLATE( "Western European (ISO-8859-1)" ),
109 wxTRANSLATE( "Central European (ISO-8859-2)" ),
110 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
111 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
112 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
113 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
114 wxTRANSLATE( "Greek (ISO-8859-7)" ),
115 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
116 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
117 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
118 wxTRANSLATE( "Thai (ISO-8859-11)" ),
119 wxTRANSLATE( "Indian (ISO-8859-12)" ),
120 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
121 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
122 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
123 wxTRANSLATE( "KOI8-R" ),
124 wxTRANSLATE( "KOI8-U" ),
125 wxTRANSLATE( "Windows Thai (CP 874)" ),
126 wxTRANSLATE( "Windows Japanese (CP 932)" ),
127 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
128 wxTRANSLATE( "Windows Korean (CP 949)" ),
129 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
130 wxTRANSLATE( "Windows Central European (CP 1250)" ),
131 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
132 wxTRANSLATE( "Windows Western European (CP 1252)" ),
133 wxTRANSLATE( "Windows Greek (CP 1253)" ),
134 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
135 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
136 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
137 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
138 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
139 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
140 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
141 wxTRANSLATE( "Unicode 16 bit (UTF-16)" ),
142 wxTRANSLATE( "Unicode 16 bit Big Endian (UTF-16BE)" ),
143 wxTRANSLATE( "Unicode 16 bit Little Endian (UTF-16LE)" ),
144 wxTRANSLATE( "Unicode 32 bit (UTF-32)" ),
145 wxTRANSLATE( "Unicode 32 bit Big Endian (UTF-32BE)" ),
146 wxTRANSLATE( "Unicode 32 bit Little Endian (UTF-32LE)" ),
147 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
148 wxTRANSLATE( "US-ASCII" ),
149 wxTRANSLATE( "BIG5" ),
150 wxTRANSLATE( "SHIFT-JIS" ),
151 wxTRANSLATE( "GB-2312" ),
154 // and the internal names (these are not translated on purpose!)
155 static const wxChar
* gs_encodingNames
[WXSIZEOF(gs_encodingDescs
)][10] =
157 // names from the columns correspond to these OS:
158 // Linux Solaris and IRIX HP-UX AIX
159 { _T("ISO-8859-1"), _T("ISO8859-1"), _T("iso88591"), _T("8859-1"), wxT("iso_8859_1"), NULL
},
160 { _T("ISO-8859-2"), _T("ISO8859-2"), _T("iso88592"), _T("8859-2"), NULL
},
161 { _T("ISO-8859-3"), _T("ISO8859-3"), _T("iso88593"), _T("8859-3"), NULL
},
162 { _T("ISO-8859-4"), _T("ISO8859-4"), _T("iso88594"), _T("8859-4"), NULL
},
163 { _T("ISO-8859-5"), _T("ISO8859-5"), _T("iso88595"), _T("8859-5"), NULL
},
164 { _T("ISO-8859-6"), _T("ISO8859-6"), _T("iso88596"), _T("8859-6"), NULL
},
165 { _T("ISO-8859-7"), _T("ISO8859-7"), _T("iso88597"), _T("8859-7"), NULL
},
166 { _T("ISO-8859-8"), _T("ISO8859-8"), _T("iso88598"), _T("8859-8"), NULL
},
167 { _T("ISO-8859-9"), _T("ISO8859-9"), _T("iso88599"), _T("8859-9"), NULL
},
168 { _T("ISO-8859-10"), _T("ISO8859-10"), _T("iso885910"), _T("8859-10"), NULL
},
169 { _T("ISO-8859-11"), _T("ISO8859-11"), _T("iso885911"), _T("8859-11"), NULL
},
170 { _T("ISO-8859-12"), _T("ISO8859-12"), _T("iso885912"), _T("8859-12"), NULL
},
171 { _T("ISO-8859-13"), _T("ISO8859-13"), _T("iso885913"), _T("8859-13"), NULL
},
172 { _T("ISO-8859-14"), _T("ISO8859-14"), _T("iso885914"), _T("8859-14"), NULL
},
173 { _T("ISO-8859-15"), _T("ISO8859-15"), _T("iso885915"), _T("8859-15"), NULL
},
175 // although koi8-ru is not strictly speaking the same as koi8-r,
176 // they are similar enough to make mapping it to koi8 better than
177 // not recognizing it at all
178 { wxT( "KOI8-R" ), wxT( "KOI8-RU" ), NULL
},
179 { wxT( "KOI8-U" ), NULL
},
181 { wxT( "WINDOWS-874" ), wxT( "CP-874" ), NULL
},
182 { wxT( "WINDOWS-932" ), wxT( "CP-932" ), NULL
},
183 { wxT( "WINDOWS-936" ), wxT( "CP-936" ), NULL
},
184 { wxT( "WINDOWS-949" ), wxT( "CP-949" ), wxT( "EUC-KR" ), wxT( "eucKR" ), wxT( "euc_kr" ), NULL
},
185 { wxT( "WINDOWS-950" ), wxT( "CP-950" ), NULL
},
186 { wxT( "WINDOWS-1250" ),wxT( "CP-1250" ), NULL
},
187 { wxT( "WINDOWS-1251" ),wxT( "CP-1251" ), NULL
},
188 { wxT( "WINDOWS-1252" ),wxT( "CP-1252" ), wxT("IBM-1252"), NULL
},
189 { wxT( "WINDOWS-1253" ),wxT( "CP-1253" ), NULL
},
190 { wxT( "WINDOWS-1254" ),wxT( "CP-1254" ), NULL
},
191 { wxT( "WINDOWS-1255" ),wxT( "CP-1255" ), NULL
},
192 { wxT( "WINDOWS-1256" ),wxT( "CP-1256" ), NULL
},
193 { wxT( "WINDOWS-1257" ),wxT( "CP-1257" ), NULL
},
194 { wxT( "WINDOWS-437" ), wxT( "CP-437" ), NULL
},
196 { wxT( "UTF-7" ), wxT("utf7"), NULL
},
197 { wxT( "UTF-8" ), wxT("utf8"), NULL
},
198 { wxT( "UTF-16" ), wxT("UCS-2"), wxT("UCS2"), NULL
},
199 { wxT( "UTF-16BE" ), wxT("UCS-2BE"), NULL
},
200 { wxT( "UTF-16LE" ), wxT("UCS-2LE"), NULL
},
201 { wxT( "UTF-32" ), wxT( "UCS-4" ), wxT("UCS4"), NULL
},
202 { wxT( "UTF-32BE" ), wxT( "UCS-4BE" ), NULL
},
203 { wxT( "UTF-32LE" ), wxT( "UCS-4LE" ), NULL
},
205 { wxT( "EUC-JP" ), wxT( "eucJP" ), wxT( "euc_jp" ), wxT( "IBM-eucJP" ), NULL
},
207 // 646 is for Solaris, roman8 -- for HP-UX
208 { wxT( "US-ASCII" ), wxT( "ASCII" ), wxT("C"), wxT("POSIX"), wxT("ANSI_X3.4-1968"),
209 wxT("646"), wxT("roman8"), wxT( "" ), NULL
},
211 { wxT( "BIG5" ), wxT("big5"), NULL
},
212 { wxT( "SJIS" ), wxT( "SHIFT-JIS" ), wxT( "SHIFT_JIS" ), NULL
},
213 { wxT( "GB2312" ), NULL
},
216 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
217 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingNames
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
219 // ----------------------------------------------------------------------------
221 // ----------------------------------------------------------------------------
223 // clean up the font mapper object
224 class wxFontMapperModule
: public wxModule
227 wxFontMapperModule() : wxModule() { }
228 virtual bool OnInit() { return true; }
229 virtual void OnExit() { delete (wxFontMapperBase
*)wxFontMapperBase::Set(NULL
); }
231 DECLARE_DYNAMIC_CLASS(wxFontMapperModule
)
234 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule
, wxModule
)
237 // ============================================================================
238 // wxFontMapperBase implementation
239 // ============================================================================
241 wxFontMapper
*wxFontMapperBase::sm_instance
= NULL
;
243 // ----------------------------------------------------------------------------
245 // ----------------------------------------------------------------------------
247 wxFontMapperBase::wxFontMapperBase()
249 #if wxUSE_CONFIG && wxUSE_FILECONFIG
251 m_configIsDummy
= false;
252 #endif // wxUSE_CONFIG
255 wxFontMapperBase::~wxFontMapperBase()
257 #if wxUSE_CONFIG && wxUSE_FILECONFIG
258 if ( m_configIsDummy
)
260 #endif // wxUSE_CONFIG
263 bool wxFontMapperBase::IsWxFontMapper()
267 wxFontMapperBase
*wxFontMapperBase::Get()
271 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
274 sm_instance
= traits
->CreateFontMapper();
276 wxASSERT_MSG( sm_instance
,
277 _T("wxAppTraits::CreateFontMapper() failed") );
282 // last resort: we must create something because the existing code
283 // relies on always having a valid font mapper object
284 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
288 return (wxFontMapperBase
*)sm_instance
;
292 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
294 wxFontMapper
*old
= sm_instance
;
295 sm_instance
= mapper
;
299 #if wxUSE_CONFIG && wxUSE_FILECONFIG
301 // ----------------------------------------------------------------------------
302 // config usage customisation
303 // ----------------------------------------------------------------------------
306 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
308 return FONTMAPPER_ROOT_PATH
;
311 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
313 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
314 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
316 m_configRootPath
= prefix
;
319 // ----------------------------------------------------------------------------
320 // get config object and path for it
321 // ----------------------------------------------------------------------------
323 wxConfigBase
*wxFontMapperBase::GetConfig()
328 m_config
= wxConfig::Get(false /*don't create on demand*/ );
332 // we still want to have a config object because otherwise we would
333 // keep asking the user the same questions in the interactive mode,
334 // so create a dummy config which won't write to any files/registry
335 // but will allow us to remember the results of the questions at
336 // least during this run
337 m_config
= new wxMemoryConfig
;
338 m_configIsDummy
= true;
339 // VS: we can't call wxConfig::Set(m_config) here because that would
340 // disable automatic wxConfig instance creation if this code was
341 // called before wxApp::OnInit (this happens in wxGTK -- it sets
342 // default wxFont encoding in wxApp::Initialize())
346 if ( m_configIsDummy
&& wxConfig::Get(false) != NULL
)
348 // VS: in case we created dummy m_config (see above), we want to switch back
349 // to the real one as soon as one becomes available.
351 m_config
= wxConfig::Get(false);
352 m_configIsDummy
= false;
353 // FIXME: ideally, we should add keys from dummy config to the real one now,
354 // but it is a low-priority task because typical wxWin application
355 // either doesn't use wxConfig at all or creates wxConfig object in
356 // wxApp::OnInit(), before any real interaction with the user takes
363 const wxString
& wxFontMapperBase::GetConfigPath()
365 if ( !m_configRootPath
)
368 m_configRootPath
= GetDefaultConfigPath();
371 return m_configRootPath
;
374 // ----------------------------------------------------------------------------
376 // ----------------------------------------------------------------------------
378 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
380 wxConfigBase
*config
= GetConfig();
384 *pathOld
= config
->GetPath();
386 wxString path
= GetConfigPath();
387 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
389 path
+= wxCONFIG_PATH_SEPARATOR
;
392 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
393 wxT("should be a relative path") );
397 config
->SetPath(path
);
402 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
404 GetConfig()->SetPath(pathOld
);
409 // ----------------------------------------------------------------------------
410 // charset/encoding correspondence
411 // ----------------------------------------------------------------------------
414 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
415 bool WXUNUSED(interactive
))
417 int enc
= NonInteractiveCharsetToEncoding(charset
);
418 if ( enc
== wxFONTENCODING_UNKNOWN
)
420 // we should return wxFONTENCODING_SYSTEM from here for unknown
422 enc
= wxFONTENCODING_SYSTEM
;
425 return (wxFontEncoding
)enc
;
429 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
431 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
433 // we're going to modify it, make a copy
434 wxString cs
= charset
;
436 #if wxUSE_CONFIG && wxUSE_FILECONFIG
437 // first try the user-defined settings
438 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
441 wxConfigBase
*config
= GetConfig();
443 // do we have an encoding for this charset?
444 long value
= config
->Read(charset
, -1l);
447 if ( value
== wxFONTENCODING_UNKNOWN
)
449 // don't try to find it, in particular don't ask the user
453 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
455 encoding
= (wxFontEncoding
)value
;
459 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
460 value
, charset
.c_str());
464 if ( encoding
== wxFONTENCODING_SYSTEM
)
466 // may be we have an alias?
467 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
469 wxString alias
= config
->Read(charset
);
470 if ( !alias
.IsEmpty() )
472 // yes, we do - use it instead
477 #endif // wxUSE_CONFIG
479 // if didn't find it there, try to recognize it ourselves
480 if ( encoding
== wxFONTENCODING_SYSTEM
)
486 // discard the optional quotes
489 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
491 cs
= wxString(cs
.c_str(), cs
.length() - 1);
495 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); ++i
)
497 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
499 if ( cs
.CmpNoCase(*encName
) == 0 )
500 return gs_encodings
[i
];
506 if ( cs
.Left(3) == wxT("ISO") )
508 // the dash is optional (or, to be exact, it is not, but
509 // several brokenmails "forget" it)
510 const wxChar
*p
= cs
.c_str() + 3;
511 if ( *p
== wxT('-') )
514 // printf( "iso %s\n", (const char*) cs.ToAscii() );
517 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
519 // printf( "value %d\n", (int)value );
521 // make it 0 based and check that it is strictly positive in
522 // the process (no such thing as iso8859-0 encoding)
523 if ( (value
-- > 0) &&
524 (value
< wxFONTENCODING_ISO8859_MAX
-
525 wxFONTENCODING_ISO8859_1
) )
527 // it's a valid ISO8859 encoding
528 value
+= wxFONTENCODING_ISO8859_1
;
529 encoding
= (wxFontEncoding
)value
;
533 else if ( cs
.Left(4) == wxT("8859") )
535 const wxChar
*p
= cs
.c_str();
538 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
540 // printf( "value %d\n", (int)value );
542 // make it 0 based and check that it is strictly positive in
543 // the process (no such thing as iso8859-0 encoding)
544 if ( (value
-- > 0) &&
545 (value
< wxFONTENCODING_ISO8859_MAX
-
546 wxFONTENCODING_ISO8859_1
) )
548 // it's a valid ISO8859 encoding
549 value
+= wxFONTENCODING_ISO8859_1
;
550 encoding
= (wxFontEncoding
)value
;
554 else // check for Windows charsets
557 if ( cs
.Left(7) == wxT("WINDOWS") )
561 else if ( cs
.Left(2) == wxT("CP") )
565 else // not a Windows encoding
572 const wxChar
*p
= cs
.c_str() + len
;
573 if ( *p
== wxT('-') )
577 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
582 if ( value
< wxFONTENCODING_CP12_MAX
-
583 wxFONTENCODING_CP1250
)
585 // a valid Windows code page
586 value
+= wxFONTENCODING_CP1250
;
587 encoding
= (wxFontEncoding
)value
;
594 encoding
= wxFONTENCODING_CP874
;
598 encoding
= wxFONTENCODING_CP932
;
602 encoding
= wxFONTENCODING_CP936
;
606 encoding
= wxFONTENCODING_CP949
;
610 encoding
= wxFONTENCODING_CP950
;
623 size_t wxFontMapperBase::GetSupportedEncodingsCount()
625 return WXSIZEOF(gs_encodings
);
629 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
631 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
632 _T("wxFontMapper::GetEncoding(): invalid index") );
634 return gs_encodings
[n
];
638 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
640 if ( encoding
== wxFONTENCODING_DEFAULT
)
642 return _("Default encoding");
645 const size_t count
= WXSIZEOF(gs_encodingDescs
);
647 for ( size_t i
= 0; i
< count
; i
++ )
649 if ( gs_encodings
[i
] == encoding
)
651 return wxGetTranslation(gs_encodingDescs
[i
]);
656 str
.Printf(_("Unknown encoding (%d)"), encoding
);
662 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
664 if ( encoding
== wxFONTENCODING_DEFAULT
)
669 const size_t count
= WXSIZEOF(gs_encodingNames
);
671 for ( size_t i
= 0; i
< count
; i
++ )
673 if ( gs_encodings
[i
] == encoding
)
675 return gs_encodingNames
[i
][0];
680 str
.Printf(_("unknown-%d"), encoding
);
686 const wxChar
** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding
)
688 static const wxChar
* dummy
[] = { NULL
};
690 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); i
++ )
692 if ( gs_encodings
[i
] == encoding
)
694 return gs_encodingNames
[i
];
702 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
704 const size_t count
= WXSIZEOF(gs_encodingNames
);
706 for ( size_t i
= 0; i
< count
; i
++ )
708 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
710 if ( name
.CmpNoCase(*encName
) == 0 )
711 return gs_encodings
[i
];
715 return wxFONTENCODING_MAX
;
718 #endif // wxUSE_FONTMAP