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