]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
Committing in .
[wxWidgets.git] / src / common / fontmap.cpp
CommitLineData
3c1866e8
VZ
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
1e6feb95
VZ
31#if wxUSE_FONTMAP
32
3c1866e8
VZ
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"
7beba2fc 40
f6bcfd97
BP
41#if wxUSE_CONFIG
42 #include "wx/config.h"
43 #include "wx/memconf.h"
44#endif
45
46#if wxUSE_GUI
70184095 47 #include "wx/fontutil.h"
f6bcfd97
BP
48 #include "wx/msgdlg.h"
49 #include "wx/fontdlg.h"
50 #include "wx/choicdlg.h"
51#endif // wxUSE_GUI
52
82545b58 53#include "wx/encconv.h"
3c1866e8
VZ
54
55// ----------------------------------------------------------------------------
56// constants
57// ----------------------------------------------------------------------------
58
59// the config paths we use
1e6feb95 60#if wxUSE_CONFIG
3ca6a5f0 61static const wxChar* FONTMAPPER_ROOT_PATH = wxT("/wxWindows/FontMapper");
511f273f
OK
62static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
63static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
6603907d
VZ
64
65// we only ask questions in GUI mode
f6bcfd97
BP
66#if wxUSE_GUI
67 static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
6603907d 68 static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none");
f6bcfd97 69#endif // wxUSE_GUI
1e6feb95 70#endif // wxUSE_CONFIG
7beba2fc
VZ
71
72// encodings supported by GetEncodingDescription
73static 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,
bc4e6fcd
VZ
91 wxFONTENCODING_CP932,
92 wxFONTENCODING_CP936,
93 wxFONTENCODING_CP949,
94 wxFONTENCODING_CP950,
7beba2fc
VZ
95 wxFONTENCODING_CP1250,
96 wxFONTENCODING_CP1251,
97 wxFONTENCODING_CP1252,
98 wxFONTENCODING_CP1253,
99 wxFONTENCODING_CP1254,
100 wxFONTENCODING_CP1255,
101 wxFONTENCODING_CP1256,
102 wxFONTENCODING_CP1257,
f6bcfd97 103 wxFONTENCODING_CP437,
bb84929e
VZ
104 wxFONTENCODING_UTF7,
105 wxFONTENCODING_UTF8,
7beba2fc
VZ
106};
107
108// the descriptions for them
109static const wxChar* gs_encodingDescs[] =
110{
03424b1b
VZ
111 wxTRANSLATE( "Western European (ISO-8859-1)" ),
112 wxTRANSLATE( "Central European (ISO-8859-2)" ),
7beba2fc 113 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
f6bcfd97 114 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
03424b1b 115 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
7beba2fc
VZ
116 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
117 wxTRANSLATE( "Greek (ISO-8859-7)" ),
118 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
119 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
f6bcfd97 120 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
7beba2fc 121 wxTRANSLATE( "Thai (ISO-8859-11)" ),
80a24267 122 wxTRANSLATE( "Indian (ISO-8859-12)" ),
f6bcfd97 123 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
80a24267 124 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
03424b1b 125 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
7beba2fc 126 wxTRANSLATE( "KOI8-R" ),
bc4e6fcd 127 wxTRANSLATE( "Windows Japanese (CP 932)" ),
62b3ca69 128 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
bc4e6fcd
VZ
129 wxTRANSLATE( "Windows Korean (CP 949)" ),
130 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
80a24267 131 wxTRANSLATE( "Windows Central European (CP 1250)" ),
7beba2fc 132 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
80a24267 133 wxTRANSLATE( "Windows Western European (CP 1252)" ),
7beba2fc
VZ
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)" ),
f6bcfd97 139 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
bb84929e
VZ
140 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
141 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
7beba2fc
VZ
142};
143
a4a6984d 144// and the internal names (these are not translated on purpose!)
7beba2fc
VZ
145static const wxChar* gs_encodingNames[] =
146{
ecffe992
VS
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" ),
511f273f 162 wxT( "koi8-r" ),
bc4e6fcd
VZ
163 wxT( "windows-932" ),
164 wxT( "windows-936" ),
165 wxT( "windows-949" ),
166 wxT( "windows-950" ),
551fe3a6
VZ
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" ),
5707316c
VS
176 wxT( "utf-7" ),
177 wxT( "utf-8" ),
7beba2fc
VZ
178};
179
180// ----------------------------------------------------------------------------
181// global data
182// ----------------------------------------------------------------------------
183
184// private object
185static wxFontMapper gs_fontMapper;
186
187// and public pointer
b40b0f5b 188wxFontMapper * wxTheFontMapper = &gs_fontMapper;
7beba2fc
VZ
189
190// ----------------------------------------------------------------------------
191// private classes
192// ----------------------------------------------------------------------------
193
194// change the config path during the lifetime of this object
195class wxFontMapperPathChanger
196{
197public:
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
212private:
213 wxFontMapper *m_fontMapper;
214 bool m_ok;
215 wxString m_pathOld;
216};
3c1866e8
VZ
217
218// ============================================================================
219// implementation
220// ============================================================================
221
222// ----------------------------------------------------------------------------
223// ctor and dtor
224// ----------------------------------------------------------------------------
225
226wxFontMapper::wxFontMapper()
227{
f6bcfd97 228#if wxUSE_CONFIG
3c1866e8 229 m_config = NULL;
5fe83549 230 m_configIsDummy = FALSE;
f6bcfd97
BP
231#endif // wxUSE_CONFIG
232
233#if wxUSE_GUI
3c1866e8 234 m_windowParent = NULL;
f6bcfd97 235#endif // wxUSE_GUI
3c1866e8
VZ
236}
237
238wxFontMapper::~wxFontMapper()
239{
240}
241
242// ----------------------------------------------------------------------------
243// customisation
244// ----------------------------------------------------------------------------
245
f6bcfd97
BP
246#if wxUSE_CONFIG
247
3c1866e8
VZ
248/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
249{
250 return FONTMAPPER_ROOT_PATH;
251}
252
253void wxFontMapper::SetConfigPath(const wxString& prefix)
254{
255 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
fbdcff4a 256 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
3c1866e8
VZ
257
258 m_configRootPath = prefix;
259}
260
3c1866e8
VZ
261// ----------------------------------------------------------------------------
262// get config object and path for it
263// ----------------------------------------------------------------------------
264
265wxConfigBase *wxFontMapper::GetConfig()
266{
267 if ( !m_config )
268 {
269 // try the default
1d910ac1
VZ
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;
5fe83549
VS
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())
1d910ac1 285 }
3c1866e8
VZ
286 }
287
5fe83549
VS
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
c7821f94
VZ
296 // either doesn't use wxConfig at all or creates wxConfig object in
297 // wxApp::OnInit(), before any real interaction with the user takes
5fe83549
VS
298 // place...
299 }
300
3c1866e8
VZ
301 return m_config;
302}
303
304const wxString& wxFontMapper::GetConfigPath()
305{
306 if ( !m_configRootPath )
307 {
308 // use the default
309 m_configRootPath = GetDefaultConfigPath();
310 }
311
312 return m_configRootPath;
313}
f6bcfd97 314#endif
3c1866e8
VZ
315
316bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
317{
f6bcfd97 318#if wxUSE_CONFIG
3c1866e8
VZ
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),
58c837a4 332 wxT("should be a relative path") );
3c1866e8
VZ
333
334 path += pathNew;
335
336 config->SetPath(path);
337
338 return TRUE;
f6bcfd97
BP
339#else
340 return FALSE;
341#endif
3c1866e8
VZ
342}
343
344void wxFontMapper::RestorePath(const wxString& pathOld)
345{
f6bcfd97 346#if wxUSE_CONFIG
3c1866e8 347 GetConfig()->SetPath(pathOld);
f6bcfd97
BP
348#else
349#endif
3c1866e8
VZ
350}
351
352// ----------------------------------------------------------------------------
353// charset/encoding correspondence
354// ----------------------------------------------------------------------------
355
7beba2fc
VZ
356/* static */
357wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
358{
551fe3a6
VZ
359 if ( encoding == wxFONTENCODING_DEFAULT )
360 {
361 return _("Default encoding");
362 }
363
7beba2fc
VZ
364 size_t count = WXSIZEOF(gs_encodingDescs);
365
366 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 367 wxT("inconsitency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
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 */
384wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
385{
551fe3a6
VZ
386 if ( encoding == wxFONTENCODING_DEFAULT )
387 {
388 return _("default");
389 }
390
7beba2fc
VZ
391 size_t count = WXSIZEOF(gs_encodingNames);
392
393 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 394 wxT("inconsistency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
395
396 for ( size_t i = 0; i < count; i++ )
397 {
398 if ( gs_encodings[i] == encoding )
399 {
a4a6984d 400 return gs_encodingNames[i];
7beba2fc
VZ
401 }
402 }
403
404 wxString str;
405 str.Printf(_("unknown-%d"), encoding);
406
407 return str;
408}
409
3c1866e8
VZ
410wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
411 bool interactive)
412{
3e7fb236
VZ
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
3c1866e8
VZ
419 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
420
421 // we're going to modify it, make a copy
422 wxString cs = charset;
423
f6bcfd97 424#if wxUSE_CONFIG
3c1866e8
VZ
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 {
3e7fb236
VZ
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
3c1866e8
VZ
441 if ( value >= 0 && value <= wxFONTENCODING_MAX )
442 {
443 encoding = (wxFontEncoding)value;
444 }
445 else
446 {
f6bcfd97 447 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 448 value, charset.c_str());
3c1866e8
VZ
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 }
3e7fb236 467#endif // wxUSE_CONFIG
3c1866e8 468
551fe3a6 469 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
470 if ( encoding == wxFONTENCODING_SYSTEM )
471 {
551fe3a6
VZ
472 // trim any spaces
473 cs.Trim(TRUE);
474 cs.Trim(FALSE);
475
3ca6a5f0
BP
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
3c1866e8
VZ
485 cs.MakeUpper();
486
58c837a4 487 if ( !cs || cs == wxT("US-ASCII") )
551fe3a6 488 {
3c1866e8 489 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 490 }
bb84929e 491 else if ( cs == wxT("UTF-7") )
551fe3a6 492 {
bb84929e 493 encoding = wxFONTENCODING_UTF7;
551fe3a6 494 }
bb84929e 495 else if ( cs == wxT("UTF-8") )
551fe3a6 496 {
bb84929e 497 encoding = wxFONTENCODING_UTF8;
551fe3a6
VZ
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
3c1866e8 506 encoding = wxFONTENCODING_KOI8;
551fe3a6 507 }
58c837a4 508 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
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;
58c837a4 513 if ( *p == wxT('-') )
3c1866e8
VZ
514 p++;
515
516 unsigned int value;
58c837a4 517 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 518 {
daaa6710
VZ
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) )
3c1866e8
VZ
524 {
525 // it's a valid ISO8859 encoding
daaa6710 526 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
527 encoding = (wxFontEncoding)value;
528 }
529 }
530 }
551fe3a6 531 else // check for Windows charsets
3c1866e8 532 {
551fe3a6
VZ
533 size_t len;
534 if ( cs.Left(7) == wxT("WINDOWS") )
535 {
536 len = 7;
537 }
538 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 539 {
551fe3a6
VZ
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 )
3c1866e8 555 {
551fe3a6 556 if ( value >= 1250 )
3c1866e8 557 {
551fe3a6
VZ
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 }
3c1866e8 566 }
c7821f94
VZ
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 }
3c1866e8
VZ
586 }
587 }
588 }
589 //else: unknown
590 }
591
f6bcfd97 592#if wxUSE_GUI
3c1866e8
VZ
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;
f6bcfd97 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());
3c1866e8
VZ
606
607 // the list of choices
7beba2fc
VZ
608 size_t count = WXSIZEOF(gs_encodingDescs);
609
610 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 611 wxT("inconsitency detected - forgot to update one of the arrays?") );
3c1866e8
VZ
612
613 wxString *encodingNamesTranslated = new wxString[count];
614
11c7d5b6 615 for ( size_t i = 0; i < count; i++ )
3c1866e8 616 {
11c7d5b6 617 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
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 {
7beba2fc 635 encoding = gs_encodings[n];
3e7fb236 636 }
1d910ac1 637
f6bcfd97
BP
638#if wxUSE_CONFIG
639 // save the result in the config now
3e7fb236
VZ
640 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
641 {
642 wxConfigBase *config = GetConfig();
1d910ac1 643
3e7fb236
VZ
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());
1d910ac1 650 }
3e7fb236
VZ
651
652 RestorePath(pathOld);
3c1866e8 653 }
3e7fb236 654#endif // wxUSE_CONFIG
3c1866e8 655 }
f6bcfd97 656#endif // wxUSE_GUI
3c1866e8
VZ
657
658 return encoding;
659}
660
7beba2fc
VZ
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
f6bcfd97
BP
667#if wxUSE_GUI
668
7beba2fc
VZ
669bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
670 wxFontEncoding encReplacement,
671 wxNativeEncodingInfo *info)
672{
673 if ( wxGetNativeFontEncoding(encReplacement, info) &&
674 wxTestFontEncoding(*info) )
675 {
f6bcfd97 676#if wxUSE_CONFIG
7beba2fc
VZ
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 }
f6bcfd97 684#endif // wxUSE_CONFIG
7beba2fc
VZ
685 return TRUE;
686 }
687
688 return FALSE;
689}
690
f6bcfd97
BP
691#if wxUSE_GUI
692class ReentrancyBlocker
693{
694public:
695 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
696 ~ReentrancyBlocker() { m_b = FALSE; }
697
698private:
699 bool& m_b;
700};
701#endif
702
7beba2fc
VZ
703bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
704 wxNativeEncodingInfo *info,
6648cd46 705 const wxString& facename,
7beba2fc
VZ
706 bool interactive)
707{
f6bcfd97
BP
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
58c837a4 726 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 727
6648cd46
VS
728 info->facename = facename;
729
97d3f0ee
VZ
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
a4a6984d
VZ
746 wxString configEntry,
747 encName = GetEncodingName(encoding);
1d910ac1
VZ
748 if ( !!facename )
749 {
750 configEntry = facename + _T("_");
751 }
752 configEntry += encName;
7beba2fc 753
f6bcfd97 754#if wxUSE_CONFIG
7beba2fc
VZ
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
6603907d
VZ
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 )
1d910ac1 769 {
6603907d 770 interactive = FALSE;
1d910ac1 771 }
6603907d 772 else // use the info entered the last time
7beba2fc 773 {
6603907d 774 if ( !!fontinfo && !!facename )
7beba2fc 775 {
6603907d
VZ
776 // we tried to find a match with facename - now try without it
777 fontinfo = config->Read(encName);
7beba2fc 778 }
6603907d
VZ
779
780 if ( !!fontinfo )
7beba2fc 781 {
6603907d
VZ
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 }
7beba2fc 797 }
6603907d 798 //else: there is no information in config about this encoding
7beba2fc
VZ
799 }
800 }
f6bcfd97 801#endif // wxUSE_CONFIG
7beba2fc
VZ
802
803 // ask the user
3379ed37 804#if wxUSE_FONTDLG
7beba2fc
VZ
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;
6603907d 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)?"),
7beba2fc
VZ
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
11c7d5b6 832 *info = retData.EncodingInfo();
551fe3a6 833 info -> encoding = retData.GetEncoding();
7beba2fc 834
f6bcfd97 835#if wxUSE_CONFIG
6603907d 836 // remember this in the config
7beba2fc
VZ
837 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
838 {
839 GetConfig()->Write(configEntry, info->ToString());
840
841 RestorePath(pathOld);
842 }
bb84929e 843#endif // wxUSE_CONFIG
7beba2fc
VZ
844
845 return TRUE;
846 }
847 //else: the user canceled the font selection dialog
848 }
6603907d
VZ
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 }
7beba2fc
VZ
862 }
863 //else: we're in non-interactive mode
3379ed37 864#endif // wxUSE_FONTDLG
7beba2fc 865
82545b58 866 // now try the default mappings:
82545b58 867 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
1d910ac1 868 size_t count = equiv.GetCount();
3ca6a5f0 869 if ( count )
1d910ac1 870 {
3ca6a5f0
BP
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 }
1d910ac1 876 }
7beba2fc
VZ
877
878 return FALSE;
879}
6648cd46 880
6648cd46
VS
881bool 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
6648cd46
VS
892bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
893 const wxString& facename)
894{
895 wxNativeEncodingInfo info;
62ea506e 896
551fe3a6 897 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
898 {
899 info.facename = facename;
900 return wxTestFontEncoding(info);
901 }
3ca6a5f0
BP
902
903 return FALSE;
6648cd46 904}
f6bcfd97
BP
905
906#endif // wxUSE_GUI
1e6feb95
VZ
907
908#endif // wxUSE_FONTMAP