]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
merged MapBitmap() from 2.2 branch
[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;
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 {
388 return wxGetTranslation(gs_encodingNames[i]);
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{
401 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
402
403 // we're going to modify it, make a copy
404 wxString cs = charset;
405
f6bcfd97 406#if wxUSE_CONFIG
3c1866e8
VZ
407 // first try the user-defined settings
408 wxString pathOld;
409 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
410 {
411 wxConfigBase *config = GetConfig();
412
413 // do we have an encoding for this charset?
414 long value = config->Read(charset, -1l);
415 if ( value != -1 )
416 {
417 if ( value >= 0 && value <= wxFONTENCODING_MAX )
418 {
419 encoding = (wxFontEncoding)value;
420 }
421 else
422 {
f6bcfd97 423 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 424 value, charset.c_str());
3c1866e8
VZ
425 }
426 }
427
428 if ( encoding == wxFONTENCODING_SYSTEM )
429 {
430 // may be we have an alias?
431 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
432
433 wxString alias = config->Read(charset);
434 if ( !!alias )
435 {
436 // yes, we do - use it instead
437 cs = alias;
438 }
439 }
440
441 RestorePath(pathOld);
442 }
551fe3a6 443#endif
3c1866e8 444
551fe3a6 445 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
446 if ( encoding == wxFONTENCODING_SYSTEM )
447 {
551fe3a6
VZ
448 // trim any spaces
449 cs.Trim(TRUE);
450 cs.Trim(FALSE);
451
3ca6a5f0
BP
452 // discard the optional quotes
453 if ( !!cs )
454 {
455 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
456 {
457 cs = wxString(cs.c_str(), cs.length() - 1);
458 }
459 }
460
3c1866e8
VZ
461 cs.MakeUpper();
462
58c837a4 463 if ( !cs || cs == wxT("US-ASCII") )
551fe3a6 464 {
3c1866e8 465 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 466 }
bb84929e 467 else if ( cs == wxT("UTF-7") )
551fe3a6 468 {
bb84929e 469 encoding = wxFONTENCODING_UTF7;
551fe3a6 470 }
bb84929e 471 else if ( cs == wxT("UTF-8") )
551fe3a6 472 {
bb84929e 473 encoding = wxFONTENCODING_UTF8;
551fe3a6
VZ
474 }
475 else if ( cs == wxT("KOI8-R") ||
476 cs == wxT("KOI8-U") ||
477 cs == wxT("KOI8-RU") )
478 {
479 // although koi8-ru is not strictly speaking the same as koi8-r,
480 // they are similar enough to make mapping it to koi8 better than
481 // not reckognizing it at all
3c1866e8 482 encoding = wxFONTENCODING_KOI8;
551fe3a6 483 }
58c837a4 484 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
485 {
486 // the dash is optional (or, to be exact, it is not, but
487 // several brokenmails "forget" it)
488 const wxChar *p = cs.c_str() + 3;
58c837a4 489 if ( *p == wxT('-') )
3c1866e8
VZ
490 p++;
491
492 unsigned int value;
58c837a4 493 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 494 {
daaa6710
VZ
495 // make it 0 based and check that it is strictly positive in
496 // the process (no such thing as iso8859-0 encoding)
497 if ( (value-- > 0) &&
498 (value < wxFONTENCODING_ISO8859_MAX -
499 wxFONTENCODING_ISO8859_1) )
3c1866e8
VZ
500 {
501 // it's a valid ISO8859 encoding
daaa6710 502 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
503 encoding = (wxFontEncoding)value;
504 }
505 }
506 }
551fe3a6 507 else // check for Windows charsets
3c1866e8 508 {
551fe3a6
VZ
509 size_t len;
510 if ( cs.Left(7) == wxT("WINDOWS") )
511 {
512 len = 7;
513 }
514 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 515 {
551fe3a6
VZ
516 len = 2;
517 }
518 else // not a Windows encoding
519 {
520 len = 0;
521 }
522
523 if ( len )
524 {
525 const wxChar *p = cs.c_str() + len;
526 if ( *p == wxT('-') )
527 p++;
528
529 int value;
530 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
3c1866e8 531 {
551fe3a6 532 if ( value >= 1250 )
3c1866e8 533 {
551fe3a6
VZ
534 value -= 1250;
535 if ( value < wxFONTENCODING_CP12_MAX -
536 wxFONTENCODING_CP1250 )
537 {
538 // a valid Windows code page
539 value += wxFONTENCODING_CP1250;
540 encoding = (wxFontEncoding)value;
541 }
3c1866e8
VZ
542 }
543 }
544 }
545 }
546 //else: unknown
547 }
548
f6bcfd97 549#if wxUSE_GUI
3c1866e8
VZ
550 // if still no luck, ask the user - unless disabled
551 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
552 {
553 // prepare the dialog data
554
555 // the dialog title
556 wxString title(m_titleDialog);
557 if ( !title )
558 title << wxTheApp->GetAppName() << _(": unknown charset");
559
560 // the message
561 wxString msg;
f6bcfd97 562 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
563
564 // the list of choices
7beba2fc
VZ
565 size_t count = WXSIZEOF(gs_encodingDescs);
566
567 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 568 wxT("inconsitency detected - forgot to update one of the arrays?") );
3c1866e8
VZ
569
570 wxString *encodingNamesTranslated = new wxString[count];
571
11c7d5b6 572 for ( size_t i = 0; i < count; i++ )
3c1866e8 573 {
11c7d5b6 574 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
575 }
576
577 // the parent window
578 wxWindow *parent = m_windowParent;
579 if ( !parent )
580 parent = wxTheApp->GetTopWindow();
581
582 // do ask the user and get back the index in encodings table
583 int n = wxGetSingleChoiceIndex(msg, title,
584 count,
585 encodingNamesTranslated,
586 parent);
587
588 delete [] encodingNamesTranslated;
589
590 if ( n != -1 )
591 {
7beba2fc 592 encoding = gs_encodings[n];
1d910ac1 593
f6bcfd97
BP
594#if wxUSE_CONFIG
595 // save the result in the config now
1d910ac1
VZ
596 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
597 {
598 wxConfigBase *config = GetConfig();
599
600 // remember the alt encoding for this charset
601 if ( !config->Write(charset, (long)encoding) )
602 {
f6bcfd97 603 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
1d910ac1
VZ
604 }
605
606 RestorePath(pathOld);
607 }
f6bcfd97 608#endif // wxUSE_CONFIG
3c1866e8
VZ
609 }
610 //else: cancelled
611 }
f6bcfd97 612#endif // wxUSE_GUI
3c1866e8
VZ
613
614 return encoding;
615}
616
7beba2fc
VZ
617// ----------------------------------------------------------------------------
618// support for unknown encodings: we maintain a map between the
619// (platform-specific) strings identifying them and our wxFontEncodings they
620// correspond to which is used by GetFontForEncoding() function
621// ----------------------------------------------------------------------------
622
f6bcfd97
BP
623#if wxUSE_GUI
624
7beba2fc
VZ
625bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
626 wxFontEncoding encReplacement,
627 wxNativeEncodingInfo *info)
628{
629 if ( wxGetNativeFontEncoding(encReplacement, info) &&
630 wxTestFontEncoding(*info) )
631 {
f6bcfd97 632#if wxUSE_CONFIG
7beba2fc
VZ
633 // remember the mapping in the config
634 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
635
636 if ( path.IsOk() )
637 {
638 GetConfig()->Write(configEntry, info->ToString());
639 }
f6bcfd97 640#endif // wxUSE_CONFIG
7beba2fc
VZ
641 return TRUE;
642 }
643
644 return FALSE;
645}
646
f6bcfd97
BP
647#if wxUSE_GUI
648class ReentrancyBlocker
649{
650public:
651 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
652 ~ReentrancyBlocker() { m_b = FALSE; }
653
654private:
655 bool& m_b;
656};
657#endif
658
7beba2fc
VZ
659bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
660 wxNativeEncodingInfo *info,
6648cd46 661 const wxString& facename,
7beba2fc
VZ
662 bool interactive)
663{
f6bcfd97
BP
664#if wxUSE_GUI
665 // we need a flag to prevent infinite recursion which happens, for
666 // example, when GetAltForEncoding() is called from an OnPaint() handler:
667 // in this case, wxYield() which is called from wxMessageBox() we use here
668 // will lead to another call of OnPaint() and hence to another call of
669 // GetAltForEncoding() - and it is impossible to catch this from the user
670 // code because we are called from wxFont ctor implicitly.
671
672 // assume we're always called from the main thread, so that it is safe to
673 // use a static var
674 static bool s_inGetAltForEncoding = FALSE;
675
676 if ( interactive && s_inGetAltForEncoding )
677 return FALSE;
678
679 ReentrancyBlocker blocker(s_inGetAltForEncoding);
680#endif // wxUSE_GUI
681
58c837a4 682 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 683
6648cd46
VS
684 info->facename = facename;
685
97d3f0ee
VZ
686 if ( encoding == wxFONTENCODING_DEFAULT )
687 {
688 encoding = wxFont::GetDefaultEncoding();
689 }
690
691 // if we failed to load the system default encoding, something is really
692 // wrong and we'd better stop now - otherwise we will go into endless
693 // recursion trying to create the font in the msg box with the error
694 // message
695 if ( encoding == wxFONTENCODING_SYSTEM )
696 {
697 wxFatalError(_("can't load any font, aborting"));
698
699 // wxFatalError doesn't return
700 }
701
1d910ac1
VZ
702 wxString configEntry, encName = GetEncodingName(encoding);
703 if ( !!facename )
704 {
705 configEntry = facename + _T("_");
706 }
707 configEntry += encName;
7beba2fc 708
f6bcfd97 709#if wxUSE_CONFIG
7beba2fc
VZ
710 // do we have a font spec for this encoding?
711 wxString pathOld;
712 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
713 {
714 wxConfigBase *config = GetConfig();
715
716 wxString fontinfo = config->Read(configEntry);
717
718 RestorePath(pathOld);
719
6603907d
VZ
720 // this special value means that we don't know of fonts for this
721 // encoding but, moreover, have already asked the user as well and he
722 // didn't specify any font neither
723 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
1d910ac1 724 {
6603907d 725 interactive = FALSE;
1d910ac1 726 }
6603907d 727 else // use the info entered the last time
7beba2fc 728 {
6603907d 729 if ( !!fontinfo && !!facename )
7beba2fc 730 {
6603907d
VZ
731 // we tried to find a match with facename - now try without it
732 fontinfo = config->Read(encName);
7beba2fc 733 }
6603907d
VZ
734
735 if ( !!fontinfo )
7beba2fc 736 {
6603907d
VZ
737 if ( info->FromString(fontinfo) )
738 {
739 if ( wxTestFontEncoding(*info) )
740 {
741 // ok, got something
742 return TRUE;
743 }
744 //else: no such fonts, look for something else
745 // (should we erase the outdated value?)
746 }
747 else
748 {
749 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
750 fontinfo.c_str());
751 }
7beba2fc 752 }
6603907d 753 //else: there is no information in config about this encoding
7beba2fc
VZ
754 }
755 }
f6bcfd97 756#endif // wxUSE_CONFIG
7beba2fc
VZ
757
758 // ask the user
3379ed37 759#if wxUSE_FONTDLG
7beba2fc
VZ
760 if ( interactive )
761 {
762 wxString title(m_titleDialog);
763 if ( !title )
764 title << wxTheApp->GetAppName() << _(": unknown encoding");
765
766 // the message
767 wxString msg;
6603907d 768 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
769 GetEncodingDescription(encoding).c_str());
770
771 wxWindow *parent = m_windowParent;
772 if ( !parent )
773 parent = wxTheApp->GetTopWindow();
774
775 if ( wxMessageBox(msg, title,
776 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
777 {
778 wxFontData data;
779 data.SetEncoding(encoding);
780 data.EncodingInfo() = *info;
781 wxFontDialog dialog(parent, &data);
782 if ( dialog.ShowModal() == wxID_OK )
783 {
784 wxFontData retData = dialog.GetFontData();
785 wxFont font = retData.GetChosenFont();
786
11c7d5b6 787 *info = retData.EncodingInfo();
551fe3a6 788 info -> encoding = retData.GetEncoding();
7beba2fc 789
f6bcfd97 790#if wxUSE_CONFIG
6603907d 791 // remember this in the config
7beba2fc
VZ
792 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
793 {
794 GetConfig()->Write(configEntry, info->ToString());
795
796 RestorePath(pathOld);
797 }
bb84929e 798#endif // wxUSE_CONFIG
7beba2fc
VZ
799
800 return TRUE;
801 }
802 //else: the user canceled the font selection dialog
803 }
6603907d
VZ
804 else
805 {
806 // the user doesn't want to select a font for this encoding,
807 // remember it to avoid asking the same question again later
808#if wxUSE_CONFIG
809 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
810 {
811 GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK);
812
813 RestorePath(pathOld);
814 }
815#endif // wxUSE_CONFIG
816 }
7beba2fc
VZ
817 }
818 //else: we're in non-interactive mode
3379ed37 819#endif // wxUSE_FONTDLG
7beba2fc 820
82545b58 821 // now try the default mappings:
82545b58 822 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
1d910ac1 823 size_t count = equiv.GetCount();
3ca6a5f0 824 if ( count )
1d910ac1 825 {
3ca6a5f0
BP
826 for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
827 {
828 if ( TestAltEncoding(configEntry, equiv[i], info) )
829 return TRUE;
830 }
1d910ac1 831 }
7beba2fc
VZ
832
833 return FALSE;
834}
6648cd46 835
6648cd46
VS
836bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
837 wxFontEncoding *alt_encoding,
838 const wxString& facename,
839 bool interactive)
840{
841 wxNativeEncodingInfo info;
842 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
843 *alt_encoding = info.encoding;
844 return r;
845}
846
6648cd46
VS
847bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
848 const wxString& facename)
849{
850 wxNativeEncodingInfo info;
62ea506e 851
551fe3a6 852 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
853 {
854 info.facename = facename;
855 return wxTestFontEncoding(info);
856 }
3ca6a5f0
BP
857
858 return FALSE;
6648cd46 859}
f6bcfd97
BP
860
861#endif // wxUSE_GUI
1e6feb95
VZ
862
863#endif // wxUSE_FONTMAP