]> git.saurik.com Git - wxWidgets.git/blob - src/common/fontmap.cpp
wxRegion fixes (off by one)
[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 (these are not translated on purpose!)
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( "utf-7" ),
165 wxT( "utf-8" ),
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 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,
716 encName = GetEncodingName(encoding);
717 if ( !!facename )
718 {
719 configEntry = facename + _T("_");
720 }
721 configEntry += encName;
722
723 #if wxUSE_CONFIG
724 // do we have a font spec for this encoding?
725 wxString pathOld;
726 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
727 {
728 wxConfigBase *config = GetConfig();
729
730 wxString fontinfo = config->Read(configEntry);
731
732 RestorePath(pathOld);
733
734 // this special value means that we don't know of fonts for this
735 // encoding but, moreover, have already asked the user as well and he
736 // didn't specify any font neither
737 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
738 {
739 interactive = FALSE;
740 }
741 else // use the info entered the last time
742 {
743 if ( !!fontinfo && !!facename )
744 {
745 // we tried to find a match with facename - now try without it
746 fontinfo = config->Read(encName);
747 }
748
749 if ( !!fontinfo )
750 {
751 if ( info->FromString(fontinfo) )
752 {
753 if ( wxTestFontEncoding(*info) )
754 {
755 // ok, got something
756 return TRUE;
757 }
758 //else: no such fonts, look for something else
759 // (should we erase the outdated value?)
760 }
761 else
762 {
763 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
764 fontinfo.c_str());
765 }
766 }
767 //else: there is no information in config about this encoding
768 }
769 }
770 #endif // wxUSE_CONFIG
771
772 // ask the user
773 #if wxUSE_FONTDLG
774 if ( interactive )
775 {
776 wxString title(m_titleDialog);
777 if ( !title )
778 title << wxTheApp->GetAppName() << _(": unknown encoding");
779
780 // the message
781 wxString msg;
782 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)?"),
783 GetEncodingDescription(encoding).c_str());
784
785 wxWindow *parent = m_windowParent;
786 if ( !parent )
787 parent = wxTheApp->GetTopWindow();
788
789 if ( wxMessageBox(msg, title,
790 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
791 {
792 wxFontData data;
793 data.SetEncoding(encoding);
794 data.EncodingInfo() = *info;
795 wxFontDialog dialog(parent, &data);
796 if ( dialog.ShowModal() == wxID_OK )
797 {
798 wxFontData retData = dialog.GetFontData();
799 wxFont font = retData.GetChosenFont();
800
801 *info = retData.EncodingInfo();
802 info -> encoding = retData.GetEncoding();
803
804 #if wxUSE_CONFIG
805 // remember this in the config
806 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
807 {
808 GetConfig()->Write(configEntry, info->ToString());
809
810 RestorePath(pathOld);
811 }
812 #endif // wxUSE_CONFIG
813
814 return TRUE;
815 }
816 //else: the user canceled the font selection dialog
817 }
818 else
819 {
820 // the user doesn't want to select a font for this encoding,
821 // remember it to avoid asking the same question again later
822 #if wxUSE_CONFIG
823 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
824 {
825 GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK);
826
827 RestorePath(pathOld);
828 }
829 #endif // wxUSE_CONFIG
830 }
831 }
832 //else: we're in non-interactive mode
833 #endif // wxUSE_FONTDLG
834
835 // now try the default mappings:
836 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
837 size_t count = equiv.GetCount();
838 if ( count )
839 {
840 for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
841 {
842 if ( TestAltEncoding(configEntry, equiv[i], info) )
843 return TRUE;
844 }
845 }
846
847 return FALSE;
848 }
849
850 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
851 wxFontEncoding *alt_encoding,
852 const wxString& facename,
853 bool interactive)
854 {
855 wxNativeEncodingInfo info;
856 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
857 *alt_encoding = info.encoding;
858 return r;
859 }
860
861 bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
862 const wxString& facename)
863 {
864 wxNativeEncodingInfo info;
865
866 if (wxGetNativeFontEncoding(encoding, &info))
867 {
868 info.facename = facename;
869 return wxTestFontEncoding(info);
870 }
871
872 return FALSE;
873 }
874
875 #endif // wxUSE_GUI
876
877 #endif // wxUSE_FONTMAP