]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
modifications to URL<->filename conversion: take wxFileName, rename
[wxWidgets.git] / src / common / fontmap.cpp
CommitLineData
3c1866e8
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: common/fontmap.cpp
3// Purpose: wxFontMapper class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 04.11.99
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "fontmap.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
1e6feb95
VZ
31#if wxUSE_FONTMAP
32
3c1866e8
VZ
33#ifndef WX_PRECOMP
34 #include "wx/app.h"
35 #include "wx/log.h"
36 #include "wx/intl.h"
37#endif // PCH
38
65e50848 39#include "wx/module.h"
3c1866e8 40#include "wx/fontmap.h"
7beba2fc 41
f6bcfd97
BP
42#if wxUSE_CONFIG
43 #include "wx/config.h"
44 #include "wx/memconf.h"
45#endif
46
47#if wxUSE_GUI
70184095 48 #include "wx/fontutil.h"
f6bcfd97
BP
49 #include "wx/msgdlg.h"
50 #include "wx/fontdlg.h"
51 #include "wx/choicdlg.h"
52#endif // wxUSE_GUI
53
82545b58 54#include "wx/encconv.h"
3c1866e8
VZ
55
56// ----------------------------------------------------------------------------
57// constants
58// ----------------------------------------------------------------------------
59
60// the config paths we use
1e6feb95 61#if wxUSE_CONFIG
3ca6a5f0 62static const wxChar* FONTMAPPER_ROOT_PATH = wxT("/wxWindows/FontMapper");
511f273f
OK
63static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
64static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
6603907d
VZ
65
66// we only ask questions in GUI mode
f6bcfd97
BP
67#if wxUSE_GUI
68 static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
6603907d 69 static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none");
f6bcfd97 70#endif // wxUSE_GUI
1e6feb95 71#endif // wxUSE_CONFIG
7beba2fc
VZ
72
73// encodings supported by GetEncodingDescription
74static wxFontEncoding gs_encodings[] =
75{
76 wxFONTENCODING_ISO8859_1,
77 wxFONTENCODING_ISO8859_2,
78 wxFONTENCODING_ISO8859_3,
79 wxFONTENCODING_ISO8859_4,
80 wxFONTENCODING_ISO8859_5,
81 wxFONTENCODING_ISO8859_6,
82 wxFONTENCODING_ISO8859_7,
83 wxFONTENCODING_ISO8859_8,
84 wxFONTENCODING_ISO8859_9,
85 wxFONTENCODING_ISO8859_10,
86 wxFONTENCODING_ISO8859_11,
87 wxFONTENCODING_ISO8859_12,
88 wxFONTENCODING_ISO8859_13,
89 wxFONTENCODING_ISO8859_14,
90 wxFONTENCODING_ISO8859_15,
91 wxFONTENCODING_KOI8,
bc4e6fcd
VZ
92 wxFONTENCODING_CP932,
93 wxFONTENCODING_CP936,
94 wxFONTENCODING_CP949,
95 wxFONTENCODING_CP950,
7beba2fc
VZ
96 wxFONTENCODING_CP1250,
97 wxFONTENCODING_CP1251,
98 wxFONTENCODING_CP1252,
99 wxFONTENCODING_CP1253,
100 wxFONTENCODING_CP1254,
101 wxFONTENCODING_CP1255,
102 wxFONTENCODING_CP1256,
103 wxFONTENCODING_CP1257,
f6bcfd97 104 wxFONTENCODING_CP437,
bb84929e
VZ
105 wxFONTENCODING_UTF7,
106 wxFONTENCODING_UTF8,
2b5f62a0 107 wxFONTENCODING_EUC_JP,
7beba2fc
VZ
108};
109
110// the descriptions for them
111static const wxChar* gs_encodingDescs[] =
112{
03424b1b
VZ
113 wxTRANSLATE( "Western European (ISO-8859-1)" ),
114 wxTRANSLATE( "Central European (ISO-8859-2)" ),
7beba2fc 115 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
f6bcfd97 116 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
03424b1b 117 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
7beba2fc
VZ
118 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
119 wxTRANSLATE( "Greek (ISO-8859-7)" ),
120 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
121 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
f6bcfd97 122 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
7beba2fc 123 wxTRANSLATE( "Thai (ISO-8859-11)" ),
80a24267 124 wxTRANSLATE( "Indian (ISO-8859-12)" ),
f6bcfd97 125 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
80a24267 126 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
03424b1b 127 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
7beba2fc 128 wxTRANSLATE( "KOI8-R" ),
bc4e6fcd 129 wxTRANSLATE( "Windows Japanese (CP 932)" ),
62b3ca69 130 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
bc4e6fcd
VZ
131 wxTRANSLATE( "Windows Korean (CP 949)" ),
132 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
80a24267 133 wxTRANSLATE( "Windows Central European (CP 1250)" ),
7beba2fc 134 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
80a24267 135 wxTRANSLATE( "Windows Western European (CP 1252)" ),
7beba2fc
VZ
136 wxTRANSLATE( "Windows Greek (CP 1253)" ),
137 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
138 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
139 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
140 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
f6bcfd97 141 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
bb84929e
VZ
142 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
143 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
2b5f62a0 144 wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
7beba2fc
VZ
145};
146
a4a6984d 147// and the internal names (these are not translated on purpose!)
7beba2fc
VZ
148static const wxChar* gs_encodingNames[] =
149{
ecffe992
VS
150 wxT( "iso-8859-1" ),
151 wxT( "iso-8859-2" ),
152 wxT( "iso-8859-3" ),
153 wxT( "iso-8859-4" ),
154 wxT( "iso-8859-5" ),
155 wxT( "iso-8859-6" ),
156 wxT( "iso-8859-7" ),
157 wxT( "iso-8859-8" ),
158 wxT( "iso-8859-9" ),
159 wxT( "iso-8859-10" ),
160 wxT( "iso-8859-11" ),
161 wxT( "iso-8859-12" ),
162 wxT( "iso-8859-13" ),
163 wxT( "iso-8859-14" ),
164 wxT( "iso-8859-15" ),
511f273f 165 wxT( "koi8-r" ),
bc4e6fcd
VZ
166 wxT( "windows-932" ),
167 wxT( "windows-936" ),
168 wxT( "windows-949" ),
169 wxT( "windows-950" ),
551fe3a6
VZ
170 wxT( "windows-1250" ),
171 wxT( "windows-1251" ),
172 wxT( "windows-1252" ),
173 wxT( "windows-1253" ),
174 wxT( "windows-1254" ),
175 wxT( "windows-1255" ),
176 wxT( "windows-1256" ),
177 wxT( "windows-1257" ),
178 wxT( "windows-437" ),
5707316c
VS
179 wxT( "utf-7" ),
180 wxT( "utf-8" ),
2b5f62a0 181 wxT( "euc-jp" ),
7beba2fc
VZ
182};
183
2b5f62a0
VZ
184wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs) == WXSIZEOF(gs_encodings) &&
185 WXSIZEOF(gs_encodingNames) == WXSIZEOF(gs_encodings),
186 EncodingsArraysNotInSync );
7beba2fc
VZ
187
188// ----------------------------------------------------------------------------
189// private classes
190// ----------------------------------------------------------------------------
191
192// change the config path during the lifetime of this object
193class wxFontMapperPathChanger
194{
195public:
196 wxFontMapperPathChanger(wxFontMapper *fontMapper, const wxString& path)
197 {
198 m_fontMapper = fontMapper;
199 m_ok = m_fontMapper->ChangePath(path, &m_pathOld);
200 }
201
202 bool IsOk() const { return m_ok; }
203
204 ~wxFontMapperPathChanger()
205 {
206 if ( IsOk() )
207 m_fontMapper->RestorePath(m_pathOld);
208 }
209
210private:
211 wxFontMapper *m_fontMapper;
212 bool m_ok;
213 wxString m_pathOld;
214};
3c1866e8
VZ
215
216// ============================================================================
217// implementation
218// ============================================================================
219
220// ----------------------------------------------------------------------------
221// ctor and dtor
222// ----------------------------------------------------------------------------
223
224wxFontMapper::wxFontMapper()
225{
f6bcfd97 226#if wxUSE_CONFIG
3c1866e8 227 m_config = NULL;
5fe83549 228 m_configIsDummy = FALSE;
f6bcfd97
BP
229#endif // wxUSE_CONFIG
230
231#if wxUSE_GUI
3c1866e8 232 m_windowParent = NULL;
f6bcfd97 233#endif // wxUSE_GUI
3c1866e8
VZ
234}
235
236wxFontMapper::~wxFontMapper()
237{
4d416b5f
VZ
238#if wxUSE_CONFIG
239 if ( m_configIsDummy )
240 delete m_config;
241#endif // wxUSE_CONFIG
3c1866e8
VZ
242}
243
142b3bc2
VS
244wxFontMapper *wxFontMapper::sm_instance = NULL;
245
246/*static*/ wxFontMapper *wxFontMapper::Get()
247{
248 if ( !sm_instance )
249 sm_instance = new wxFontMapper;
250 return sm_instance;
251}
252
253/*static*/ wxFontMapper *wxFontMapper::Set(wxFontMapper *mapper)
254{
255 wxFontMapper *old = sm_instance;
256 sm_instance = mapper;
257 return old;
258}
259
260class wxFontMapperModule: public wxModule
261{
262public:
263 wxFontMapperModule() : wxModule() {}
264 virtual bool OnInit() { return TRUE; }
265 virtual void OnExit() { delete wxFontMapper::Set(NULL); }
266
267 DECLARE_DYNAMIC_CLASS(wxFontMapperModule)
268};
269
270IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule, wxModule)
271
3c1866e8
VZ
272// ----------------------------------------------------------------------------
273// customisation
274// ----------------------------------------------------------------------------
275
f6bcfd97
BP
276#if wxUSE_CONFIG
277
3c1866e8
VZ
278/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
279{
280 return FONTMAPPER_ROOT_PATH;
281}
282
283void wxFontMapper::SetConfigPath(const wxString& prefix)
284{
285 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
fbdcff4a 286 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
3c1866e8
VZ
287
288 m_configRootPath = prefix;
289}
290
3c1866e8
VZ
291// ----------------------------------------------------------------------------
292// get config object and path for it
293// ----------------------------------------------------------------------------
294
295wxConfigBase *wxFontMapper::GetConfig()
296{
297 if ( !m_config )
298 {
299 // try the default
1d910ac1
VZ
300 m_config = wxConfig::Get(FALSE /*don't create on demand*/ );
301
302 if ( !m_config )
303 {
304 // we still want to have a config object because otherwise we would
305 // keep asking the user the same questions in the interactive mode,
306 // so create a dummy config which won't write to any files/registry
307 // but will allow us to remember the results of the questions at
308 // least during this run
309 m_config = new wxMemoryConfig;
5fe83549
VS
310 m_configIsDummy = TRUE;
311 // VS: we can't call wxConfig::Set(m_config) here because that would
312 // disable automatic wxConfig instance creation if this code was
313 // called before wxApp::OnInit (this happens in wxGTK -- it sets
314 // default wxFont encoding in wxApp::Initialize())
1d910ac1 315 }
3c1866e8
VZ
316 }
317
5fe83549
VS
318 if ( m_configIsDummy && wxConfig::Get(FALSE) != NULL )
319 {
320 // VS: in case we created dummy m_config (see above), we want to switch back
321 // to the real one as soon as one becomes available.
4d416b5f 322 delete m_config;
5fe83549
VS
323 m_config = wxConfig::Get(FALSE);
324 m_configIsDummy = FALSE;
325 // FIXME: ideally, we should add keys from dummy config to the real one now,
326 // but it is a low-priority task because typical wxWin application
c7821f94
VZ
327 // either doesn't use wxConfig at all or creates wxConfig object in
328 // wxApp::OnInit(), before any real interaction with the user takes
5fe83549
VS
329 // place...
330 }
331
3c1866e8
VZ
332 return m_config;
333}
334
335const wxString& wxFontMapper::GetConfigPath()
336{
337 if ( !m_configRootPath )
338 {
339 // use the default
340 m_configRootPath = GetDefaultConfigPath();
341 }
342
343 return m_configRootPath;
344}
f6bcfd97 345#endif
3c1866e8
VZ
346
347bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
348{
f6bcfd97 349#if wxUSE_CONFIG
3c1866e8
VZ
350 wxConfigBase *config = GetConfig();
351 if ( !config )
352 return FALSE;
353
354 *pathOld = config->GetPath();
355
356 wxString path = GetConfigPath();
357 if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
358 {
359 path += wxCONFIG_PATH_SEPARATOR;
360 }
361
362 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
58c837a4 363 wxT("should be a relative path") );
3c1866e8
VZ
364
365 path += pathNew;
366
367 config->SetPath(path);
368
369 return TRUE;
f6bcfd97
BP
370#else
371 return FALSE;
372#endif
3c1866e8
VZ
373}
374
375void wxFontMapper::RestorePath(const wxString& pathOld)
376{
f6bcfd97 377#if wxUSE_CONFIG
3c1866e8 378 GetConfig()->SetPath(pathOld);
f6bcfd97
BP
379#else
380#endif
3c1866e8
VZ
381}
382
383// ----------------------------------------------------------------------------
384// charset/encoding correspondence
385// ----------------------------------------------------------------------------
386
7beba2fc
VZ
387/* static */
388wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
389{
551fe3a6
VZ
390 if ( encoding == wxFONTENCODING_DEFAULT )
391 {
392 return _("Default encoding");
393 }
394
2b5f62a0 395 const size_t count = WXSIZEOF(gs_encodingDescs);
7beba2fc
VZ
396
397 for ( size_t i = 0; i < count; i++ )
398 {
399 if ( gs_encodings[i] == encoding )
400 {
401 return wxGetTranslation(gs_encodingDescs[i]);
402 }
403 }
404
405 wxString str;
406 str.Printf(_("Unknown encoding (%d)"), encoding);
407
408 return str;
409}
410
411/* static */
412wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
413{
551fe3a6
VZ
414 if ( encoding == wxFONTENCODING_DEFAULT )
415 {
416 return _("default");
417 }
418
2b5f62a0 419 const size_t count = WXSIZEOF(gs_encodingNames);
7beba2fc
VZ
420
421 for ( size_t i = 0; i < count; i++ )
422 {
423 if ( gs_encodings[i] == encoding )
424 {
a4a6984d 425 return gs_encodingNames[i];
7beba2fc
VZ
426 }
427 }
428
429 wxString str;
430 str.Printf(_("unknown-%d"), encoding);
431
432 return str;
433}
434
3c1866e8
VZ
435wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
436 bool interactive)
437{
3e7fb236
VZ
438 // a special pseudo encoding which means "don't ask me about this charset
439 // any more" - we need it to avoid driving the user crazy with asking him
440 // time after time about the same charset which he [presumably] doesn't
441 // have the fonts fot
442 static const int wxFONTENCODING_UNKNOWN = -2;
443
3c1866e8
VZ
444 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
445
446 // we're going to modify it, make a copy
447 wxString cs = charset;
448
f6bcfd97 449#if wxUSE_CONFIG
3c1866e8
VZ
450 // first try the user-defined settings
451 wxString pathOld;
452 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
453 {
454 wxConfigBase *config = GetConfig();
455
456 // do we have an encoding for this charset?
457 long value = config->Read(charset, -1l);
458 if ( value != -1 )
459 {
3e7fb236
VZ
460 if ( value == wxFONTENCODING_UNKNOWN )
461 {
462 // don't try to find it, in particular don't ask the user
463 return wxFONTENCODING_SYSTEM;
464 }
465
3c1866e8
VZ
466 if ( value >= 0 && value <= wxFONTENCODING_MAX )
467 {
468 encoding = (wxFontEncoding)value;
469 }
470 else
471 {
f6bcfd97 472 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 473 value, charset.c_str());
3c1866e8
VZ
474 }
475 }
476
477 if ( encoding == wxFONTENCODING_SYSTEM )
478 {
479 // may be we have an alias?
480 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
481
482 wxString alias = config->Read(charset);
483 if ( !!alias )
484 {
485 // yes, we do - use it instead
486 cs = alias;
487 }
488 }
489
490 RestorePath(pathOld);
491 }
3e7fb236 492#endif // wxUSE_CONFIG
3c1866e8 493
551fe3a6 494 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
495 if ( encoding == wxFONTENCODING_SYSTEM )
496 {
551fe3a6
VZ
497 // trim any spaces
498 cs.Trim(TRUE);
499 cs.Trim(FALSE);
500
3ca6a5f0 501 // discard the optional quotes
caa6e137 502 if ( !cs.empty() )
3ca6a5f0
BP
503 {
504 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
505 {
506 cs = wxString(cs.c_str(), cs.length() - 1);
507 }
508 }
509
3c1866e8
VZ
510 cs.MakeUpper();
511
cafbf6fb 512 if ( cs.empty() || cs == _T("US-ASCII") )
551fe3a6 513 {
3c1866e8 514 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 515 }
bb84929e 516 else if ( cs == wxT("UTF-7") )
551fe3a6 517 {
bb84929e 518 encoding = wxFONTENCODING_UTF7;
551fe3a6 519 }
bb84929e 520 else if ( cs == wxT("UTF-8") )
551fe3a6 521 {
bb84929e 522 encoding = wxFONTENCODING_UTF8;
551fe3a6 523 }
2b5f62a0
VZ
524 else if ( cs == wxT("GB2312") )
525 {
526 encoding = wxFONTENCODING_GB2312;
527 }
528 else if ( cs == wxT("BIG5") )
529 {
530 encoding = wxFONTENCODING_BIG5;
531 }
532 else if ( cs == wxT("SJIS") ||
533 cs == wxT("SHIFT_JIS") ||
534 cs == wxT("SHIFT-JIS") )
535 {
536 encoding = wxFONTENCODING_SHIFT_JIS;
537 }
538 else if ( cs == wxT("EUC-JP") ||
539 cs == wxT("EUC_JP") )
540 {
541 encoding = wxFONTENCODING_EUC_JP;
542 }
551fe3a6
VZ
543 else if ( cs == wxT("KOI8-R") ||
544 cs == wxT("KOI8-U") ||
545 cs == wxT("KOI8-RU") )
546 {
547 // although koi8-ru is not strictly speaking the same as koi8-r,
548 // they are similar enough to make mapping it to koi8 better than
549 // not reckognizing it at all
3c1866e8 550 encoding = wxFONTENCODING_KOI8;
551fe3a6 551 }
58c837a4 552 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
553 {
554 // the dash is optional (or, to be exact, it is not, but
555 // several brokenmails "forget" it)
556 const wxChar *p = cs.c_str() + 3;
58c837a4 557 if ( *p == wxT('-') )
3c1866e8 558 p++;
2b5f62a0
VZ
559
560 // printf( "iso %s\n", (const char*) cs.ToAscii() );
3c1866e8
VZ
561
562 unsigned int value;
58c837a4 563 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 564 {
2b5f62a0
VZ
565 // printf( "value %d\n", (int)value );
566
567 // make it 0 based and check that it is strictly positive in
568 // the process (no such thing as iso8859-0 encoding)
569 if ( (value-- > 0) &&
570 (value < wxFONTENCODING_ISO8859_MAX -
571 wxFONTENCODING_ISO8859_1) )
572 {
573 // it's a valid ISO8859 encoding
574 value += wxFONTENCODING_ISO8859_1;
575 encoding = (wxFontEncoding)value;
576 }
577 }
578 }
579 else if ( cs.Left(4) == wxT("8859") )
580 {
581 const wxChar *p = cs.c_str();
582
583 unsigned int value;
584 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
585 {
586 // printf( "value %d\n", (int)value );
587
daaa6710
VZ
588 // make it 0 based and check that it is strictly positive in
589 // the process (no such thing as iso8859-0 encoding)
590 if ( (value-- > 0) &&
591 (value < wxFONTENCODING_ISO8859_MAX -
592 wxFONTENCODING_ISO8859_1) )
3c1866e8
VZ
593 {
594 // it's a valid ISO8859 encoding
daaa6710 595 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
596 encoding = (wxFontEncoding)value;
597 }
598 }
599 }
551fe3a6 600 else // check for Windows charsets
3c1866e8 601 {
551fe3a6
VZ
602 size_t len;
603 if ( cs.Left(7) == wxT("WINDOWS") )
604 {
605 len = 7;
606 }
607 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 608 {
551fe3a6
VZ
609 len = 2;
610 }
611 else // not a Windows encoding
612 {
613 len = 0;
614 }
615
616 if ( len )
617 {
618 const wxChar *p = cs.c_str() + len;
619 if ( *p == wxT('-') )
620 p++;
621
622 int value;
623 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
3c1866e8 624 {
551fe3a6 625 if ( value >= 1250 )
3c1866e8 626 {
551fe3a6
VZ
627 value -= 1250;
628 if ( value < wxFONTENCODING_CP12_MAX -
629 wxFONTENCODING_CP1250 )
630 {
631 // a valid Windows code page
632 value += wxFONTENCODING_CP1250;
633 encoding = (wxFontEncoding)value;
634 }
3c1866e8 635 }
c7821f94
VZ
636
637 switch ( value )
638 {
639 case 932:
640 encoding = wxFONTENCODING_CP932;
641 break;
642
643 case 936:
644 encoding = wxFONTENCODING_CP936;
645 break;
646
647 case 949:
648 encoding = wxFONTENCODING_CP949;
649 break;
650
651 case 950:
652 encoding = wxFONTENCODING_CP950;
653 break;
654 }
3c1866e8
VZ
655 }
656 }
657 }
658 //else: unknown
659 }
660
f6bcfd97 661#if wxUSE_GUI
3c1866e8
VZ
662 // if still no luck, ask the user - unless disabled
663 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
664 {
665 // prepare the dialog data
666
667 // the dialog title
668 wxString title(m_titleDialog);
669 if ( !title )
670 title << wxTheApp->GetAppName() << _(": unknown charset");
671
672 // the message
673 wxString msg;
f6bcfd97 674 msg.Printf(_("The charset '%s' is unknown. You may select\nanother charset to replace it with or choose\n[Cancel] if it cannot be replaced"), charset.c_str());
3c1866e8
VZ
675
676 // the list of choices
2b5f62a0 677 const size_t count = WXSIZEOF(gs_encodingDescs);
3c1866e8
VZ
678
679 wxString *encodingNamesTranslated = new wxString[count];
680
11c7d5b6 681 for ( size_t i = 0; i < count; i++ )
3c1866e8 682 {
11c7d5b6 683 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
684 }
685
686 // the parent window
687 wxWindow *parent = m_windowParent;
688 if ( !parent )
689 parent = wxTheApp->GetTopWindow();
690
691 // do ask the user and get back the index in encodings table
692 int n = wxGetSingleChoiceIndex(msg, title,
693 count,
694 encodingNamesTranslated,
695 parent);
696
697 delete [] encodingNamesTranslated;
698
699 if ( n != -1 )
700 {
7beba2fc 701 encoding = gs_encodings[n];
3e7fb236 702 }
1d910ac1 703
f6bcfd97
BP
704#if wxUSE_CONFIG
705 // save the result in the config now
3e7fb236
VZ
706 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
707 {
708 wxConfigBase *config = GetConfig();
1d910ac1 709
3e7fb236
VZ
710 // remember the alt encoding for this charset - or remember that
711 // we don't know it
712 long value = n == -1 ? wxFONTENCODING_UNKNOWN : (long)encoding;
713 if ( !config->Write(charset, value) )
714 {
715 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
1d910ac1 716 }
3e7fb236
VZ
717
718 RestorePath(pathOld);
3c1866e8 719 }
3e7fb236 720#endif // wxUSE_CONFIG
3c1866e8 721 }
f6bcfd97 722#endif // wxUSE_GUI
3c1866e8
VZ
723
724 return encoding;
725}
726
7beba2fc
VZ
727// ----------------------------------------------------------------------------
728// support for unknown encodings: we maintain a map between the
729// (platform-specific) strings identifying them and our wxFontEncodings they
730// correspond to which is used by GetFontForEncoding() function
731// ----------------------------------------------------------------------------
732
f6bcfd97
BP
733#if wxUSE_GUI
734
7beba2fc
VZ
735bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
736 wxFontEncoding encReplacement,
737 wxNativeEncodingInfo *info)
738{
739 if ( wxGetNativeFontEncoding(encReplacement, info) &&
740 wxTestFontEncoding(*info) )
741 {
f6bcfd97 742#if wxUSE_CONFIG
7beba2fc
VZ
743 // remember the mapping in the config
744 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
745
746 if ( path.IsOk() )
747 {
748 GetConfig()->Write(configEntry, info->ToString());
749 }
f6bcfd97 750#endif // wxUSE_CONFIG
7beba2fc
VZ
751 return TRUE;
752 }
753
754 return FALSE;
755}
756
f6bcfd97
BP
757#if wxUSE_GUI
758class ReentrancyBlocker
759{
760public:
761 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
762 ~ReentrancyBlocker() { m_b = FALSE; }
763
764private:
765 bool& m_b;
766};
767#endif
768
7beba2fc
VZ
769bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
770 wxNativeEncodingInfo *info,
6648cd46 771 const wxString& facename,
7beba2fc
VZ
772 bool interactive)
773{
f6bcfd97
BP
774#if wxUSE_GUI
775 // we need a flag to prevent infinite recursion which happens, for
776 // example, when GetAltForEncoding() is called from an OnPaint() handler:
777 // in this case, wxYield() which is called from wxMessageBox() we use here
778 // will lead to another call of OnPaint() and hence to another call of
779 // GetAltForEncoding() - and it is impossible to catch this from the user
780 // code because we are called from wxFont ctor implicitly.
781
782 // assume we're always called from the main thread, so that it is safe to
783 // use a static var
784 static bool s_inGetAltForEncoding = FALSE;
785
786 if ( interactive && s_inGetAltForEncoding )
787 return FALSE;
788
789 ReentrancyBlocker blocker(s_inGetAltForEncoding);
790#endif // wxUSE_GUI
791
58c837a4 792 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 793
6648cd46
VS
794 info->facename = facename;
795
97d3f0ee
VZ
796 if ( encoding == wxFONTENCODING_DEFAULT )
797 {
798 encoding = wxFont::GetDefaultEncoding();
799 }
800
801 // if we failed to load the system default encoding, something is really
802 // wrong and we'd better stop now - otherwise we will go into endless
803 // recursion trying to create the font in the msg box with the error
804 // message
805 if ( encoding == wxFONTENCODING_SYSTEM )
806 {
73deed44 807 wxLogFatalError(_("can't load any font, aborting"));
97d3f0ee 808
73deed44 809 // wxLogFatalError doesn't return
97d3f0ee
VZ
810 }
811
a4a6984d
VZ
812 wxString configEntry,
813 encName = GetEncodingName(encoding);
1d910ac1
VZ
814 if ( !!facename )
815 {
816 configEntry = facename + _T("_");
817 }
818 configEntry += encName;
7beba2fc 819
f6bcfd97 820#if wxUSE_CONFIG
7beba2fc
VZ
821 // do we have a font spec for this encoding?
822 wxString pathOld;
823 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
824 {
825 wxConfigBase *config = GetConfig();
826
827 wxString fontinfo = config->Read(configEntry);
828
829 RestorePath(pathOld);
830
6603907d
VZ
831 // this special value means that we don't know of fonts for this
832 // encoding but, moreover, have already asked the user as well and he
833 // didn't specify any font neither
834 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
1d910ac1 835 {
6603907d 836 interactive = FALSE;
1d910ac1 837 }
6603907d 838 else // use the info entered the last time
7beba2fc 839 {
6603907d 840 if ( !!fontinfo && !!facename )
7beba2fc 841 {
6603907d
VZ
842 // we tried to find a match with facename - now try without it
843 fontinfo = config->Read(encName);
7beba2fc 844 }
6603907d
VZ
845
846 if ( !!fontinfo )
7beba2fc 847 {
6603907d
VZ
848 if ( info->FromString(fontinfo) )
849 {
850 if ( wxTestFontEncoding(*info) )
851 {
852 // ok, got something
853 return TRUE;
854 }
855 //else: no such fonts, look for something else
856 // (should we erase the outdated value?)
857 }
858 else
859 {
860 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
861 fontinfo.c_str());
862 }
7beba2fc 863 }
6603907d 864 //else: there is no information in config about this encoding
7beba2fc
VZ
865 }
866 }
f6bcfd97 867#endif // wxUSE_CONFIG
7beba2fc 868
3a989c8a
VZ
869 // now try to map this encoding to a compatible one which we have on this
870 // system
871 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
872 size_t count = equiv.GetCount();
873 bool foundEquivEncoding = FALSE;
c6465c96 874 wxFontEncoding equivEncoding = wxFONTENCODING_SYSTEM;
3a989c8a
VZ
875 if ( count )
876 {
877 for ( size_t i = 0; i < count && !foundEquivEncoding; i++ )
878 {
879 // don't test for encoding itself, we already know we don't have it
880 if ( equiv[i] == encoding )
881 continue;
882
883 if ( TestAltEncoding(configEntry, equiv[i], info) )
884 {
885 equivEncoding = equiv[i];
886
887 foundEquivEncoding = TRUE;
888 }
889 }
890 }
891
7beba2fc 892 // ask the user
3379ed37 893#if wxUSE_FONTDLG
7beba2fc
VZ
894 if ( interactive )
895 {
896 wxString title(m_titleDialog);
897 if ( !title )
898 title << wxTheApp->GetAppName() << _(": unknown encoding");
899
3a989c8a
VZ
900 // built the message
901 wxString encDesc = GetEncodingDescription(encoding),
902 msg;
903 if ( foundEquivEncoding )
904 {
905 // ask the user if he wants to override found alternative encoding
906 msg.Printf(_("No font for displaying text in encoding '%s' found,\nbut an alternative encoding '%s' is available.\nDo you want to use this encoding (otherwise you will have to choose another one)?"),
907 encDesc.c_str(), GetEncodingDescription(equivEncoding).c_str());
908 }
909 else
910 {
911 msg.Printf(_("No font for displaying text in encoding '%s' found.\nWould you like to select a font to be used for this encoding\n(otherwise the text in this encoding will not be shown correctly)?"),
912 encDesc.c_str());
913 }
7beba2fc 914
3a989c8a
VZ
915 // the question is different in 2 cases so the answer has to be
916 // interpreted differently as well
917 int answer = foundEquivEncoding ? wxNO : wxYES;
7beba2fc
VZ
918
919 if ( wxMessageBox(msg, title,
3a989c8a
VZ
920 wxICON_QUESTION | wxYES_NO,
921 m_windowParent) == answer )
7beba2fc
VZ
922 {
923 wxFontData data;
924 data.SetEncoding(encoding);
925 data.EncodingInfo() = *info;
baaae89f 926 wxFontDialog dialog(m_windowParent, data);
7beba2fc
VZ
927 if ( dialog.ShowModal() == wxID_OK )
928 {
929 wxFontData retData = dialog.GetFontData();
930 wxFont font = retData.GetChosenFont();
931
11c7d5b6 932 *info = retData.EncodingInfo();
3a989c8a 933 info->encoding = retData.GetEncoding();
7beba2fc 934
f6bcfd97 935#if wxUSE_CONFIG
6603907d 936 // remember this in the config
7beba2fc
VZ
937 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
938 {
939 GetConfig()->Write(configEntry, info->ToString());
940
941 RestorePath(pathOld);
942 }
bb84929e 943#endif // wxUSE_CONFIG
7beba2fc
VZ
944
945 return TRUE;
946 }
947 //else: the user canceled the font selection dialog
948 }
6603907d
VZ
949 else
950 {
3a989c8a
VZ
951 // the user doesn't want to select a font for this encoding
952 // or selected to use equivalent encoding
953 //
6603907d
VZ
954 // remember it to avoid asking the same question again later
955#if wxUSE_CONFIG
956 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
957 {
3a989c8a
VZ
958 GetConfig()->Write
959 (
960 configEntry,
961 foundEquivEncoding ? info->ToString().c_str()
962 : FONTMAPPER_FONT_DONT_ASK
963 );
6603907d
VZ
964
965 RestorePath(pathOld);
966 }
967#endif // wxUSE_CONFIG
968 }
7beba2fc
VZ
969 }
970 //else: we're in non-interactive mode
3379ed37 971#endif // wxUSE_FONTDLG
7beba2fc 972
3a989c8a 973 return foundEquivEncoding;
7beba2fc 974}
6648cd46 975
6648cd46
VS
976bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
977 wxFontEncoding *alt_encoding,
978 const wxString& facename,
979 bool interactive)
980{
981 wxNativeEncodingInfo info;
982 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
983 *alt_encoding = info.encoding;
984 return r;
985}
986
6648cd46
VS
987bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
988 const wxString& facename)
989{
990 wxNativeEncodingInfo info;
62ea506e 991
551fe3a6 992 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
993 {
994 info.facename = facename;
995 return wxTestFontEncoding(info);
996 }
3ca6a5f0
BP
997
998 return FALSE;
6648cd46 999}
f6bcfd97
BP
1000
1001#endif // wxUSE_GUI
1e6feb95
VZ
1002
1003#endif // wxUSE_FONTMAP