]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
wxMac: wxUniversal integration steps
[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
136// and the internal names
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" ),
bb84929e
VZ
164 wxT( "utf7" ),
165 wxT( "utf8" ),
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;
f6bcfd97
BP
218#endif // wxUSE_CONFIG
219
220#if wxUSE_GUI
3c1866e8 221 m_windowParent = NULL;
f6bcfd97 222#endif // wxUSE_GUI
3c1866e8
VZ
223}
224
225wxFontMapper::~wxFontMapper()
226{
227}
228
229// ----------------------------------------------------------------------------
230// customisation
231// ----------------------------------------------------------------------------
232
f6bcfd97
BP
233#if wxUSE_CONFIG
234
3c1866e8
VZ
235/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
236{
237 return FONTMAPPER_ROOT_PATH;
238}
239
240void wxFontMapper::SetConfigPath(const wxString& prefix)
241{
242 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
fbdcff4a 243 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
3c1866e8
VZ
244
245 m_configRootPath = prefix;
246}
247
3c1866e8
VZ
248// ----------------------------------------------------------------------------
249// get config object and path for it
250// ----------------------------------------------------------------------------
251
252wxConfigBase *wxFontMapper::GetConfig()
253{
254 if ( !m_config )
255 {
256 // try the default
1d910ac1
VZ
257 m_config = wxConfig::Get(FALSE /*don't create on demand*/ );
258
259 if ( !m_config )
260 {
261 // we still want to have a config object because otherwise we would
262 // keep asking the user the same questions in the interactive mode,
263 // so create a dummy config which won't write to any files/registry
264 // but will allow us to remember the results of the questions at
265 // least during this run
266 m_config = new wxMemoryConfig;
267 wxConfig::Set(m_config);
268 }
3c1866e8
VZ
269 }
270
271 return m_config;
272}
273
274const wxString& wxFontMapper::GetConfigPath()
275{
276 if ( !m_configRootPath )
277 {
278 // use the default
279 m_configRootPath = GetDefaultConfigPath();
280 }
281
282 return m_configRootPath;
283}
f6bcfd97 284#endif
3c1866e8
VZ
285
286bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
287{
f6bcfd97 288#if wxUSE_CONFIG
3c1866e8
VZ
289 wxConfigBase *config = GetConfig();
290 if ( !config )
291 return FALSE;
292
293 *pathOld = config->GetPath();
294
295 wxString path = GetConfigPath();
296 if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
297 {
298 path += wxCONFIG_PATH_SEPARATOR;
299 }
300
301 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
58c837a4 302 wxT("should be a relative path") );
3c1866e8
VZ
303
304 path += pathNew;
305
306 config->SetPath(path);
307
308 return TRUE;
f6bcfd97
BP
309#else
310 return FALSE;
311#endif
3c1866e8
VZ
312}
313
314void wxFontMapper::RestorePath(const wxString& pathOld)
315{
f6bcfd97 316#if wxUSE_CONFIG
3c1866e8 317 GetConfig()->SetPath(pathOld);
f6bcfd97
BP
318#else
319#endif
3c1866e8
VZ
320}
321
322// ----------------------------------------------------------------------------
323// charset/encoding correspondence
324// ----------------------------------------------------------------------------
325
7beba2fc
VZ
326/* static */
327wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
328{
551fe3a6
VZ
329 if ( encoding == wxFONTENCODING_DEFAULT )
330 {
331 return _("Default encoding");
332 }
333
7beba2fc
VZ
334 size_t count = WXSIZEOF(gs_encodingDescs);
335
336 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 337 wxT("inconsitency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
338
339 for ( size_t i = 0; i < count; i++ )
340 {
341 if ( gs_encodings[i] == encoding )
342 {
343 return wxGetTranslation(gs_encodingDescs[i]);
344 }
345 }
346
347 wxString str;
348 str.Printf(_("Unknown encoding (%d)"), encoding);
349
350 return str;
351}
352
353/* static */
354wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
355{
551fe3a6
VZ
356 if ( encoding == wxFONTENCODING_DEFAULT )
357 {
358 return _("default");
359 }
360
7beba2fc
VZ
361 size_t count = WXSIZEOF(gs_encodingNames);
362
363 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 364 wxT("inconsistency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
365
366 for ( size_t i = 0; i < count; i++ )
367 {
368 if ( gs_encodings[i] == encoding )
369 {
370 return wxGetTranslation(gs_encodingNames[i]);
371 }
372 }
373
374 wxString str;
375 str.Printf(_("unknown-%d"), encoding);
376
377 return str;
378}
379
3c1866e8
VZ
380wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
381 bool interactive)
382{
383 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
384
385 // we're going to modify it, make a copy
386 wxString cs = charset;
387
f6bcfd97 388#if wxUSE_CONFIG
3c1866e8
VZ
389 // first try the user-defined settings
390 wxString pathOld;
391 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
392 {
393 wxConfigBase *config = GetConfig();
394
395 // do we have an encoding for this charset?
396 long value = config->Read(charset, -1l);
397 if ( value != -1 )
398 {
399 if ( value >= 0 && value <= wxFONTENCODING_MAX )
400 {
401 encoding = (wxFontEncoding)value;
402 }
403 else
404 {
f6bcfd97 405 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 406 value, charset.c_str());
3c1866e8
VZ
407 }
408 }
409
410 if ( encoding == wxFONTENCODING_SYSTEM )
411 {
412 // may be we have an alias?
413 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
414
415 wxString alias = config->Read(charset);
416 if ( !!alias )
417 {
418 // yes, we do - use it instead
419 cs = alias;
420 }
421 }
422
423 RestorePath(pathOld);
424 }
551fe3a6 425#endif
3c1866e8 426
551fe3a6 427 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
428 if ( encoding == wxFONTENCODING_SYSTEM )
429 {
551fe3a6
VZ
430 // trim any spaces
431 cs.Trim(TRUE);
432 cs.Trim(FALSE);
433
3ca6a5f0
BP
434 // discard the optional quotes
435 if ( !!cs )
436 {
437 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
438 {
439 cs = wxString(cs.c_str(), cs.length() - 1);
440 }
441 }
442
3c1866e8
VZ
443 cs.MakeUpper();
444
58c837a4 445 if ( !cs || cs == wxT("US-ASCII") )
551fe3a6 446 {
3c1866e8 447 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 448 }
bb84929e 449 else if ( cs == wxT("UTF-7") )
551fe3a6 450 {
bb84929e 451 encoding = wxFONTENCODING_UTF7;
551fe3a6 452 }
bb84929e 453 else if ( cs == wxT("UTF-8") )
551fe3a6 454 {
bb84929e 455 encoding = wxFONTENCODING_UTF8;
551fe3a6
VZ
456 }
457 else if ( cs == wxT("KOI8-R") ||
458 cs == wxT("KOI8-U") ||
459 cs == wxT("KOI8-RU") )
460 {
461 // although koi8-ru is not strictly speaking the same as koi8-r,
462 // they are similar enough to make mapping it to koi8 better than
463 // not reckognizing it at all
3c1866e8 464 encoding = wxFONTENCODING_KOI8;
551fe3a6 465 }
58c837a4 466 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
467 {
468 // the dash is optional (or, to be exact, it is not, but
469 // several brokenmails "forget" it)
470 const wxChar *p = cs.c_str() + 3;
58c837a4 471 if ( *p == wxT('-') )
3c1866e8
VZ
472 p++;
473
474 unsigned int value;
58c837a4 475 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 476 {
daaa6710
VZ
477 // make it 0 based and check that it is strictly positive in
478 // the process (no such thing as iso8859-0 encoding)
479 if ( (value-- > 0) &&
480 (value < wxFONTENCODING_ISO8859_MAX -
481 wxFONTENCODING_ISO8859_1) )
3c1866e8
VZ
482 {
483 // it's a valid ISO8859 encoding
daaa6710 484 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
485 encoding = (wxFontEncoding)value;
486 }
487 }
488 }
551fe3a6 489 else // check for Windows charsets
3c1866e8 490 {
551fe3a6
VZ
491 size_t len;
492 if ( cs.Left(7) == wxT("WINDOWS") )
493 {
494 len = 7;
495 }
496 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 497 {
551fe3a6
VZ
498 len = 2;
499 }
500 else // not a Windows encoding
501 {
502 len = 0;
503 }
504
505 if ( len )
506 {
507 const wxChar *p = cs.c_str() + len;
508 if ( *p == wxT('-') )
509 p++;
510
511 int value;
512 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
3c1866e8 513 {
551fe3a6 514 if ( value >= 1250 )
3c1866e8 515 {
551fe3a6
VZ
516 value -= 1250;
517 if ( value < wxFONTENCODING_CP12_MAX -
518 wxFONTENCODING_CP1250 )
519 {
520 // a valid Windows code page
521 value += wxFONTENCODING_CP1250;
522 encoding = (wxFontEncoding)value;
523 }
3c1866e8
VZ
524 }
525 }
526 }
527 }
528 //else: unknown
529 }
530
f6bcfd97 531#if wxUSE_GUI
3c1866e8
VZ
532 // if still no luck, ask the user - unless disabled
533 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
534 {
535 // prepare the dialog data
536
537 // the dialog title
538 wxString title(m_titleDialog);
539 if ( !title )
540 title << wxTheApp->GetAppName() << _(": unknown charset");
541
542 // the message
543 wxString msg;
f6bcfd97 544 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
545
546 // the list of choices
7beba2fc
VZ
547 size_t count = WXSIZEOF(gs_encodingDescs);
548
549 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 550 wxT("inconsitency detected - forgot to update one of the arrays?") );
3c1866e8
VZ
551
552 wxString *encodingNamesTranslated = new wxString[count];
553
11c7d5b6 554 for ( size_t i = 0; i < count; i++ )
3c1866e8 555 {
11c7d5b6 556 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
557 }
558
559 // the parent window
560 wxWindow *parent = m_windowParent;
561 if ( !parent )
562 parent = wxTheApp->GetTopWindow();
563
564 // do ask the user and get back the index in encodings table
565 int n = wxGetSingleChoiceIndex(msg, title,
566 count,
567 encodingNamesTranslated,
568 parent);
569
570 delete [] encodingNamesTranslated;
571
572 if ( n != -1 )
573 {
7beba2fc 574 encoding = gs_encodings[n];
1d910ac1 575
f6bcfd97
BP
576#if wxUSE_CONFIG
577 // save the result in the config now
1d910ac1
VZ
578 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
579 {
580 wxConfigBase *config = GetConfig();
581
582 // remember the alt encoding for this charset
583 if ( !config->Write(charset, (long)encoding) )
584 {
f6bcfd97 585 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
1d910ac1
VZ
586 }
587
588 RestorePath(pathOld);
589 }
f6bcfd97 590#endif // wxUSE_CONFIG
3c1866e8
VZ
591 }
592 //else: cancelled
593 }
f6bcfd97 594#endif // wxUSE_GUI
3c1866e8
VZ
595
596 return encoding;
597}
598
7beba2fc
VZ
599// ----------------------------------------------------------------------------
600// support for unknown encodings: we maintain a map between the
601// (platform-specific) strings identifying them and our wxFontEncodings they
602// correspond to which is used by GetFontForEncoding() function
603// ----------------------------------------------------------------------------
604
f6bcfd97
BP
605#if wxUSE_GUI
606
7beba2fc
VZ
607bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
608 wxFontEncoding encReplacement,
609 wxNativeEncodingInfo *info)
610{
611 if ( wxGetNativeFontEncoding(encReplacement, info) &&
612 wxTestFontEncoding(*info) )
613 {
f6bcfd97 614#if wxUSE_CONFIG
7beba2fc
VZ
615 // remember the mapping in the config
616 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
617
618 if ( path.IsOk() )
619 {
620 GetConfig()->Write(configEntry, info->ToString());
621 }
f6bcfd97 622#endif // wxUSE_CONFIG
7beba2fc
VZ
623 return TRUE;
624 }
625
626 return FALSE;
627}
628
f6bcfd97
BP
629#if wxUSE_GUI
630class ReentrancyBlocker
631{
632public:
633 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
634 ~ReentrancyBlocker() { m_b = FALSE; }
635
636private:
637 bool& m_b;
638};
639#endif
640
7beba2fc
VZ
641bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
642 wxNativeEncodingInfo *info,
6648cd46 643 const wxString& facename,
7beba2fc
VZ
644 bool interactive)
645{
f6bcfd97
BP
646#if wxUSE_GUI
647 // we need a flag to prevent infinite recursion which happens, for
648 // example, when GetAltForEncoding() is called from an OnPaint() handler:
649 // in this case, wxYield() which is called from wxMessageBox() we use here
650 // will lead to another call of OnPaint() and hence to another call of
651 // GetAltForEncoding() - and it is impossible to catch this from the user
652 // code because we are called from wxFont ctor implicitly.
653
654 // assume we're always called from the main thread, so that it is safe to
655 // use a static var
656 static bool s_inGetAltForEncoding = FALSE;
657
658 if ( interactive && s_inGetAltForEncoding )
659 return FALSE;
660
661 ReentrancyBlocker blocker(s_inGetAltForEncoding);
662#endif // wxUSE_GUI
663
58c837a4 664 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 665
6648cd46
VS
666 info->facename = facename;
667
97d3f0ee
VZ
668 if ( encoding == wxFONTENCODING_DEFAULT )
669 {
670 encoding = wxFont::GetDefaultEncoding();
671 }
672
673 // if we failed to load the system default encoding, something is really
674 // wrong and we'd better stop now - otherwise we will go into endless
675 // recursion trying to create the font in the msg box with the error
676 // message
677 if ( encoding == wxFONTENCODING_SYSTEM )
678 {
679 wxFatalError(_("can't load any font, aborting"));
680
681 // wxFatalError doesn't return
682 }
683
1d910ac1
VZ
684 wxString configEntry, encName = GetEncodingName(encoding);
685 if ( !!facename )
686 {
687 configEntry = facename + _T("_");
688 }
689 configEntry += encName;
7beba2fc 690
f6bcfd97 691#if wxUSE_CONFIG
7beba2fc
VZ
692 // do we have a font spec for this encoding?
693 wxString pathOld;
694 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
695 {
696 wxConfigBase *config = GetConfig();
697
698 wxString fontinfo = config->Read(configEntry);
699
700 RestorePath(pathOld);
701
6603907d
VZ
702 // this special value means that we don't know of fonts for this
703 // encoding but, moreover, have already asked the user as well and he
704 // didn't specify any font neither
705 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
1d910ac1 706 {
6603907d 707 interactive = FALSE;
1d910ac1 708 }
6603907d 709 else // use the info entered the last time
7beba2fc 710 {
6603907d 711 if ( !!fontinfo && !!facename )
7beba2fc 712 {
6603907d
VZ
713 // we tried to find a match with facename - now try without it
714 fontinfo = config->Read(encName);
7beba2fc 715 }
6603907d
VZ
716
717 if ( !!fontinfo )
7beba2fc 718 {
6603907d
VZ
719 if ( info->FromString(fontinfo) )
720 {
721 if ( wxTestFontEncoding(*info) )
722 {
723 // ok, got something
724 return TRUE;
725 }
726 //else: no such fonts, look for something else
727 // (should we erase the outdated value?)
728 }
729 else
730 {
731 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
732 fontinfo.c_str());
733 }
7beba2fc 734 }
6603907d 735 //else: there is no information in config about this encoding
7beba2fc
VZ
736 }
737 }
f6bcfd97 738#endif // wxUSE_CONFIG
7beba2fc
VZ
739
740 // ask the user
3379ed37 741#if wxUSE_FONTDLG
7beba2fc
VZ
742 if ( interactive )
743 {
744 wxString title(m_titleDialog);
745 if ( !title )
746 title << wxTheApp->GetAppName() << _(": unknown encoding");
747
748 // the message
749 wxString msg;
6603907d 750 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
751 GetEncodingDescription(encoding).c_str());
752
753 wxWindow *parent = m_windowParent;
754 if ( !parent )
755 parent = wxTheApp->GetTopWindow();
756
757 if ( wxMessageBox(msg, title,
758 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
759 {
760 wxFontData data;
761 data.SetEncoding(encoding);
762 data.EncodingInfo() = *info;
763 wxFontDialog dialog(parent, &data);
764 if ( dialog.ShowModal() == wxID_OK )
765 {
766 wxFontData retData = dialog.GetFontData();
767 wxFont font = retData.GetChosenFont();
768
11c7d5b6 769 *info = retData.EncodingInfo();
551fe3a6 770 info -> encoding = retData.GetEncoding();
7beba2fc 771
f6bcfd97 772#if wxUSE_CONFIG
6603907d 773 // remember this in the config
7beba2fc
VZ
774 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
775 {
776 GetConfig()->Write(configEntry, info->ToString());
777
778 RestorePath(pathOld);
779 }
bb84929e 780#endif // wxUSE_CONFIG
7beba2fc
VZ
781
782 return TRUE;
783 }
784 //else: the user canceled the font selection dialog
785 }
6603907d
VZ
786 else
787 {
788 // the user doesn't want to select a font for this encoding,
789 // remember it to avoid asking the same question again later
790#if wxUSE_CONFIG
791 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
792 {
793 GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK);
794
795 RestorePath(pathOld);
796 }
797#endif // wxUSE_CONFIG
798 }
7beba2fc
VZ
799 }
800 //else: we're in non-interactive mode
3379ed37 801#endif // wxUSE_FONTDLG
7beba2fc 802
82545b58 803 // now try the default mappings:
82545b58 804 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
1d910ac1 805 size_t count = equiv.GetCount();
3ca6a5f0 806 if ( count )
1d910ac1 807 {
3ca6a5f0
BP
808 for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
809 {
810 if ( TestAltEncoding(configEntry, equiv[i], info) )
811 return TRUE;
812 }
1d910ac1 813 }
7beba2fc
VZ
814
815 return FALSE;
816}
6648cd46 817
6648cd46
VS
818bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
819 wxFontEncoding *alt_encoding,
820 const wxString& facename,
821 bool interactive)
822{
823 wxNativeEncodingInfo info;
824 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
825 *alt_encoding = info.encoding;
826 return r;
827}
828
6648cd46
VS
829bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
830 const wxString& facename)
831{
832 wxNativeEncodingInfo info;
62ea506e 833
551fe3a6 834 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
835 {
836 info.facename = facename;
837 return wxTestFontEncoding(info);
838 }
3ca6a5f0
BP
839
840 return FALSE;
6648cd46 841}
f6bcfd97
BP
842
843#endif // wxUSE_GUI
1e6feb95
VZ
844
845#endif // wxUSE_FONTMAP