]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
Revert back to standard point size for fonts in OS/2
[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{
4d416b5f
VZ
240#if wxUSE_CONFIG
241 if ( m_configIsDummy )
242 delete m_config;
243#endif // wxUSE_CONFIG
3c1866e8
VZ
244}
245
246// ----------------------------------------------------------------------------
247// customisation
248// ----------------------------------------------------------------------------
249
f6bcfd97
BP
250#if wxUSE_CONFIG
251
3c1866e8
VZ
252/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
253{
254 return FONTMAPPER_ROOT_PATH;
255}
256
257void wxFontMapper::SetConfigPath(const wxString& prefix)
258{
259 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
fbdcff4a 260 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
3c1866e8
VZ
261
262 m_configRootPath = prefix;
263}
264
3c1866e8
VZ
265// ----------------------------------------------------------------------------
266// get config object and path for it
267// ----------------------------------------------------------------------------
268
269wxConfigBase *wxFontMapper::GetConfig()
270{
271 if ( !m_config )
272 {
273 // try the default
1d910ac1
VZ
274 m_config = wxConfig::Get(FALSE /*don't create on demand*/ );
275
276 if ( !m_config )
277 {
278 // we still want to have a config object because otherwise we would
279 // keep asking the user the same questions in the interactive mode,
280 // so create a dummy config which won't write to any files/registry
281 // but will allow us to remember the results of the questions at
282 // least during this run
283 m_config = new wxMemoryConfig;
5fe83549
VS
284 m_configIsDummy = TRUE;
285 // VS: we can't call wxConfig::Set(m_config) here because that would
286 // disable automatic wxConfig instance creation if this code was
287 // called before wxApp::OnInit (this happens in wxGTK -- it sets
288 // default wxFont encoding in wxApp::Initialize())
1d910ac1 289 }
3c1866e8
VZ
290 }
291
5fe83549
VS
292 if ( m_configIsDummy && wxConfig::Get(FALSE) != NULL )
293 {
294 // VS: in case we created dummy m_config (see above), we want to switch back
295 // to the real one as soon as one becomes available.
4d416b5f 296 delete m_config;
5fe83549
VS
297 m_config = wxConfig::Get(FALSE);
298 m_configIsDummy = FALSE;
299 // FIXME: ideally, we should add keys from dummy config to the real one now,
300 // but it is a low-priority task because typical wxWin application
c7821f94
VZ
301 // either doesn't use wxConfig at all or creates wxConfig object in
302 // wxApp::OnInit(), before any real interaction with the user takes
5fe83549
VS
303 // place...
304 }
305
3c1866e8
VZ
306 return m_config;
307}
308
309const wxString& wxFontMapper::GetConfigPath()
310{
311 if ( !m_configRootPath )
312 {
313 // use the default
314 m_configRootPath = GetDefaultConfigPath();
315 }
316
317 return m_configRootPath;
318}
f6bcfd97 319#endif
3c1866e8
VZ
320
321bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
322{
f6bcfd97 323#if wxUSE_CONFIG
3c1866e8
VZ
324 wxConfigBase *config = GetConfig();
325 if ( !config )
326 return FALSE;
327
328 *pathOld = config->GetPath();
329
330 wxString path = GetConfigPath();
331 if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
332 {
333 path += wxCONFIG_PATH_SEPARATOR;
334 }
335
336 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
58c837a4 337 wxT("should be a relative path") );
3c1866e8
VZ
338
339 path += pathNew;
340
341 config->SetPath(path);
342
343 return TRUE;
f6bcfd97
BP
344#else
345 return FALSE;
346#endif
3c1866e8
VZ
347}
348
349void wxFontMapper::RestorePath(const wxString& pathOld)
350{
f6bcfd97 351#if wxUSE_CONFIG
3c1866e8 352 GetConfig()->SetPath(pathOld);
f6bcfd97
BP
353#else
354#endif
3c1866e8
VZ
355}
356
357// ----------------------------------------------------------------------------
358// charset/encoding correspondence
359// ----------------------------------------------------------------------------
360
7beba2fc
VZ
361/* static */
362wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
363{
551fe3a6
VZ
364 if ( encoding == wxFONTENCODING_DEFAULT )
365 {
366 return _("Default encoding");
367 }
368
7beba2fc
VZ
369 size_t count = WXSIZEOF(gs_encodingDescs);
370
371 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 372 wxT("inconsitency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
373
374 for ( size_t i = 0; i < count; i++ )
375 {
376 if ( gs_encodings[i] == encoding )
377 {
378 return wxGetTranslation(gs_encodingDescs[i]);
379 }
380 }
381
382 wxString str;
383 str.Printf(_("Unknown encoding (%d)"), encoding);
384
385 return str;
386}
387
388/* static */
389wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
390{
551fe3a6
VZ
391 if ( encoding == wxFONTENCODING_DEFAULT )
392 {
393 return _("default");
394 }
395
7beba2fc
VZ
396 size_t count = WXSIZEOF(gs_encodingNames);
397
398 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 399 wxT("inconsistency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
400
401 for ( size_t i = 0; i < count; i++ )
402 {
403 if ( gs_encodings[i] == encoding )
404 {
a4a6984d 405 return gs_encodingNames[i];
7beba2fc
VZ
406 }
407 }
408
409 wxString str;
410 str.Printf(_("unknown-%d"), encoding);
411
412 return str;
413}
414
3c1866e8
VZ
415wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
416 bool interactive)
417{
3e7fb236
VZ
418 // a special pseudo encoding which means "don't ask me about this charset
419 // any more" - we need it to avoid driving the user crazy with asking him
420 // time after time about the same charset which he [presumably] doesn't
421 // have the fonts fot
422 static const int wxFONTENCODING_UNKNOWN = -2;
423
3c1866e8
VZ
424 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
425
426 // we're going to modify it, make a copy
427 wxString cs = charset;
428
f6bcfd97 429#if wxUSE_CONFIG
3c1866e8
VZ
430 // first try the user-defined settings
431 wxString pathOld;
432 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
433 {
434 wxConfigBase *config = GetConfig();
435
436 // do we have an encoding for this charset?
437 long value = config->Read(charset, -1l);
438 if ( value != -1 )
439 {
3e7fb236
VZ
440 if ( value == wxFONTENCODING_UNKNOWN )
441 {
442 // don't try to find it, in particular don't ask the user
443 return wxFONTENCODING_SYSTEM;
444 }
445
3c1866e8
VZ
446 if ( value >= 0 && value <= wxFONTENCODING_MAX )
447 {
448 encoding = (wxFontEncoding)value;
449 }
450 else
451 {
f6bcfd97 452 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 453 value, charset.c_str());
3c1866e8
VZ
454 }
455 }
456
457 if ( encoding == wxFONTENCODING_SYSTEM )
458 {
459 // may be we have an alias?
460 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
461
462 wxString alias = config->Read(charset);
463 if ( !!alias )
464 {
465 // yes, we do - use it instead
466 cs = alias;
467 }
468 }
469
470 RestorePath(pathOld);
471 }
3e7fb236 472#endif // wxUSE_CONFIG
3c1866e8 473
551fe3a6 474 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
475 if ( encoding == wxFONTENCODING_SYSTEM )
476 {
551fe3a6
VZ
477 // trim any spaces
478 cs.Trim(TRUE);
479 cs.Trim(FALSE);
480
3ca6a5f0 481 // discard the optional quotes
caa6e137 482 if ( !cs.empty() )
3ca6a5f0
BP
483 {
484 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
485 {
486 cs = wxString(cs.c_str(), cs.length() - 1);
487 }
488 }
489
3c1866e8
VZ
490 cs.MakeUpper();
491
caa6e137
VZ
492 // nl_langinfo() under Solaris returns 646 by default which stands for
493 // ISO-646, i.e. 7 bit ASCII and we should recognize it to avoid
494 // warnings about unrecognized encoding on each program startup
495 if ( cs.empty() || cs == _T("US-ASCII") || cs == _T("646") )
551fe3a6 496 {
3c1866e8 497 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 498 }
bb84929e 499 else if ( cs == wxT("UTF-7") )
551fe3a6 500 {
bb84929e 501 encoding = wxFONTENCODING_UTF7;
551fe3a6 502 }
bb84929e 503 else if ( cs == wxT("UTF-8") )
551fe3a6 504 {
bb84929e 505 encoding = wxFONTENCODING_UTF8;
551fe3a6
VZ
506 }
507 else if ( cs == wxT("KOI8-R") ||
508 cs == wxT("KOI8-U") ||
509 cs == wxT("KOI8-RU") )
510 {
511 // although koi8-ru is not strictly speaking the same as koi8-r,
512 // they are similar enough to make mapping it to koi8 better than
513 // not reckognizing it at all
3c1866e8 514 encoding = wxFONTENCODING_KOI8;
551fe3a6 515 }
58c837a4 516 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
517 {
518 // the dash is optional (or, to be exact, it is not, but
519 // several brokenmails "forget" it)
520 const wxChar *p = cs.c_str() + 3;
58c837a4 521 if ( *p == wxT('-') )
3c1866e8
VZ
522 p++;
523
524 unsigned int value;
58c837a4 525 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 526 {
daaa6710
VZ
527 // make it 0 based and check that it is strictly positive in
528 // the process (no such thing as iso8859-0 encoding)
529 if ( (value-- > 0) &&
530 (value < wxFONTENCODING_ISO8859_MAX -
531 wxFONTENCODING_ISO8859_1) )
3c1866e8
VZ
532 {
533 // it's a valid ISO8859 encoding
daaa6710 534 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
535 encoding = (wxFontEncoding)value;
536 }
537 }
538 }
551fe3a6 539 else // check for Windows charsets
3c1866e8 540 {
551fe3a6
VZ
541 size_t len;
542 if ( cs.Left(7) == wxT("WINDOWS") )
543 {
544 len = 7;
545 }
546 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 547 {
551fe3a6
VZ
548 len = 2;
549 }
550 else // not a Windows encoding
551 {
552 len = 0;
553 }
554
555 if ( len )
556 {
557 const wxChar *p = cs.c_str() + len;
558 if ( *p == wxT('-') )
559 p++;
560
561 int value;
562 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
3c1866e8 563 {
551fe3a6 564 if ( value >= 1250 )
3c1866e8 565 {
551fe3a6
VZ
566 value -= 1250;
567 if ( value < wxFONTENCODING_CP12_MAX -
568 wxFONTENCODING_CP1250 )
569 {
570 // a valid Windows code page
571 value += wxFONTENCODING_CP1250;
572 encoding = (wxFontEncoding)value;
573 }
3c1866e8 574 }
c7821f94
VZ
575
576 switch ( value )
577 {
578 case 932:
579 encoding = wxFONTENCODING_CP932;
580 break;
581
582 case 936:
583 encoding = wxFONTENCODING_CP936;
584 break;
585
586 case 949:
587 encoding = wxFONTENCODING_CP949;
588 break;
589
590 case 950:
591 encoding = wxFONTENCODING_CP950;
592 break;
593 }
3c1866e8
VZ
594 }
595 }
596 }
597 //else: unknown
598 }
599
f6bcfd97 600#if wxUSE_GUI
3c1866e8
VZ
601 // if still no luck, ask the user - unless disabled
602 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
603 {
604 // prepare the dialog data
605
606 // the dialog title
607 wxString title(m_titleDialog);
608 if ( !title )
609 title << wxTheApp->GetAppName() << _(": unknown charset");
610
611 // the message
612 wxString msg;
f6bcfd97 613 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
614
615 // the list of choices
7beba2fc
VZ
616 size_t count = WXSIZEOF(gs_encodingDescs);
617
618 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 619 wxT("inconsitency detected - forgot to update one of the arrays?") );
3c1866e8
VZ
620
621 wxString *encodingNamesTranslated = new wxString[count];
622
11c7d5b6 623 for ( size_t i = 0; i < count; i++ )
3c1866e8 624 {
11c7d5b6 625 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
626 }
627
628 // the parent window
629 wxWindow *parent = m_windowParent;
630 if ( !parent )
631 parent = wxTheApp->GetTopWindow();
632
633 // do ask the user and get back the index in encodings table
634 int n = wxGetSingleChoiceIndex(msg, title,
635 count,
636 encodingNamesTranslated,
637 parent);
638
639 delete [] encodingNamesTranslated;
640
641 if ( n != -1 )
642 {
7beba2fc 643 encoding = gs_encodings[n];
3e7fb236 644 }
1d910ac1 645
f6bcfd97
BP
646#if wxUSE_CONFIG
647 // save the result in the config now
3e7fb236
VZ
648 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
649 {
650 wxConfigBase *config = GetConfig();
1d910ac1 651
3e7fb236
VZ
652 // remember the alt encoding for this charset - or remember that
653 // we don't know it
654 long value = n == -1 ? wxFONTENCODING_UNKNOWN : (long)encoding;
655 if ( !config->Write(charset, value) )
656 {
657 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
1d910ac1 658 }
3e7fb236
VZ
659
660 RestorePath(pathOld);
3c1866e8 661 }
3e7fb236 662#endif // wxUSE_CONFIG
3c1866e8 663 }
f6bcfd97 664#endif // wxUSE_GUI
3c1866e8
VZ
665
666 return encoding;
667}
668
7beba2fc
VZ
669// ----------------------------------------------------------------------------
670// support for unknown encodings: we maintain a map between the
671// (platform-specific) strings identifying them and our wxFontEncodings they
672// correspond to which is used by GetFontForEncoding() function
673// ----------------------------------------------------------------------------
674
f6bcfd97
BP
675#if wxUSE_GUI
676
7beba2fc
VZ
677bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
678 wxFontEncoding encReplacement,
679 wxNativeEncodingInfo *info)
680{
681 if ( wxGetNativeFontEncoding(encReplacement, info) &&
682 wxTestFontEncoding(*info) )
683 {
f6bcfd97 684#if wxUSE_CONFIG
7beba2fc
VZ
685 // remember the mapping in the config
686 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
687
688 if ( path.IsOk() )
689 {
690 GetConfig()->Write(configEntry, info->ToString());
691 }
f6bcfd97 692#endif // wxUSE_CONFIG
7beba2fc
VZ
693 return TRUE;
694 }
695
696 return FALSE;
697}
698
f6bcfd97
BP
699#if wxUSE_GUI
700class ReentrancyBlocker
701{
702public:
703 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
704 ~ReentrancyBlocker() { m_b = FALSE; }
705
706private:
707 bool& m_b;
708};
709#endif
710
7beba2fc
VZ
711bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
712 wxNativeEncodingInfo *info,
6648cd46 713 const wxString& facename,
7beba2fc
VZ
714 bool interactive)
715{
f6bcfd97
BP
716#if wxUSE_GUI
717 // we need a flag to prevent infinite recursion which happens, for
718 // example, when GetAltForEncoding() is called from an OnPaint() handler:
719 // in this case, wxYield() which is called from wxMessageBox() we use here
720 // will lead to another call of OnPaint() and hence to another call of
721 // GetAltForEncoding() - and it is impossible to catch this from the user
722 // code because we are called from wxFont ctor implicitly.
723
724 // assume we're always called from the main thread, so that it is safe to
725 // use a static var
726 static bool s_inGetAltForEncoding = FALSE;
727
728 if ( interactive && s_inGetAltForEncoding )
729 return FALSE;
730
731 ReentrancyBlocker blocker(s_inGetAltForEncoding);
732#endif // wxUSE_GUI
733
58c837a4 734 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 735
6648cd46
VS
736 info->facename = facename;
737
97d3f0ee
VZ
738 if ( encoding == wxFONTENCODING_DEFAULT )
739 {
740 encoding = wxFont::GetDefaultEncoding();
741 }
742
743 // if we failed to load the system default encoding, something is really
744 // wrong and we'd better stop now - otherwise we will go into endless
745 // recursion trying to create the font in the msg box with the error
746 // message
747 if ( encoding == wxFONTENCODING_SYSTEM )
748 {
749 wxFatalError(_("can't load any font, aborting"));
750
751 // wxFatalError doesn't return
752 }
753
a4a6984d
VZ
754 wxString configEntry,
755 encName = GetEncodingName(encoding);
1d910ac1
VZ
756 if ( !!facename )
757 {
758 configEntry = facename + _T("_");
759 }
760 configEntry += encName;
7beba2fc 761
f6bcfd97 762#if wxUSE_CONFIG
7beba2fc
VZ
763 // do we have a font spec for this encoding?
764 wxString pathOld;
765 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
766 {
767 wxConfigBase *config = GetConfig();
768
769 wxString fontinfo = config->Read(configEntry);
770
771 RestorePath(pathOld);
772
6603907d
VZ
773 // this special value means that we don't know of fonts for this
774 // encoding but, moreover, have already asked the user as well and he
775 // didn't specify any font neither
776 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
1d910ac1 777 {
6603907d 778 interactive = FALSE;
1d910ac1 779 }
6603907d 780 else // use the info entered the last time
7beba2fc 781 {
6603907d 782 if ( !!fontinfo && !!facename )
7beba2fc 783 {
6603907d
VZ
784 // we tried to find a match with facename - now try without it
785 fontinfo = config->Read(encName);
7beba2fc 786 }
6603907d
VZ
787
788 if ( !!fontinfo )
7beba2fc 789 {
6603907d
VZ
790 if ( info->FromString(fontinfo) )
791 {
792 if ( wxTestFontEncoding(*info) )
793 {
794 // ok, got something
795 return TRUE;
796 }
797 //else: no such fonts, look for something else
798 // (should we erase the outdated value?)
799 }
800 else
801 {
802 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
803 fontinfo.c_str());
804 }
7beba2fc 805 }
6603907d 806 //else: there is no information in config about this encoding
7beba2fc
VZ
807 }
808 }
f6bcfd97 809#endif // wxUSE_CONFIG
7beba2fc 810
3a989c8a
VZ
811 // now try to map this encoding to a compatible one which we have on this
812 // system
813 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
814 size_t count = equiv.GetCount();
815 bool foundEquivEncoding = FALSE;
c6465c96 816 wxFontEncoding equivEncoding = wxFONTENCODING_SYSTEM;
3a989c8a
VZ
817 if ( count )
818 {
819 for ( size_t i = 0; i < count && !foundEquivEncoding; i++ )
820 {
821 // don't test for encoding itself, we already know we don't have it
822 if ( equiv[i] == encoding )
823 continue;
824
825 if ( TestAltEncoding(configEntry, equiv[i], info) )
826 {
827 equivEncoding = equiv[i];
828
829 foundEquivEncoding = TRUE;
830 }
831 }
832 }
833
7beba2fc 834 // ask the user
3379ed37 835#if wxUSE_FONTDLG
7beba2fc
VZ
836 if ( interactive )
837 {
838 wxString title(m_titleDialog);
839 if ( !title )
840 title << wxTheApp->GetAppName() << _(": unknown encoding");
841
3a989c8a
VZ
842 // built the message
843 wxString encDesc = GetEncodingDescription(encoding),
844 msg;
845 if ( foundEquivEncoding )
846 {
847 // ask the user if he wants to override found alternative encoding
848 msg.Printf(_("No font for displaying text in encoding '%s' found,\nbut an alternative encoding '%s' is available.\nDo you want to use this encoding (otherwise you will have to choose another one)?"),
849 encDesc.c_str(), GetEncodingDescription(equivEncoding).c_str());
850 }
851 else
852 {
853 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)?"),
854 encDesc.c_str());
855 }
7beba2fc 856
3a989c8a
VZ
857 // the question is different in 2 cases so the answer has to be
858 // interpreted differently as well
859 int answer = foundEquivEncoding ? wxNO : wxYES;
7beba2fc
VZ
860
861 if ( wxMessageBox(msg, title,
3a989c8a
VZ
862 wxICON_QUESTION | wxYES_NO,
863 m_windowParent) == answer )
7beba2fc
VZ
864 {
865 wxFontData data;
866 data.SetEncoding(encoding);
867 data.EncodingInfo() = *info;
3a989c8a 868 wxFontDialog dialog(m_windowParent, &data);
7beba2fc
VZ
869 if ( dialog.ShowModal() == wxID_OK )
870 {
871 wxFontData retData = dialog.GetFontData();
872 wxFont font = retData.GetChosenFont();
873
11c7d5b6 874 *info = retData.EncodingInfo();
3a989c8a 875 info->encoding = retData.GetEncoding();
7beba2fc 876
f6bcfd97 877#if wxUSE_CONFIG
6603907d 878 // remember this in the config
7beba2fc
VZ
879 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
880 {
881 GetConfig()->Write(configEntry, info->ToString());
882
883 RestorePath(pathOld);
884 }
bb84929e 885#endif // wxUSE_CONFIG
7beba2fc
VZ
886
887 return TRUE;
888 }
889 //else: the user canceled the font selection dialog
890 }
6603907d
VZ
891 else
892 {
3a989c8a
VZ
893 // the user doesn't want to select a font for this encoding
894 // or selected to use equivalent encoding
895 //
6603907d
VZ
896 // remember it to avoid asking the same question again later
897#if wxUSE_CONFIG
898 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
899 {
3a989c8a
VZ
900 GetConfig()->Write
901 (
902 configEntry,
903 foundEquivEncoding ? info->ToString().c_str()
904 : FONTMAPPER_FONT_DONT_ASK
905 );
6603907d
VZ
906
907 RestorePath(pathOld);
908 }
909#endif // wxUSE_CONFIG
910 }
7beba2fc
VZ
911 }
912 //else: we're in non-interactive mode
3379ed37 913#endif // wxUSE_FONTDLG
7beba2fc 914
3a989c8a 915 return foundEquivEncoding;
7beba2fc 916}
6648cd46 917
6648cd46
VS
918bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
919 wxFontEncoding *alt_encoding,
920 const wxString& facename,
921 bool interactive)
922{
923 wxNativeEncodingInfo info;
924 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
925 *alt_encoding = info.encoding;
926 return r;
927}
928
6648cd46
VS
929bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
930 const wxString& facename)
931{
932 wxNativeEncodingInfo info;
62ea506e 933
551fe3a6 934 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
935 {
936 info.facename = facename;
937 return wxTestFontEncoding(info);
938 }
3ca6a5f0
BP
939
940 return FALSE;
6648cd46 941}
f6bcfd97
BP
942
943#endif // wxUSE_GUI
1e6feb95
VZ
944
945#endif // wxUSE_FONTMAP