1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/fontmap.cpp
3 // Purpose: wxFontMapper class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "fontmap.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
37 #include "wx/fontmap.h"
38 #include "wx/config.h"
40 #include "wx/msgdlg.h"
41 #include "wx/fontdlg.h"
42 #include "wx/choicdlg.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 // the config paths we use
49 static const char* FONTMAPPER_ROOT_PATH
= _T("FontMapper");
50 static const char* FONTMAPPER_CHARSET_PATH
= _T("Charsets");
51 static const char* FONTMAPPER_CHARSET_ALIAS_PATH
= _T("Aliases");
52 static const char* FONTMAPPER_FONT_FROM_ENCODING_PATH
= _T("Encodings");
54 // encodings supported by GetEncodingDescription
55 static wxFontEncoding gs_encodings
[] =
57 wxFONTENCODING_ISO8859_1
,
58 wxFONTENCODING_ISO8859_2
,
59 wxFONTENCODING_ISO8859_3
,
60 wxFONTENCODING_ISO8859_4
,
61 wxFONTENCODING_ISO8859_5
,
62 wxFONTENCODING_ISO8859_6
,
63 wxFONTENCODING_ISO8859_7
,
64 wxFONTENCODING_ISO8859_8
,
65 wxFONTENCODING_ISO8859_9
,
66 wxFONTENCODING_ISO8859_10
,
67 wxFONTENCODING_ISO8859_11
,
68 wxFONTENCODING_ISO8859_12
,
69 wxFONTENCODING_ISO8859_13
,
70 wxFONTENCODING_ISO8859_14
,
71 wxFONTENCODING_ISO8859_15
,
73 wxFONTENCODING_CP1250
,
74 wxFONTENCODING_CP1251
,
75 wxFONTENCODING_CP1252
,
76 wxFONTENCODING_CP1253
,
77 wxFONTENCODING_CP1254
,
78 wxFONTENCODING_CP1255
,
79 wxFONTENCODING_CP1256
,
80 wxFONTENCODING_CP1257
,
83 // the descriptions for them
84 static const wxChar
* gs_encodingDescs
[] =
86 wxTRANSLATE( "West European (ISO-8859-1/Latin 1)" ),
87 wxTRANSLATE( "Central European (ISO-8859-2/Latin 2)" ),
88 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
89 wxTRANSLATE( "Baltic (ISO-8859-4)" ),
90 wxTRANSLATE( "Cyrillic (Latin 5)" ),
91 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
92 wxTRANSLATE( "Greek (ISO-8859-7)" ),
93 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
94 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
95 wxTRANSLATE( "Baltic II (ISO-8859-10)" ),
96 wxTRANSLATE( "Thai (ISO-8859-11)" ),
97 wxTRANSLATE( "ISO-8859-12" ),
98 wxTRANSLATE( "ISO-8859-13" ),
99 wxTRANSLATE( "ISO-8859-14" ),
100 wxTRANSLATE( "West European new (ISO-8859-15/Latin 0)" ),
101 wxTRANSLATE( "KOI8-R" ),
102 wxTRANSLATE( "Windows Latin 2 (CP 1250)" ),
103 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
104 wxTRANSLATE( "Windows Latin 1 (CP 1252)" ),
105 wxTRANSLATE( "Windows Greek (CP 1253)" ),
106 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
107 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
108 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
109 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
112 // and the internal names
113 static const wxChar
* gs_encodingNames
[] =
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
146 static wxFontMapper gs_fontMapper
;
148 // and public pointer
149 wxFontMapper
* WXDLLEXPORT wxTheFontMapper
= &gs_fontMapper
;
151 // ----------------------------------------------------------------------------
153 // ----------------------------------------------------------------------------
155 // change the config path during the lifetime of this object
156 class wxFontMapperPathChanger
159 wxFontMapperPathChanger(wxFontMapper
*fontMapper
, const wxString
& path
)
161 m_fontMapper
= fontMapper
;
162 m_ok
= m_fontMapper
->ChangePath(path
, &m_pathOld
);
165 bool IsOk() const { return m_ok
; }
167 ~wxFontMapperPathChanger()
170 m_fontMapper
->RestorePath(m_pathOld
);
174 wxFontMapper
*m_fontMapper
;
179 // ============================================================================
181 // ============================================================================
183 // ----------------------------------------------------------------------------
185 // ----------------------------------------------------------------------------
187 wxFontMapper::wxFontMapper()
190 m_windowParent
= NULL
;
193 wxFontMapper::~wxFontMapper()
197 // ----------------------------------------------------------------------------
199 // ----------------------------------------------------------------------------
201 /* static */ const wxChar
*wxFontMapper::GetDefaultConfigPath()
203 return FONTMAPPER_ROOT_PATH
;
206 void wxFontMapper::SetConfigPath(const wxString
& prefix
)
208 wxCHECK_RET( !prefix
.IsEmpty() && prefix
[0] == wxCONFIG_PATH_SEPARATOR
,
209 _T("an absolute path should be given to "
210 "wxFontMapper::SetConfigPath()") );
212 m_configRootPath
= prefix
;
216 // ----------------------------------------------------------------------------
217 // get config object and path for it
218 // ----------------------------------------------------------------------------
220 wxConfigBase
*wxFontMapper::GetConfig()
225 m_config
= wxConfig::Get();
231 const wxString
& wxFontMapper::GetConfigPath()
233 if ( !m_configRootPath
)
236 m_configRootPath
= GetDefaultConfigPath();
239 return m_configRootPath
;
242 bool wxFontMapper::ChangePath(const wxString
& pathNew
, wxString
*pathOld
)
244 wxConfigBase
*config
= GetConfig();
248 *pathOld
= config
->GetPath();
250 wxString path
= GetConfigPath();
251 if ( path
.IsEmpty() || path
.Last() != wxCONFIG_PATH_SEPARATOR
)
253 path
+= wxCONFIG_PATH_SEPARATOR
;
256 wxASSERT_MSG( !pathNew
|| (pathNew
[0] != wxCONFIG_PATH_SEPARATOR
),
257 _T("should be a relative path") );
261 config
->SetPath(path
);
266 void wxFontMapper::RestorePath(const wxString
& pathOld
)
268 GetConfig()->SetPath(pathOld
);
271 // ----------------------------------------------------------------------------
272 // charset/encoding correspondence
273 // ----------------------------------------------------------------------------
276 wxString
wxFontMapper::GetEncodingDescription(wxFontEncoding encoding
)
278 size_t count
= WXSIZEOF(gs_encodingDescs
);
280 wxASSERT_MSG( count
== WXSIZEOF(gs_encodings
),
281 _T("inconsitency detected - forgot to update one of "
284 for ( size_t i
= 0; i
< count
; i
++ )
286 if ( gs_encodings
[i
] == encoding
)
288 return wxGetTranslation(gs_encodingDescs
[i
]);
293 str
.Printf(_("Unknown encoding (%d)"), encoding
);
299 wxString
wxFontMapper::GetEncodingName(wxFontEncoding encoding
)
301 size_t count
= WXSIZEOF(gs_encodingNames
);
303 wxASSERT_MSG( count
== WXSIZEOF(gs_encodings
),
304 _T("inconsitency detected - forgot to update one of "
307 for ( size_t i
= 0; i
< count
; i
++ )
309 if ( gs_encodings
[i
] == encoding
)
311 return wxGetTranslation(gs_encodingNames
[i
]);
316 str
.Printf(_("unknown-%d"), encoding
);
321 wxFontEncoding
wxFontMapper::CharsetToEncoding(const wxString
& charset
,
324 wxFontEncoding encoding
= wxFONTENCODING_SYSTEM
;
326 // we're going to modify it, make a copy
327 wxString cs
= charset
;
329 // first try the user-defined settings
331 if ( ChangePath(FONTMAPPER_CHARSET_PATH
, &pathOld
) )
333 wxConfigBase
*config
= GetConfig();
335 // do we have an encoding for this charset?
336 long value
= config
->Read(charset
, -1l);
339 if ( value
>= 0 && value
<= wxFONTENCODING_MAX
)
341 encoding
= (wxFontEncoding
)value
;
345 wxLogDebug(_T("corrupted config data - invalid encoding %ld "
346 "for charset '%s'"), value
, charset
.c_str());
350 if ( encoding
== wxFONTENCODING_SYSTEM
)
352 // may be we have an alias?
353 config
->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH
);
355 wxString alias
= config
->Read(charset
);
358 // yes, we do - use it instead
363 RestorePath(pathOld
);
366 // if didn't find it there, try to reckognise it ourselves
367 if ( encoding
== wxFONTENCODING_SYSTEM
)
371 if ( !cs
|| cs
== _T("US-ASCII") )
372 encoding
= wxFONTENCODING_DEFAULT
;
373 else if ( cs
== _T("KOI8-R") || cs
== _T("KOI8-U") )
374 encoding
= wxFONTENCODING_KOI8
;
375 else if ( cs
.Left(3) == _T("ISO") )
377 // the dash is optional (or, to be exact, it is not, but
378 // several brokenmails "forget" it)
379 const wxChar
*p
= cs
.c_str() + 3;
384 if ( wxSscanf(p
, _T("8859-%u"), &value
) == 1 )
386 if ( value
< wxFONTENCODING_ISO8859_MAX
-
387 wxFONTENCODING_ISO8859_1
)
389 // it's a valid ISO8859 encoding
390 value
+= wxFONTENCODING_ISO8859_1
- 1;
391 encoding
= (wxFontEncoding
)value
;
395 else if ( cs
.Left(8) == _T("WINDOWS-") )
398 if ( wxSscanf(cs
.c_str() + 8, "%u", &value
) == 1 )
403 if ( value
< wxFONTENCODING_CP12_MAX
-
404 wxFONTENCODING_CP1250
- 1 )
406 // a valid Windows code page
407 value
+= wxFONTENCODING_CP1250
;
408 encoding
= (wxFontEncoding
)value
;
416 // if still no luck, ask the user - unless disabled
417 if ( (encoding
== wxFONTENCODING_SYSTEM
) && interactive
)
419 // prepare the dialog data
422 wxString
title(m_titleDialog
);
424 title
<< wxTheApp
->GetAppName() << _(": unknown charset");
428 msg
.Printf(_("The charset '%s' is unknown. You may select another "
429 "charset to replace it with or choose [Cancel] if it "
430 "cannot be replaced"), charset
.c_str());
432 // the list of choices
433 size_t count
= WXSIZEOF(gs_encodingDescs
);
435 wxASSERT_MSG( count
== WXSIZEOF(gs_encodings
),
436 _T("inconsitency detected - forgot to update one of "
439 wxString
*encodingNamesTranslated
= new wxString
[count
];
441 for ( size_t i
= 0; i
< count
; i
++ )
443 encodingNamesTranslated
[i
] = wxGetTranslation(gs_encodingDescs
[i
]);
447 wxWindow
*parent
= m_windowParent
;
449 parent
= wxTheApp
->GetTopWindow();
451 // do ask the user and get back the index in encodings table
452 int n
= wxGetSingleChoiceIndex(msg
, title
,
454 encodingNamesTranslated
,
457 delete [] encodingNamesTranslated
;
461 // TODO save the result in the config!
463 encoding
= gs_encodings
[n
];
471 // ----------------------------------------------------------------------------
472 // support for unknown encodings: we maintain a map between the
473 // (platform-specific) strings identifying them and our wxFontEncodings they
474 // correspond to which is used by GetFontForEncoding() function
475 // ----------------------------------------------------------------------------
477 bool wxFontMapper::TestAltEncoding(const wxString
& configEntry
,
478 wxFontEncoding encReplacement
,
479 wxNativeEncodingInfo
*info
)
481 if ( wxGetNativeFontEncoding(encReplacement
, info
) &&
482 wxTestFontEncoding(*info
) )
484 // remember the mapping in the config
485 wxFontMapperPathChanger
path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH
);
489 GetConfig()->Write(configEntry
, info
->ToString());
498 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding
,
499 wxNativeEncodingInfo
*info
,
502 wxCHECK_MSG( info
, FALSE
, _T("bad pointer in GetAltForEncoding") );
504 wxString configEntry
= GetEncodingName(encoding
);
506 // do we have a font spec for this encoding?
508 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH
, &pathOld
) )
510 wxConfigBase
*config
= GetConfig();
512 wxString fontinfo
= config
->Read(configEntry
);
514 RestorePath(pathOld
);
518 if ( info
->FromString(fontinfo
) )
520 if ( wxTestFontEncoding(*info
) )
525 //else: no such fonts, look for something else
529 wxLogDebug(_T("corrupted config data: string '%s' is not "
530 "a valid font encoding info"), fontinfo
.c_str());
538 wxString
title(m_titleDialog
);
540 title
<< wxTheApp
->GetAppName() << _(": unknown encoding");
544 msg
.Printf(_("The encoding '%s' is unknown.\n"
545 "Would you like to select a font to be used for this "
547 "(otherwise the text in this encoding will not be "
548 "shown correctly)?"),
549 GetEncodingDescription(encoding
).c_str());
551 wxWindow
*parent
= m_windowParent
;
553 parent
= wxTheApp
->GetTopWindow();
555 if ( wxMessageBox(msg
, title
,
556 wxICON_QUESTION
| wxYES_NO
, parent
) == wxYES
)
559 data
.SetEncoding(encoding
);
560 data
.EncodingInfo() = *info
;
561 wxFontDialog
dialog(parent
, &data
);
562 if ( dialog
.ShowModal() == wxID_OK
)
564 wxFontData retData
= dialog
.GetFontData();
565 wxFont font
= retData
.GetChosenFont();
567 *info
= retData
.EncodingInfo();
569 // remember this in the config
570 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH
, &pathOld
) )
572 GetConfig()->Write(configEntry
, info
->ToString());
574 RestorePath(pathOld
);
579 //else: the user canceled the font selection dialog
581 //else: the user doesn't want to select a font
583 //else: we're in non-interactive mode
585 // now try the default mappings
588 case wxFONTENCODING_ISO8859_15
:
589 // iso8859-15 is slightly modified iso8859-1
590 if ( TestAltEncoding(configEntry
, wxFONTENCODING_ISO8859_1
, info
) )
594 case wxFONTENCODING_ISO8859_1
:
595 // iso8859-1 is identical to CP1252
596 if ( TestAltEncoding(configEntry
, wxFONTENCODING_CP1252
, info
) )
601 case wxFONTENCODING_CP1252
:
602 if ( TestAltEncoding(configEntry
, wxFONTENCODING_ISO8859_1
, info
) )
607 // iso8859-13 is quite similar to WinBaltic
608 case wxFONTENCODING_ISO8859_13
:
609 if ( TestAltEncoding(configEntry
, wxFONTENCODING_CP1257
, info
) )
614 case wxFONTENCODING_CP1257
:
615 if ( TestAltEncoding(configEntry
, wxFONTENCODING_ISO8859_13
, info
) )
620 // iso8859-8 is almost identical to WinHebrew
621 case wxFONTENCODING_ISO8859_8
:
622 if ( TestAltEncoding(configEntry
, wxFONTENCODING_CP1255
, info
) )
627 case wxFONTENCODING_CP1255
:
628 if ( TestAltEncoding(configEntry
, wxFONTENCODING_ISO8859_8
, info
) )
633 // and iso8859-7 is not too different from WinGreek
634 case wxFONTENCODING_ISO8859_7
:
635 if ( TestAltEncoding(configEntry
, wxFONTENCODING_CP1253
, info
) )
640 case wxFONTENCODING_CP1253
:
641 if ( TestAltEncoding(configEntry
, wxFONTENCODING_ISO8859_7
, info
) )
647 // TODO add other mappings...