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
)][7] =
157 { wxT( "iso-8859-1" ), NULL
},
158 { wxT( "iso-8859-2" ), NULL
},
159 { wxT( "iso-8859-3" ), NULL
},
160 { wxT( "iso-8859-4" ), NULL
},
161 { wxT( "iso-8859-5" ), NULL
},
162 { wxT( "iso-8859-6" ), NULL
},
163 { wxT( "iso-8859-7" ), NULL
},
164 { wxT( "iso-8859-8" ), NULL
},
165 { wxT( "iso-8859-9" ), NULL
},
166 { wxT( "iso-8859-10" ), NULL
},
167 { wxT( "iso-8859-11" ), NULL
},
168 { wxT( "iso-8859-12" ), NULL
},
169 { wxT( "iso-8859-13" ), NULL
},
170 { wxT( "iso-8859-14" ), NULL
},
171 { wxT( "iso-8859-15" ), NULL
},
172 // although koi8-ru is not strictly speaking the same as koi8-r,
173 // they are similar enough to make mapping it to koi8 better than
174 // not recognizing it at all
175 { wxT( "koi8-r" ), wxT( "koi8-ru" ), NULL
},
176 { wxT( "koi8-u" ), NULL
},
177 { wxT( "windows-874" ), NULL
},
178 { wxT( "windows-932" ), NULL
},
179 { wxT( "windows-936" ), NULL
},
180 { wxT( "windows-949" ), wxT( "euc-kr" ),
181 wxT( "euckr" ), wxT( "euc_kr" ), NULL
},
182 { wxT( "windows-950" ), NULL
},
183 { wxT( "windows-1250" ), NULL
},
184 { wxT( "windows-1251" ), NULL
},
185 { wxT( "windows-1252" ), NULL
},
186 { wxT( "windows-1253" ), NULL
},
187 { wxT( "windows-1254" ), NULL
},
188 { wxT( "windows-1255" ), NULL
},
189 { wxT( "windows-1256" ), NULL
},
190 { wxT( "windows-1257" ), NULL
},
191 { wxT( "windows-437" ), NULL
},
192 { wxT( "UTF-7" ), NULL
},
193 { wxT( "UTF-8" ), NULL
},
194 { wxT( "UTF-16" ), NULL
},
195 { wxT( "UTF-16be" ), NULL
},
196 { wxT( "UTF-16le" ), NULL
},
197 { wxT( "UTF-32" ), wxT( "UCS-4" ), NULL
},
198 { wxT( "UTF-32be" ), wxT( "UCS-4be" ), NULL
},
199 { wxT( "UTF-32le" ), wxT( "UCS-4le" ), NULL
},
200 { wxT( "euc-jp" ), wxT( "eucJP" ), wxT( "euc_jp" ), wxT( "IBM-eucJP" ), NULL
},
201 { wxT( "us-ascii" ), wxT( "ascii" ), wxT("ANSI_X3.4-1968"),
209 { wxT( "big5" ), NULL
},
210 { wxT( "shift-jis" ), wxT( "shift_jis" ), wxT( "sjis" ), NULL
},
211 { wxT( "gb2312" ), NULL
},
214 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
215 wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingNames
) == WXSIZEOF(gs_encodings
), EncodingsArraysNotInSync
);
217 // ----------------------------------------------------------------------------
219 // ----------------------------------------------------------------------------
221 // clean up the font mapper object
222 class wxFontMapperModule
: public wxModule
225 wxFontMapperModule() : wxModule() { }
226 virtual bool OnInit() { return true; }
227 virtual void OnExit() { delete (wxFontMapperBase
*)wxFontMapperBase::Set(NULL
); }
229 DECLARE_DYNAMIC_CLASS(wxFontMapperModule
)
232 IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule
, wxModule
)
235 // ============================================================================
236 // wxFontMapperBase implementation
237 // ============================================================================
239 wxFontMapper
*wxFontMapperBase::sm_instance
= NULL
;
241 // ----------------------------------------------------------------------------
243 // ----------------------------------------------------------------------------
245 wxFontMapperBase::wxFontMapperBase()
247 #if wxUSE_CONFIG && wxUSE_FILECONFIG
249 m_configIsDummy
= false;
250 #endif // wxUSE_CONFIG
253 wxFontMapperBase::~wxFontMapperBase()
255 #if wxUSE_CONFIG && wxUSE_FILECONFIG
256 if ( m_configIsDummy
)
258 #endif // wxUSE_CONFIG
261 bool wxFontMapperBase::IsWxFontMapper()
265 wxFontMapperBase
*wxFontMapperBase::Get()
269 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
272 sm_instance
= traits
->CreateFontMapper();
274 wxASSERT_MSG( sm_instance
,
275 _T("wxAppTraits::CreateFontMapper() failed") );
280 // last resort: we must create something because the existing code
281 // relies on always having a valid font mapper object
282 sm_instance
= (wxFontMapper
*)new wxFontMapperBase
;
286 return (wxFontMapperBase
*)sm_instance
;
290 wxFontMapper
*wxFontMapperBase::Set(wxFontMapper
*mapper
)
292 wxFontMapper
*old
= sm_instance
;
293 sm_instance
= mapper
;
297 #if wxUSE_CONFIG && wxUSE_FILECONFIG
299 // ----------------------------------------------------------------------------
300 // config usage customisation
301 // ----------------------------------------------------------------------------
304 const wxChar
*wxFontMapperBase::GetDefaultConfigPath()
306 return FONTMAPPER_ROOT_PATH
;
309 void wxFontMapperBase::SetConfigPath(const wxString
& prefix
)
311 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
312 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
314 m_configRootPath
= prefix
;
317 // ----------------------------------------------------------------------------
318 // get config object and path for it
319 // ----------------------------------------------------------------------------
321 wxConfigBase
*wxFontMapperBase::GetConfig()
326 m_config
= wxConfig::Get(false /*don't create on demand*/ );
330 // we still want to have a config object because otherwise we would
331 // keep asking the user the same questions in the interactive mode,
332 // so create a dummy config which won't write to any files/registry
333 // but will allow us to remember the results of the questions at
334 // least during this run
335 m_config
= new wxMemoryConfig
;
336 m_configIsDummy
= true;
337 // VS: we can't call wxConfig::Set(m_config) here because that would
338 // disable automatic wxConfig instance creation if this code was
339 // called before wxApp::OnInit (this happens in wxGTK -- it sets
340 // default wxFont encoding in wxApp::Initialize())
344 if ( m_configIsDummy
&& wxConfig::Get(false) != NULL
)
346 // VS: in case we created dummy m_config (see above), we want to switch back
347 // to the real one as soon as one becomes available.
349 m_config
= wxConfig::Get(false);
350 m_configIsDummy
= false;
351 // FIXME: ideally, we should add keys from dummy config to the real one now,
352 // but it is a low-priority task because typical wxWin application
353 // either doesn't use wxConfig at all or creates wxConfig object in
354 // wxApp::OnInit(), before any real interaction with the user takes
361 const wxString
& wxFontMapperBase::GetConfigPath()
363 if ( !m_configRootPath
)
366 m_configRootPath
= GetDefaultConfigPath();
369 return m_configRootPath
;
372 // ----------------------------------------------------------------------------
374 // ----------------------------------------------------------------------------
376 bool wxFontMapperBase::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
378 wxConfigBase
*config
= GetConfig();
382 *pathOld
= config
->GetPath();
384 wxString path
= GetConfigPath();
385 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
387 path
+= wxCONFIG_PATH_SEPARATOR
;
390 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
391 wxT("should be a relative path") );
395 config
->SetPath(path
);
400 void wxFontMapperBase::RestorePath(const wxString
& pathOld
)
402 GetConfig()->SetPath(pathOld
);
407 // ----------------------------------------------------------------------------
408 // charset/encoding correspondence
409 // ----------------------------------------------------------------------------
412 wxFontMapperBase::CharsetToEncoding(const wxString
& charset
,
413 bool WXUNUSED(interactive
))
415 int enc
= NonInteractiveCharsetToEncoding(charset
);
416 if ( enc
== wxFONTENCODING_UNKNOWN
)
418 // we should return wxFONTENCODING_SYSTEM from here for unknown
420 enc
= wxFONTENCODING_SYSTEM
;
423 return (wxFontEncoding
)enc
;
427 wxFontMapperBase::NonInteractiveCharsetToEncoding(const wxString
& charset
)
429 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
431 // we're going to modify it, make a copy
432 wxString cs
= charset
;
434 #if wxUSE_CONFIG && wxUSE_FILECONFIG
435 // first try the user-defined settings
436 wxFontMapperPathChanger
path(this, FONTMAPPER_CHARSET_PATH
);
439 wxConfigBase
*config
= GetConfig();
441 // do we have an encoding for this charset?
442 long value
= config
->Read(charset
, -1l);
445 if ( value
== wxFONTENCODING_UNKNOWN
)
447 // don't try to find it, in particular don't ask the user
451 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
453 encoding
= (wxFontEncoding
)value
;
457 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
458 value
, charset
.c_str());
462 if ( encoding
== wxFONTENCODING_SYSTEM
)
464 // may be we have an alias?
465 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
467 wxString alias
= config
->Read(charset
);
468 if ( !alias
.IsEmpty() )
470 // yes, we do - use it instead
475 #endif // wxUSE_CONFIG
477 // if didn't find it there, try to recognize it ourselves
478 if ( encoding
== wxFONTENCODING_SYSTEM
)
484 // discard the optional quotes
487 if ( cs
[0u] == _T('"') && cs
.Last() == _T('"') )
489 cs
= wxString(cs
.c_str(), cs
.length() - 1);
493 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); ++i
)
495 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
497 if ( cs
.CmpNoCase(*encName
) == 0 )
498 return gs_encodings
[i
];
504 if ( cs
.Left(3) == wxT("ISO") )
506 // the dash is optional (or, to be exact, it is not, but
507 // several brokenmails "forget" it)
508 const wxChar
*p
= cs
.c_str() + 3;
509 if ( *p
== wxT('-') )
512 // printf( "iso %s\n", (const char*) cs.ToAscii() );
515 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
517 // printf( "value %d\n", (int)value );
519 // make it 0 based and check that it is strictly positive in
520 // the process (no such thing as iso8859-0 encoding)
521 if ( (value
-- > 0) &&
522 (value
< wxFONTENCODING_ISO8859_MAX
-
523 wxFONTENCODING_ISO8859_1
) )
525 // it's a valid ISO8859 encoding
526 value
+= wxFONTENCODING_ISO8859_1
;
527 encoding
= (wxFontEncoding
)value
;
531 else if ( cs
.Left(4) == wxT("8859") )
533 const wxChar
*p
= cs
.c_str();
536 if ( wxSscanf(p
, wxT("8859-%u"), &value
) == 1 )
538 // printf( "value %d\n", (int)value );
540 // make it 0 based and check that it is strictly positive in
541 // the process (no such thing as iso8859-0 encoding)
542 if ( (value
-- > 0) &&
543 (value
< wxFONTENCODING_ISO8859_MAX
-
544 wxFONTENCODING_ISO8859_1
) )
546 // it's a valid ISO8859 encoding
547 value
+= wxFONTENCODING_ISO8859_1
;
548 encoding
= (wxFontEncoding
)value
;
552 else // check for Windows charsets
555 if ( cs
.Left(7) == wxT("WINDOWS") )
559 else if ( cs
.Left(2) == wxT("CP") )
563 else // not a Windows encoding
570 const wxChar
*p
= cs
.c_str() + len
;
571 if ( *p
== wxT('-') )
575 if ( wxSscanf(p
, wxT("%u"), &value
) == 1 )
580 if ( value
< wxFONTENCODING_CP12_MAX
-
581 wxFONTENCODING_CP1250
)
583 // a valid Windows code page
584 value
+= wxFONTENCODING_CP1250
;
585 encoding
= (wxFontEncoding
)value
;
592 encoding
= wxFONTENCODING_CP874
;
596 encoding
= wxFONTENCODING_CP932
;
600 encoding
= wxFONTENCODING_CP936
;
604 encoding
= wxFONTENCODING_CP949
;
608 encoding
= wxFONTENCODING_CP950
;
621 size_t wxFontMapperBase::GetSupportedEncodingsCount()
623 return WXSIZEOF(gs_encodings
);
627 wxFontEncoding
wxFontMapperBase::GetEncoding(size_t n
)
629 wxCHECK_MSG( n
< WXSIZEOF(gs_encodings
), wxFONTENCODING_SYSTEM
,
630 _T("wxFontMapper::GetEncoding(): invalid index") );
632 return gs_encodings
[n
];
636 wxString
wxFontMapperBase::GetEncodingDescription(wxFontEncoding encoding
)
638 if ( encoding
== wxFONTENCODING_DEFAULT
)
640 return _("Default encoding");
643 const size_t count
= WXSIZEOF(gs_encodingDescs
);
645 for ( size_t i
= 0; i
< count
; i
++ )
647 if ( gs_encodings
[i
] == encoding
)
649 return wxGetTranslation(gs_encodingDescs
[i
]);
654 str
.Printf(_("Unknown encoding (%d)"), encoding
);
660 wxString
wxFontMapperBase::GetEncodingName(wxFontEncoding encoding
)
662 if ( encoding
== wxFONTENCODING_DEFAULT
)
667 const size_t count
= WXSIZEOF(gs_encodingNames
);
669 for ( size_t i
= 0; i
< count
; i
++ )
671 if ( gs_encodings
[i
] == encoding
)
673 return gs_encodingNames
[i
][0];
678 str
.Printf(_("unknown-%d"), encoding
);
684 const wxChar
** wxFontMapperBase::GetAllEncodingNames(wxFontEncoding encoding
)
686 static const wxChar
* dummy
[] = { NULL
};
688 for ( size_t i
= 0; i
< WXSIZEOF(gs_encodingNames
); i
++ )
690 if ( gs_encodings
[i
] == encoding
)
692 return gs_encodingNames
[i
];
700 wxFontEncoding
wxFontMapperBase::GetEncodingFromName(const wxString
& name
)
702 const size_t count
= WXSIZEOF(gs_encodingNames
);
704 for ( size_t i
= 0; i
< count
; i
++ )
706 for ( const wxChar
** encName
= gs_encodingNames
[i
]; *encName
; ++encName
)
708 if ( name
.CmpNoCase(*encName
) == 0 )
709 return gs_encodings
[i
];
713 if ( name
== _("default") )
715 return wxFONTENCODING_DEFAULT
;
718 return wxFONTENCODING_MAX
;
721 #endif // wxUSE_FONTMAP