remember unknown charsets in the config too
[wxWidgets.git] / src / common / fontmap.cpp
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
31 #if wxUSE_FONTMAP
32
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"
40
41 #if wxUSE_CONFIG
42 #include "wx/config.h"
43 #include "wx/memconf.h"
44 #endif
45
46 #if wxUSE_GUI
47 #include "wx/fontutil.h"
48 #include "wx/msgdlg.h"
49 #include "wx/fontdlg.h"
50 #include "wx/choicdlg.h"
51 #endif // wxUSE_GUI
52
53 #include "wx/encconv.h"
54
55 // ----------------------------------------------------------------------------
56 // constants
57 // ----------------------------------------------------------------------------
58
59 // the config paths we use
60 #if wxUSE_CONFIG
61 static const wxChar* FONTMAPPER_ROOT_PATH = wxT("/wxWindows/FontMapper");
62 static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
63 static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
64
65 // we only ask questions in GUI mode
66 #if wxUSE_GUI
67 static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
68 static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none");
69 #endif // wxUSE_GUI
70 #endif // wxUSE_CONFIG
71
72 // encodings supported by GetEncodingDescription
73 static 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,
99 wxFONTENCODING_CP437,
100 wxFONTENCODING_UTF7,
101 wxFONTENCODING_UTF8,
102 };
103
104 // the descriptions for them
105 static const wxChar* gs_encodingDescs[] =
106 {
107 wxTRANSLATE( "Western European (ISO-8859-1)" ),
108 wxTRANSLATE( "Central European (ISO-8859-2)" ),
109 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
110 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
111 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
112 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
113 wxTRANSLATE( "Greek (ISO-8859-7)" ),
114 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
115 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
116 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
117 wxTRANSLATE( "Thai (ISO-8859-11)" ),
118 wxTRANSLATE( "Indian (ISO-8859-12)" ),
119 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
120 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
121 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
122 wxTRANSLATE( "KOI8-R" ),
123 wxTRANSLATE( "Windows Central European (CP 1250)" ),
124 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
125 wxTRANSLATE( "Windows Western European (CP 1252)" ),
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)" ),
131 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
132 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
133 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
134 };
135
136 // and the internal names
137 static const wxChar* gs_encodingNames[] =
138 {
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" ),
154 wxT( "koi8-r" ),
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" ),
164 wxT( "utf7" ),
165 wxT( "utf8" ),
166 };
167
168 // ----------------------------------------------------------------------------
169 // global data
170 // ----------------------------------------------------------------------------
171
172 // private object
173 static wxFontMapper gs_fontMapper;
174
175 // and public pointer
176 wxFontMapper * wxTheFontMapper = &gs_fontMapper;
177
178 // ----------------------------------------------------------------------------
179 // private classes
180 // ----------------------------------------------------------------------------
181
182 // change the config path during the lifetime of this object
183 class wxFontMapperPathChanger
184 {
185 public:
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
200 private:
201 wxFontMapper *m_fontMapper;
202 bool m_ok;
203 wxString m_pathOld;
204 };
205
206 // ============================================================================
207 // implementation
208 // ============================================================================
209
210 // ----------------------------------------------------------------------------
211 // ctor and dtor
212 // ----------------------------------------------------------------------------
213
214 wxFontMapper::wxFontMapper()
215 {
216 #if wxUSE_CONFIG
217 m_config = NULL;
218 m_configIsDummy = FALSE;
219 #endif // wxUSE_CONFIG
220
221 #if wxUSE_GUI
222 m_windowParent = NULL;
223 #endif // wxUSE_GUI
224 }
225
226 wxFontMapper::~wxFontMapper()
227 {
228 }
229
230 // ----------------------------------------------------------------------------
231 // customisation
232 // ----------------------------------------------------------------------------
233
234 #if wxUSE_CONFIG
235
236 /* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
237 {
238 return FONTMAPPER_ROOT_PATH;
239 }
240
241 void wxFontMapper::SetConfigPath(const wxString& prefix)
242 {
243 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
244 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
245
246 m_configRootPath = prefix;
247 }
248
249 // ----------------------------------------------------------------------------
250 // get config object and path for it
251 // ----------------------------------------------------------------------------
252
253 wxConfigBase *wxFontMapper::GetConfig()
254 {
255 if ( !m_config )
256 {
257 // try the default
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;
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())
273 }
274 }
275
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
289 return m_config;
290 }
291
292 const wxString& wxFontMapper::GetConfigPath()
293 {
294 if ( !m_configRootPath )
295 {
296 // use the default
297 m_configRootPath = GetDefaultConfigPath();
298 }
299
300 return m_configRootPath;
301 }
302 #endif
303
304 bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
305 {
306 #if wxUSE_CONFIG
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),
320 wxT("should be a relative path") );
321
322 path += pathNew;
323
324 config->SetPath(path);
325
326 return TRUE;
327 #else
328 return FALSE;
329 #endif
330 }
331
332 void wxFontMapper::RestorePath(const wxString& pathOld)
333 {
334 #if wxUSE_CONFIG
335 GetConfig()->SetPath(pathOld);
336 #else
337 #endif
338 }
339
340 // ----------------------------------------------------------------------------
341 // charset/encoding correspondence
342 // ----------------------------------------------------------------------------
343
344 /* static */
345 wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
346 {
347 if ( encoding == wxFONTENCODING_DEFAULT )
348 {
349 return _("Default encoding");
350 }
351
352 size_t count = WXSIZEOF(gs_encodingDescs);
353
354 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
355 wxT("inconsitency detected - forgot to update one of the arrays?") );
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 */
372 wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
373 {
374 if ( encoding == wxFONTENCODING_DEFAULT )
375 {
376 return _("default");
377 }
378
379 size_t count = WXSIZEOF(gs_encodingNames);
380
381 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
382 wxT("inconsistency detected - forgot to update one of the arrays?") );
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
398 wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
399 bool interactive)
400 {
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
407 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
408
409 // we're going to modify it, make a copy
410 wxString cs = charset;
411
412 #if wxUSE_CONFIG
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 {
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
429 if ( value >= 0 && value <= wxFONTENCODING_MAX )
430 {
431 encoding = (wxFontEncoding)value;
432 }
433 else
434 {
435 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
436 value, charset.c_str());
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 }
455 #endif // wxUSE_CONFIG
456
457 // if didn't find it there, try to recognize it ourselves
458 if ( encoding == wxFONTENCODING_SYSTEM )
459 {
460 // trim any spaces
461 cs.Trim(TRUE);
462 cs.Trim(FALSE);
463
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
473 cs.MakeUpper();
474
475 if ( !cs || cs == wxT("US-ASCII") )
476 {
477 encoding = wxFONTENCODING_DEFAULT;
478 }
479 else if ( cs == wxT("UTF-7") )
480 {
481 encoding = wxFONTENCODING_UTF7;
482 }
483 else if ( cs == wxT("UTF-8") )
484 {
485 encoding = wxFONTENCODING_UTF8;
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
494 encoding = wxFONTENCODING_KOI8;
495 }
496 else if ( cs.Left(3) == wxT("ISO") )
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;
501 if ( *p == wxT('-') )
502 p++;
503
504 unsigned int value;
505 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
506 {
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) )
512 {
513 // it's a valid ISO8859 encoding
514 value += wxFONTENCODING_ISO8859_1;
515 encoding = (wxFontEncoding)value;
516 }
517 }
518 }
519 else // check for Windows charsets
520 {
521 size_t len;
522 if ( cs.Left(7) == wxT("WINDOWS") )
523 {
524 len = 7;
525 }
526 else if ( cs.Left(2) == wxT("CP") )
527 {
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 )
543 {
544 if ( value >= 1250 )
545 {
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 }
554 }
555 }
556 }
557 }
558 //else: unknown
559 }
560
561 #if wxUSE_GUI
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;
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());
575
576 // the list of choices
577 size_t count = WXSIZEOF(gs_encodingDescs);
578
579 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
580 wxT("inconsitency detected - forgot to update one of the arrays?") );
581
582 wxString *encodingNamesTranslated = new wxString[count];
583
584 for ( size_t i = 0; i < count; i++ )
585 {
586 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
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 {
604 encoding = gs_encodings[n];
605 }
606
607 #if wxUSE_CONFIG
608 // save the result in the config now
609 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
610 {
611 wxConfigBase *config = GetConfig();
612
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());
619 }
620
621 RestorePath(pathOld);
622 }
623 #endif // wxUSE_CONFIG
624 }
625 #endif // wxUSE_GUI
626
627 return encoding;
628 }
629
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
636 #if wxUSE_GUI
637
638 bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
639 wxFontEncoding encReplacement,
640 wxNativeEncodingInfo *info)
641 {
642 if ( wxGetNativeFontEncoding(encReplacement, info) &&
643 wxTestFontEncoding(*info) )
644 {
645 #if wxUSE_CONFIG
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 }
653 #endif // wxUSE_CONFIG
654 return TRUE;
655 }
656
657 return FALSE;
658 }
659
660 #if wxUSE_GUI
661 class ReentrancyBlocker
662 {
663 public:
664 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
665 ~ReentrancyBlocker() { m_b = FALSE; }
666
667 private:
668 bool& m_b;
669 };
670 #endif
671
672 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
673 wxNativeEncodingInfo *info,
674 const wxString& facename,
675 bool interactive)
676 {
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
695 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
696
697 info->facename = facename;
698
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
715 wxString configEntry, encName = GetEncodingName(encoding);
716 if ( !!facename )
717 {
718 configEntry = facename + _T("_");
719 }
720 configEntry += encName;
721
722 #if wxUSE_CONFIG
723 // do we have a font spec for this encoding?
724 wxString pathOld;
725 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
726 {
727 wxConfigBase *config = GetConfig();
728
729 wxString fontinfo = config->Read(configEntry);
730
731 RestorePath(pathOld);
732
733 // this special value means that we don't know of fonts for this
734 // encoding but, moreover, have already asked the user as well and he
735 // didn't specify any font neither
736 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
737 {
738 interactive = FALSE;
739 }
740 else // use the info entered the last time
741 {
742 if ( !!fontinfo && !!facename )
743 {
744 // we tried to find a match with facename - now try without it
745 fontinfo = config->Read(encName);
746 }
747
748 if ( !!fontinfo )
749 {
750 if ( info->FromString(fontinfo) )
751 {
752 if ( wxTestFontEncoding(*info) )
753 {
754 // ok, got something
755 return TRUE;
756 }
757 //else: no such fonts, look for something else
758 // (should we erase the outdated value?)
759 }
760 else
761 {
762 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
763 fontinfo.c_str());
764 }
765 }
766 //else: there is no information in config about this encoding
767 }
768 }
769 #endif // wxUSE_CONFIG
770
771 // ask the user
772 #if wxUSE_FONTDLG
773 if ( interactive )
774 {
775 wxString title(m_titleDialog);
776 if ( !title )
777 title << wxTheApp->GetAppName() << _(": unknown encoding");
778
779 // the message
780 wxString msg;
781 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)?"),
782 GetEncodingDescription(encoding).c_str());
783
784 wxWindow *parent = m_windowParent;
785 if ( !parent )
786 parent = wxTheApp->GetTopWindow();
787
788 if ( wxMessageBox(msg, title,
789 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
790 {
791 wxFontData data;
792 data.SetEncoding(encoding);
793 data.EncodingInfo() = *info;
794 wxFontDialog dialog(parent, &data);
795 if ( dialog.ShowModal() == wxID_OK )
796 {
797 wxFontData retData = dialog.GetFontData();
798 wxFont font = retData.GetChosenFont();
799
800 *info = retData.EncodingInfo();
801 info -> encoding = retData.GetEncoding();
802
803 #if wxUSE_CONFIG
804 // remember this in the config
805 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
806 {
807 GetConfig()->Write(configEntry, info->ToString());
808
809 RestorePath(pathOld);
810 }
811 #endif // wxUSE_CONFIG
812
813 return TRUE;
814 }
815 //else: the user canceled the font selection dialog
816 }
817 else
818 {
819 // the user doesn't want to select a font for this encoding,
820 // remember it to avoid asking the same question again later
821 #if wxUSE_CONFIG
822 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
823 {
824 GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK);
825
826 RestorePath(pathOld);
827 }
828 #endif // wxUSE_CONFIG
829 }
830 }
831 //else: we're in non-interactive mode
832 #endif // wxUSE_FONTDLG
833
834 // now try the default mappings:
835 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
836 size_t count = equiv.GetCount();
837 if ( count )
838 {
839 for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
840 {
841 if ( TestAltEncoding(configEntry, equiv[i], info) )
842 return TRUE;
843 }
844 }
845
846 return FALSE;
847 }
848
849 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
850 wxFontEncoding *alt_encoding,
851 const wxString& facename,
852 bool interactive)
853 {
854 wxNativeEncodingInfo info;
855 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
856 *alt_encoding = info.encoding;
857 return r;
858 }
859
860 bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
861 const wxString& facename)
862 {
863 wxNativeEncodingInfo info;
864
865 if (wxGetNativeFontEncoding(encoding, &info))
866 {
867 info.facename = facename;
868 return wxTestFontEncoding(info);
869 }
870
871 return FALSE;
872 }
873
874 #endif // wxUSE_GUI
875
876 #endif // wxUSE_FONTMAP