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