more DBCS-related changes (patch 481898)
[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 switch ( value )
569 {
570 case 932:
571 encoding = wxFONTENCODING_CP932;
572 break;
573
574 case 936:
575 encoding = wxFONTENCODING_CP936;
576 break;
577
578 case 949:
579 encoding = wxFONTENCODING_CP949;
580 break;
581
582 case 950:
583 encoding = wxFONTENCODING_CP950;
584 break;
585 }
586 }
587 }
588 }
589 //else: unknown
590 }
591
592 #if wxUSE_GUI
593 // if still no luck, ask the user - unless disabled
594 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
595 {
596 // prepare the dialog data
597
598 // the dialog title
599 wxString title(m_titleDialog);
600 if ( !title )
601 title << wxTheApp->GetAppName() << _(": unknown charset");
602
603 // the message
604 wxString msg;
605 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());
606
607 // the list of choices
608 size_t count = WXSIZEOF(gs_encodingDescs);
609
610 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
611 wxT("inconsitency detected - forgot to update one of the arrays?") );
612
613 wxString *encodingNamesTranslated = new wxString[count];
614
615 for ( size_t i = 0; i < count; i++ )
616 {
617 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
618 }
619
620 // the parent window
621 wxWindow *parent = m_windowParent;
622 if ( !parent )
623 parent = wxTheApp->GetTopWindow();
624
625 // do ask the user and get back the index in encodings table
626 int n = wxGetSingleChoiceIndex(msg, title,
627 count,
628 encodingNamesTranslated,
629 parent);
630
631 delete [] encodingNamesTranslated;
632
633 if ( n != -1 )
634 {
635 encoding = gs_encodings[n];
636 }
637
638 #if wxUSE_CONFIG
639 // save the result in the config now
640 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
641 {
642 wxConfigBase *config = GetConfig();
643
644 // remember the alt encoding for this charset - or remember that
645 // we don't know it
646 long value = n == -1 ? wxFONTENCODING_UNKNOWN : (long)encoding;
647 if ( !config->Write(charset, value) )
648 {
649 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
650 }
651
652 RestorePath(pathOld);
653 }
654 #endif // wxUSE_CONFIG
655 }
656 #endif // wxUSE_GUI
657
658 return encoding;
659 }
660
661 // ----------------------------------------------------------------------------
662 // support for unknown encodings: we maintain a map between the
663 // (platform-specific) strings identifying them and our wxFontEncodings they
664 // correspond to which is used by GetFontForEncoding() function
665 // ----------------------------------------------------------------------------
666
667 #if wxUSE_GUI
668
669 bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
670 wxFontEncoding encReplacement,
671 wxNativeEncodingInfo *info)
672 {
673 if ( wxGetNativeFontEncoding(encReplacement, info) &&
674 wxTestFontEncoding(*info) )
675 {
676 #if wxUSE_CONFIG
677 // remember the mapping in the config
678 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
679
680 if ( path.IsOk() )
681 {
682 GetConfig()->Write(configEntry, info->ToString());
683 }
684 #endif // wxUSE_CONFIG
685 return TRUE;
686 }
687
688 return FALSE;
689 }
690
691 #if wxUSE_GUI
692 class ReentrancyBlocker
693 {
694 public:
695 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
696 ~ReentrancyBlocker() { m_b = FALSE; }
697
698 private:
699 bool& m_b;
700 };
701 #endif
702
703 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
704 wxNativeEncodingInfo *info,
705 const wxString& facename,
706 bool interactive)
707 {
708 #if wxUSE_GUI
709 // we need a flag to prevent infinite recursion which happens, for
710 // example, when GetAltForEncoding() is called from an OnPaint() handler:
711 // in this case, wxYield() which is called from wxMessageBox() we use here
712 // will lead to another call of OnPaint() and hence to another call of
713 // GetAltForEncoding() - and it is impossible to catch this from the user
714 // code because we are called from wxFont ctor implicitly.
715
716 // assume we're always called from the main thread, so that it is safe to
717 // use a static var
718 static bool s_inGetAltForEncoding = FALSE;
719
720 if ( interactive && s_inGetAltForEncoding )
721 return FALSE;
722
723 ReentrancyBlocker blocker(s_inGetAltForEncoding);
724 #endif // wxUSE_GUI
725
726 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
727
728 info->facename = facename;
729
730 if ( encoding == wxFONTENCODING_DEFAULT )
731 {
732 encoding = wxFont::GetDefaultEncoding();
733 }
734
735 // if we failed to load the system default encoding, something is really
736 // wrong and we'd better stop now - otherwise we will go into endless
737 // recursion trying to create the font in the msg box with the error
738 // message
739 if ( encoding == wxFONTENCODING_SYSTEM )
740 {
741 wxFatalError(_("can't load any font, aborting"));
742
743 // wxFatalError doesn't return
744 }
745
746 wxString configEntry,
747 encName = GetEncodingName(encoding);
748 if ( !!facename )
749 {
750 configEntry = facename + _T("_");
751 }
752 configEntry += encName;
753
754 #if wxUSE_CONFIG
755 // do we have a font spec for this encoding?
756 wxString pathOld;
757 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
758 {
759 wxConfigBase *config = GetConfig();
760
761 wxString fontinfo = config->Read(configEntry);
762
763 RestorePath(pathOld);
764
765 // this special value means that we don't know of fonts for this
766 // encoding but, moreover, have already asked the user as well and he
767 // didn't specify any font neither
768 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
769 {
770 interactive = FALSE;
771 }
772 else // use the info entered the last time
773 {
774 if ( !!fontinfo && !!facename )
775 {
776 // we tried to find a match with facename - now try without it
777 fontinfo = config->Read(encName);
778 }
779
780 if ( !!fontinfo )
781 {
782 if ( info->FromString(fontinfo) )
783 {
784 if ( wxTestFontEncoding(*info) )
785 {
786 // ok, got something
787 return TRUE;
788 }
789 //else: no such fonts, look for something else
790 // (should we erase the outdated value?)
791 }
792 else
793 {
794 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
795 fontinfo.c_str());
796 }
797 }
798 //else: there is no information in config about this encoding
799 }
800 }
801 #endif // wxUSE_CONFIG
802
803 // ask the user
804 #if wxUSE_FONTDLG
805 if ( interactive )
806 {
807 wxString title(m_titleDialog);
808 if ( !title )
809 title << wxTheApp->GetAppName() << _(": unknown encoding");
810
811 // the message
812 wxString msg;
813 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)?"),
814 GetEncodingDescription(encoding).c_str());
815
816 wxWindow *parent = m_windowParent;
817 if ( !parent )
818 parent = wxTheApp->GetTopWindow();
819
820 if ( wxMessageBox(msg, title,
821 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
822 {
823 wxFontData data;
824 data.SetEncoding(encoding);
825 data.EncodingInfo() = *info;
826 wxFontDialog dialog(parent, &data);
827 if ( dialog.ShowModal() == wxID_OK )
828 {
829 wxFontData retData = dialog.GetFontData();
830 wxFont font = retData.GetChosenFont();
831
832 *info = retData.EncodingInfo();
833 info -> encoding = retData.GetEncoding();
834
835 #if wxUSE_CONFIG
836 // remember this in the config
837 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
838 {
839 GetConfig()->Write(configEntry, info->ToString());
840
841 RestorePath(pathOld);
842 }
843 #endif // wxUSE_CONFIG
844
845 return TRUE;
846 }
847 //else: the user canceled the font selection dialog
848 }
849 else
850 {
851 // the user doesn't want to select a font for this encoding,
852 // remember it to avoid asking the same question again later
853 #if wxUSE_CONFIG
854 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
855 {
856 GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK);
857
858 RestorePath(pathOld);
859 }
860 #endif // wxUSE_CONFIG
861 }
862 }
863 //else: we're in non-interactive mode
864 #endif // wxUSE_FONTDLG
865
866 // now try the default mappings:
867 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
868 size_t count = equiv.GetCount();
869 if ( count )
870 {
871 for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
872 {
873 if ( TestAltEncoding(configEntry, equiv[i], info) )
874 return TRUE;
875 }
876 }
877
878 return FALSE;
879 }
880
881 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
882 wxFontEncoding *alt_encoding,
883 const wxString& facename,
884 bool interactive)
885 {
886 wxNativeEncodingInfo info;
887 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
888 *alt_encoding = info.encoding;
889 return r;
890 }
891
892 bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
893 const wxString& facename)
894 {
895 wxNativeEncodingInfo info;
896
897 if (wxGetNativeFontEncoding(encoding, &info))
898 {
899 info.facename = facename;
900 return wxTestFontEncoding(info);
901 }
902
903 return FALSE;
904 }
905
906 #endif // wxUSE_GUI
907
908 #endif // wxUSE_FONTMAP