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