]> git.saurik.com Git - wxWidgets.git/blob - src/common/fontmap.cpp
speed up font list processing
[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 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
402
403 // we're going to modify it, make a copy
404 wxString cs = charset;
405
406 #if wxUSE_CONFIG
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 {
423 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
424 value, charset.c_str());
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 }
443 #endif
444
445 // if didn't find it there, try to recognize it ourselves
446 if ( encoding == wxFONTENCODING_SYSTEM )
447 {
448 // trim any spaces
449 cs.Trim(TRUE);
450 cs.Trim(FALSE);
451
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
461 cs.MakeUpper();
462
463 if ( !cs || cs == wxT("US-ASCII") )
464 {
465 encoding = wxFONTENCODING_DEFAULT;
466 }
467 else if ( cs == wxT("UTF-7") )
468 {
469 encoding = wxFONTENCODING_UTF7;
470 }
471 else if ( cs == wxT("UTF-8") )
472 {
473 encoding = wxFONTENCODING_UTF8;
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
482 encoding = wxFONTENCODING_KOI8;
483 }
484 else if ( cs.Left(3) == wxT("ISO") )
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;
489 if ( *p == wxT('-') )
490 p++;
491
492 unsigned int value;
493 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
494 {
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) )
500 {
501 // it's a valid ISO8859 encoding
502 value += wxFONTENCODING_ISO8859_1;
503 encoding = (wxFontEncoding)value;
504 }
505 }
506 }
507 else // check for Windows charsets
508 {
509 size_t len;
510 if ( cs.Left(7) == wxT("WINDOWS") )
511 {
512 len = 7;
513 }
514 else if ( cs.Left(2) == wxT("CP") )
515 {
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 )
531 {
532 if ( value >= 1250 )
533 {
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 }
542 }
543 }
544 }
545 }
546 //else: unknown
547 }
548
549 #if wxUSE_GUI
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;
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());
563
564 // the list of choices
565 size_t count = WXSIZEOF(gs_encodingDescs);
566
567 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
568 wxT("inconsitency detected - forgot to update one of the arrays?") );
569
570 wxString *encodingNamesTranslated = new wxString[count];
571
572 for ( size_t i = 0; i < count; i++ )
573 {
574 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
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 {
592 encoding = gs_encodings[n];
593
594 #if wxUSE_CONFIG
595 // save the result in the config now
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 {
603 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
604 }
605
606 RestorePath(pathOld);
607 }
608 #endif // wxUSE_CONFIG
609 }
610 //else: cancelled
611 }
612 #endif // wxUSE_GUI
613
614 return encoding;
615 }
616
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
623 #if wxUSE_GUI
624
625 bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
626 wxFontEncoding encReplacement,
627 wxNativeEncodingInfo *info)
628 {
629 if ( wxGetNativeFontEncoding(encReplacement, info) &&
630 wxTestFontEncoding(*info) )
631 {
632 #if wxUSE_CONFIG
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 }
640 #endif // wxUSE_CONFIG
641 return TRUE;
642 }
643
644 return FALSE;
645 }
646
647 #if wxUSE_GUI
648 class ReentrancyBlocker
649 {
650 public:
651 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
652 ~ReentrancyBlocker() { m_b = FALSE; }
653
654 private:
655 bool& m_b;
656 };
657 #endif
658
659 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
660 wxNativeEncodingInfo *info,
661 const wxString& facename,
662 bool interactive)
663 {
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
682 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
683
684 info->facename = facename;
685
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
702 wxString configEntry, encName = GetEncodingName(encoding);
703 if ( !!facename )
704 {
705 configEntry = facename + _T("_");
706 }
707 configEntry += encName;
708
709 #if wxUSE_CONFIG
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
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 )
724 {
725 interactive = FALSE;
726 }
727 else // use the info entered the last time
728 {
729 if ( !!fontinfo && !!facename )
730 {
731 // we tried to find a match with facename - now try without it
732 fontinfo = config->Read(encName);
733 }
734
735 if ( !!fontinfo )
736 {
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 }
752 }
753 //else: there is no information in config about this encoding
754 }
755 }
756 #endif // wxUSE_CONFIG
757
758 // ask the user
759 #if wxUSE_FONTDLG
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;
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)?"),
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
787 *info = retData.EncodingInfo();
788 info -> encoding = retData.GetEncoding();
789
790 #if wxUSE_CONFIG
791 // remember this in the config
792 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
793 {
794 GetConfig()->Write(configEntry, info->ToString());
795
796 RestorePath(pathOld);
797 }
798 #endif // wxUSE_CONFIG
799
800 return TRUE;
801 }
802 //else: the user canceled the font selection dialog
803 }
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 }
817 }
818 //else: we're in non-interactive mode
819 #endif // wxUSE_FONTDLG
820
821 // now try the default mappings:
822 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
823 size_t count = equiv.GetCount();
824 if ( count )
825 {
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 }
831 }
832
833 return FALSE;
834 }
835
836 bool 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
847 bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
848 const wxString& facename)
849 {
850 wxNativeEncodingInfo info;
851
852 if (wxGetNativeFontEncoding(encoding, &info))
853 {
854 info.facename = facename;
855 return wxTestFontEncoding(info);
856 }
857
858 return FALSE;
859 }
860
861 #endif // wxUSE_GUI
862
863 #endif // wxUSE_FONTMAP