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
250 m_configDummy
= NULL
;
251 #endif // wxUSE_CONFIG
254 wxFontMapperBase::~wxFontMapperBase()
256 #if wxUSE_CONFIG && wxUSE_FILECONFIG
258 delete m_configDummy
;
259 #endif // wxUSE_CONFIG
262 bool wxFontMapperBase::IsWxFontMapper()
266 wxFontMapperBase
*wxFontMapperBase::Get()
270 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
273 sm_instance
= traits
->CreateFontMapper();
275 wxASSERT_MSG( sm_instance
,
276 _T("wxAppTraits::CreateFontMapper() failed") );
281 // last resort: we must create something because the existing code
282 // relies on always having a valid font mapper object
283 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
287 return (wxFontMapperBase
*)sm_instance
;
291 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
293 wxFontMapper
*old
= sm_instance
;
294 sm_instance
= mapper
;
298 #if wxUSE_CONFIG && wxUSE_FILECONFIG
300 // ----------------------------------------------------------------------------
301 // config usage customisation
302 // ----------------------------------------------------------------------------
305 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
307 return FONTMAPPER_ROOT_PATH
;
310 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
312 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
313 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
315 m_configRootPath
= prefix
;
318 // ----------------------------------------------------------------------------
319 // get config object and path for it
320 // ----------------------------------------------------------------------------
322 wxConfigBase
*wxFontMapperBase::GetConfig()
324 wxConfigBase
*config
= wxConfig::Get(false);
326 // If there is no global configuration, use an internal memory configuration
329 if ( !m_configDummy
)
330 m_configDummy
= new wxMemoryConfig
;
331 config
= m_configDummy
;
333 // FIXME: ideally, we should add keys from dummy config to a real one later,
334 // but it is a low-priority task because typical wxWin application
335 // either doesn't use wxConfig at all or creates wxConfig object in
336 // wxApp::OnInit(), before any real interaction with the user takes
343 const wxString
& wxFontMapperBase::GetConfigPath()
345 if ( !m_configRootPath
)
348 m_configRootPath
= GetDefaultConfigPath();
351 return m_configRootPath
;
354 // ----------------------------------------------------------------------------
356 // ----------------------------------------------------------------------------
358 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
360 wxConfigBase
*config
= GetConfig();
364 *pathOld
= config
->GetPath();
366 wxString path
= GetConfigPath();
367 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
369 path
+= wxCONFIG_PATH_SEPARATOR
;
372 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
373 wxT("should be a relative path") );
377 config
->SetPath(path
);
382 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
384 GetConfig()->SetPath(pathOld
);
389 // ----------------------------------------------------------------------------
390 // charset/encoding correspondence
391 // ----------------------------------------------------------------------------
394 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
395 bool WXUNUSED(interactive
))
397 int enc
= NonInteractiveCharsetToEncoding(charset
);
398 if ( enc
== wxFONTENCODING_UNKNOWN
)
400 // we should return wxFONTENCODING_SYSTEM from here for unknown
402 enc
= wxFONTENCODING_SYSTEM
;
405 return (wxFontEncoding
)enc
;
409 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
411 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
413 // we're going to modify it, make a copy
414 wxString cs
= charset
;
416 #if wxUSE_CONFIG && wxUSE_FILECONFIG
417 // first try the user-defined settings
418 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
421 wxConfigBase
*config
= GetConfig();
423 // do we have an encoding for this charset?
424 long value
= config
->Read(charset
, -1l);
427 if ( value
== wxFONTENCODING_UNKNOWN
)
429 // don't try to find it, in particular don't ask the user
433 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
435 encoding
= (wxFontEncoding
)value
;
439 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
440 value
, charset
.c_str());
444 if ( encoding
== wxFONTENCODING_SYSTEM
)
446 // may be we have an alias?
447 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
449 wxString alias
= config
->Read(charset
);
450 if ( !alias
.IsEmpty() )
452 // yes, we do - use it instead
457 #endif // wxUSE_CONFIG
459 // if didn't find it there, try to recognize it ourselves
460 if ( encoding
== wxFONTENCODING_SYSTEM
)
466 // discard the optional quotes
469 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
471 cs
= wxString(cs
.c_str(), cs
.length() - 1);
475 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); ++i
)
477 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
479 if ( cs
.CmpNoCase(*encName
) == 0 )
480 return gs_encodings
[i
];
486 if ( cs
.Left(3) == wxT("ISO") )
488 // the dash is optional (or, to be exact, it is not, but
489 // several brokenmails "forget" it)
490 const wxChar
*p
= cs
.c_str() + 3;
491 if ( *p
== wxT('-') )
494 // printf( "iso %s\n", (const char*) cs.ToAscii() );
497 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
499 // printf( "value %d\n", (int)value );
501 // make it 0 based and check that it is strictly positive in
502 // the process (no such thing as iso8859-0 encoding)
503 if ( (value
-- > 0) &&
504 (value
< wxFONTENCODING_ISO8859_MAX
-
505 wxFONTENCODING_ISO8859_1
) )
507 // it's a valid ISO8859 encoding
508 value
+= wxFONTENCODING_ISO8859_1
;
509 encoding
= (wxFontEncoding
)value
;
513 else if ( cs
.Left(4) == wxT("8859") )
515 const wxChar
*p
= cs
.c_str();
518 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
520 // printf( "value %d\n", (int)value );
522 // make it 0 based and check that it is strictly positive in
523 // the process (no such thing as iso8859-0 encoding)
524 if ( (value
-- > 0) &&
525 (value
< wxFONTENCODING_ISO8859_MAX
-
526 wxFONTENCODING_ISO8859_1
) )
528 // it's a valid ISO8859 encoding
529 value
+= wxFONTENCODING_ISO8859_1
;
530 encoding
= (wxFontEncoding
)value
;
534 else // check for Windows charsets
537 if ( cs
.Left(7) == wxT("WINDOWS") )
541 else if ( cs
.Left(2) == wxT("CP") )
545 else // not a Windows encoding
552 const wxChar
*p
= cs
.c_str() + len
;
553 if ( *p
== wxT('-') )
557 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
562 if ( value
< wxFONTENCODING_CP12_MAX
-
563 wxFONTENCODING_CP1250
)
565 // a valid Windows code page
566 value
+= wxFONTENCODING_CP1250
;
567 encoding
= (wxFontEncoding
)value
;
574 encoding
= wxFONTENCODING_CP874
;
578 encoding
= wxFONTENCODING_CP932
;
582 encoding
= wxFONTENCODING_CP936
;
586 encoding
= wxFONTENCODING_CP949
;
590 encoding
= wxFONTENCODING_CP950
;
603 size_t wxFontMapperBase::GetSupportedEncodingsCount()
605 return WXSIZEOF(gs_encodings
);
609 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
611 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
612 _T("wxFontMapper::GetEncoding(): invalid index") );
614 return gs_encodings
[n
];
618 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
620 if ( encoding
== wxFONTENCODING_DEFAULT
)
622 return _("Default encoding");
625 const size_t count
= WXSIZEOF(gs_encodingDescs
);
627 for ( size_t i
= 0; i
< count
; i
++ )
629 if ( gs_encodings
[i
] == encoding
)
631 return wxGetTranslation(gs_encodingDescs
[i
]);
636 str
.Printf(_("Unknown encoding (%d)"), encoding
);
642 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
644 if ( encoding
== wxFONTENCODING_DEFAULT
)
649 const size_t count
= WXSIZEOF(gs_encodingNames
);
651 for ( size_t i
= 0; i
< count
; i
++ )
653 if ( gs_encodings
[i
] == encoding
)
655 return gs_encodingNames
[i
][0];
660 str
.Printf(_("unknown-%d"), encoding
);
666 const wxChar
** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding
)
668 static const wxChar
* dummy
[] = { NULL
};
670 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); i
++ )
672 if ( gs_encodings
[i
] == encoding
)
674 return gs_encodingNames
[i
];
682 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
684 const size_t count
= WXSIZEOF(gs_encodingNames
);
686 for ( size_t i
= 0; i
< count
; i
++ )
688 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
690 if ( name
.CmpNoCase(*encName
) == 0 )
691 return gs_encodings
[i
];
695 return wxFONTENCODING_MAX
;
698 #endif // wxUSE_FONTMAP