]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
SetPath() is now implemented in dirdlg.cpp
[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
65e50848 39#include "wx/module.h"
3c1866e8 40#include "wx/fontmap.h"
7beba2fc 41
f6bcfd97
BP
42#if wxUSE_CONFIG
43 #include "wx/config.h"
44 #include "wx/memconf.h"
45#endif
46
47#if wxUSE_GUI
70184095 48 #include "wx/fontutil.h"
f6bcfd97
BP
49 #include "wx/msgdlg.h"
50 #include "wx/fontdlg.h"
51 #include "wx/choicdlg.h"
52#endif // wxUSE_GUI
53
82545b58 54#include "wx/encconv.h"
3c1866e8
VZ
55
56// ----------------------------------------------------------------------------
57// constants
58// ----------------------------------------------------------------------------
59
60// the config paths we use
1e6feb95 61#if wxUSE_CONFIG
3ca6a5f0 62static const wxChar* FONTMAPPER_ROOT_PATH = wxT("/wxWindows/FontMapper");
511f273f
OK
63static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
64static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
6603907d
VZ
65
66// we only ask questions in GUI mode
f6bcfd97
BP
67#if wxUSE_GUI
68 static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
6603907d 69 static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none");
f6bcfd97 70#endif // wxUSE_GUI
1e6feb95 71#endif // wxUSE_CONFIG
7beba2fc
VZ
72
73// encodings supported by GetEncodingDescription
74static wxFontEncoding gs_encodings[] =
75{
76 wxFONTENCODING_ISO8859_1,
77 wxFONTENCODING_ISO8859_2,
78 wxFONTENCODING_ISO8859_3,
79 wxFONTENCODING_ISO8859_4,
80 wxFONTENCODING_ISO8859_5,
81 wxFONTENCODING_ISO8859_6,
82 wxFONTENCODING_ISO8859_7,
83 wxFONTENCODING_ISO8859_8,
84 wxFONTENCODING_ISO8859_9,
85 wxFONTENCODING_ISO8859_10,
86 wxFONTENCODING_ISO8859_11,
87 wxFONTENCODING_ISO8859_12,
88 wxFONTENCODING_ISO8859_13,
89 wxFONTENCODING_ISO8859_14,
90 wxFONTENCODING_ISO8859_15,
91 wxFONTENCODING_KOI8,
bc4e6fcd
VZ
92 wxFONTENCODING_CP932,
93 wxFONTENCODING_CP936,
94 wxFONTENCODING_CP949,
95 wxFONTENCODING_CP950,
7beba2fc
VZ
96 wxFONTENCODING_CP1250,
97 wxFONTENCODING_CP1251,
98 wxFONTENCODING_CP1252,
99 wxFONTENCODING_CP1253,
100 wxFONTENCODING_CP1254,
101 wxFONTENCODING_CP1255,
102 wxFONTENCODING_CP1256,
103 wxFONTENCODING_CP1257,
f6bcfd97 104 wxFONTENCODING_CP437,
bb84929e
VZ
105 wxFONTENCODING_UTF7,
106 wxFONTENCODING_UTF8,
7beba2fc
VZ
107};
108
109// the descriptions for them
110static const wxChar* gs_encodingDescs[] =
111{
03424b1b
VZ
112 wxTRANSLATE( "Western European (ISO-8859-1)" ),
113 wxTRANSLATE( "Central European (ISO-8859-2)" ),
7beba2fc 114 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
f6bcfd97 115 wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
03424b1b 116 wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
7beba2fc
VZ
117 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
118 wxTRANSLATE( "Greek (ISO-8859-7)" ),
119 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
120 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
f6bcfd97 121 wxTRANSLATE( "Nordic (ISO-8859-10)" ),
7beba2fc 122 wxTRANSLATE( "Thai (ISO-8859-11)" ),
80a24267 123 wxTRANSLATE( "Indian (ISO-8859-12)" ),
f6bcfd97 124 wxTRANSLATE( "Baltic (ISO-8859-13)" ),
80a24267 125 wxTRANSLATE( "Celtic (ISO-8859-14)" ),
03424b1b 126 wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
7beba2fc 127 wxTRANSLATE( "KOI8-R" ),
bc4e6fcd 128 wxTRANSLATE( "Windows Japanese (CP 932)" ),
62b3ca69 129 wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
bc4e6fcd
VZ
130 wxTRANSLATE( "Windows Korean (CP 949)" ),
131 wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
80a24267 132 wxTRANSLATE( "Windows Central European (CP 1250)" ),
7beba2fc 133 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
80a24267 134 wxTRANSLATE( "Windows Western European (CP 1252)" ),
7beba2fc
VZ
135 wxTRANSLATE( "Windows Greek (CP 1253)" ),
136 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
137 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
138 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
139 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
f6bcfd97 140 wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
bb84929e
VZ
141 wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
142 wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
7beba2fc
VZ
143};
144
a4a6984d 145// and the internal names (these are not translated on purpose!)
7beba2fc
VZ
146static const wxChar* gs_encodingNames[] =
147{
ecffe992
VS
148 wxT( "iso-8859-1" ),
149 wxT( "iso-8859-2" ),
150 wxT( "iso-8859-3" ),
151 wxT( "iso-8859-4" ),
152 wxT( "iso-8859-5" ),
153 wxT( "iso-8859-6" ),
154 wxT( "iso-8859-7" ),
155 wxT( "iso-8859-8" ),
156 wxT( "iso-8859-9" ),
157 wxT( "iso-8859-10" ),
158 wxT( "iso-8859-11" ),
159 wxT( "iso-8859-12" ),
160 wxT( "iso-8859-13" ),
161 wxT( "iso-8859-14" ),
162 wxT( "iso-8859-15" ),
511f273f 163 wxT( "koi8-r" ),
bc4e6fcd
VZ
164 wxT( "windows-932" ),
165 wxT( "windows-936" ),
166 wxT( "windows-949" ),
167 wxT( "windows-950" ),
551fe3a6
VZ
168 wxT( "windows-1250" ),
169 wxT( "windows-1251" ),
170 wxT( "windows-1252" ),
171 wxT( "windows-1253" ),
172 wxT( "windows-1254" ),
173 wxT( "windows-1255" ),
174 wxT( "windows-1256" ),
175 wxT( "windows-1257" ),
176 wxT( "windows-437" ),
5707316c
VS
177 wxT( "utf-7" ),
178 wxT( "utf-8" ),
7beba2fc
VZ
179};
180
181// ----------------------------------------------------------------------------
182// global data
183// ----------------------------------------------------------------------------
184
65e50848 185wxFontMapper * wxTheFontMapper = NULL;
7beba2fc 186
65e50848
JS
187class wxFontMapperModule: public wxModule
188{
189public:
190 wxFontMapperModule() : wxModule() { }
191 virtual bool OnInit() { wxTheFontMapper = new wxFontMapper; return TRUE; }
192 virtual void OnExit()
193 {
194 delete wxTheFontMapper;
195 wxTheFontMapper = NULL;
196 }
197
198 DECLARE_DYNAMIC_CLASS(wxFontMapperModule)
199};
200
201IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule, wxModule)
7beba2fc
VZ
202
203// ----------------------------------------------------------------------------
204// private classes
205// ----------------------------------------------------------------------------
206
207// change the config path during the lifetime of this object
208class wxFontMapperPathChanger
209{
210public:
211 wxFontMapperPathChanger(wxFontMapper *fontMapper, const wxString& path)
212 {
213 m_fontMapper = fontMapper;
214 m_ok = m_fontMapper->ChangePath(path, &m_pathOld);
215 }
216
217 bool IsOk() const { return m_ok; }
218
219 ~wxFontMapperPathChanger()
220 {
221 if ( IsOk() )
222 m_fontMapper->RestorePath(m_pathOld);
223 }
224
225private:
226 wxFontMapper *m_fontMapper;
227 bool m_ok;
228 wxString m_pathOld;
229};
3c1866e8
VZ
230
231// ============================================================================
232// implementation
233// ============================================================================
234
235// ----------------------------------------------------------------------------
236// ctor and dtor
237// ----------------------------------------------------------------------------
238
239wxFontMapper::wxFontMapper()
240{
f6bcfd97 241#if wxUSE_CONFIG
3c1866e8 242 m_config = NULL;
5fe83549 243 m_configIsDummy = FALSE;
f6bcfd97
BP
244#endif // wxUSE_CONFIG
245
246#if wxUSE_GUI
3c1866e8 247 m_windowParent = NULL;
f6bcfd97 248#endif // wxUSE_GUI
3c1866e8
VZ
249}
250
251wxFontMapper::~wxFontMapper()
252{
4d416b5f
VZ
253#if wxUSE_CONFIG
254 if ( m_configIsDummy )
255 delete m_config;
256#endif // wxUSE_CONFIG
3c1866e8
VZ
257}
258
259// ----------------------------------------------------------------------------
260// customisation
261// ----------------------------------------------------------------------------
262
f6bcfd97
BP
263#if wxUSE_CONFIG
264
3c1866e8
VZ
265/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
266{
267 return FONTMAPPER_ROOT_PATH;
268}
269
270void wxFontMapper::SetConfigPath(const wxString& prefix)
271{
272 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
fbdcff4a 273 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
3c1866e8
VZ
274
275 m_configRootPath = prefix;
276}
277
3c1866e8
VZ
278// ----------------------------------------------------------------------------
279// get config object and path for it
280// ----------------------------------------------------------------------------
281
282wxConfigBase *wxFontMapper::GetConfig()
283{
284 if ( !m_config )
285 {
286 // try the default
1d910ac1
VZ
287 m_config = wxConfig::Get(FALSE /*don't create on demand*/ );
288
289 if ( !m_config )
290 {
291 // we still want to have a config object because otherwise we would
292 // keep asking the user the same questions in the interactive mode,
293 // so create a dummy config which won't write to any files/registry
294 // but will allow us to remember the results of the questions at
295 // least during this run
296 m_config = new wxMemoryConfig;
5fe83549
VS
297 m_configIsDummy = TRUE;
298 // VS: we can't call wxConfig::Set(m_config) here because that would
299 // disable automatic wxConfig instance creation if this code was
300 // called before wxApp::OnInit (this happens in wxGTK -- it sets
301 // default wxFont encoding in wxApp::Initialize())
1d910ac1 302 }
3c1866e8
VZ
303 }
304
5fe83549
VS
305 if ( m_configIsDummy && wxConfig::Get(FALSE) != NULL )
306 {
307 // VS: in case we created dummy m_config (see above), we want to switch back
308 // to the real one as soon as one becomes available.
4d416b5f 309 delete m_config;
5fe83549
VS
310 m_config = wxConfig::Get(FALSE);
311 m_configIsDummy = FALSE;
312 // FIXME: ideally, we should add keys from dummy config to the real one now,
313 // but it is a low-priority task because typical wxWin application
c7821f94
VZ
314 // either doesn't use wxConfig at all or creates wxConfig object in
315 // wxApp::OnInit(), before any real interaction with the user takes
5fe83549
VS
316 // place...
317 }
318
3c1866e8
VZ
319 return m_config;
320}
321
322const wxString& wxFontMapper::GetConfigPath()
323{
324 if ( !m_configRootPath )
325 {
326 // use the default
327 m_configRootPath = GetDefaultConfigPath();
328 }
329
330 return m_configRootPath;
331}
f6bcfd97 332#endif
3c1866e8
VZ
333
334bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
335{
f6bcfd97 336#if wxUSE_CONFIG
3c1866e8
VZ
337 wxConfigBase *config = GetConfig();
338 if ( !config )
339 return FALSE;
340
341 *pathOld = config->GetPath();
342
343 wxString path = GetConfigPath();
344 if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
345 {
346 path += wxCONFIG_PATH_SEPARATOR;
347 }
348
349 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
58c837a4 350 wxT("should be a relative path") );
3c1866e8
VZ
351
352 path += pathNew;
353
354 config->SetPath(path);
355
356 return TRUE;
f6bcfd97
BP
357#else
358 return FALSE;
359#endif
3c1866e8
VZ
360}
361
362void wxFontMapper::RestorePath(const wxString& pathOld)
363{
f6bcfd97 364#if wxUSE_CONFIG
3c1866e8 365 GetConfig()->SetPath(pathOld);
f6bcfd97
BP
366#else
367#endif
3c1866e8
VZ
368}
369
370// ----------------------------------------------------------------------------
371// charset/encoding correspondence
372// ----------------------------------------------------------------------------
373
7beba2fc
VZ
374/* static */
375wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
376{
551fe3a6
VZ
377 if ( encoding == wxFONTENCODING_DEFAULT )
378 {
379 return _("Default encoding");
380 }
381
7beba2fc
VZ
382 size_t count = WXSIZEOF(gs_encodingDescs);
383
384 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 385 wxT("inconsitency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
386
387 for ( size_t i = 0; i < count; i++ )
388 {
389 if ( gs_encodings[i] == encoding )
390 {
391 return wxGetTranslation(gs_encodingDescs[i]);
392 }
393 }
394
395 wxString str;
396 str.Printf(_("Unknown encoding (%d)"), encoding);
397
398 return str;
399}
400
401/* static */
402wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
403{
551fe3a6
VZ
404 if ( encoding == wxFONTENCODING_DEFAULT )
405 {
406 return _("default");
407 }
408
7beba2fc
VZ
409 size_t count = WXSIZEOF(gs_encodingNames);
410
411 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 412 wxT("inconsistency detected - forgot to update one of the arrays?") );
7beba2fc
VZ
413
414 for ( size_t i = 0; i < count; i++ )
415 {
416 if ( gs_encodings[i] == encoding )
417 {
a4a6984d 418 return gs_encodingNames[i];
7beba2fc
VZ
419 }
420 }
421
422 wxString str;
423 str.Printf(_("unknown-%d"), encoding);
424
425 return str;
426}
427
3c1866e8
VZ
428wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
429 bool interactive)
430{
3e7fb236
VZ
431 // a special pseudo encoding which means "don't ask me about this charset
432 // any more" - we need it to avoid driving the user crazy with asking him
433 // time after time about the same charset which he [presumably] doesn't
434 // have the fonts fot
435 static const int wxFONTENCODING_UNKNOWN = -2;
436
3c1866e8
VZ
437 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
438
439 // we're going to modify it, make a copy
440 wxString cs = charset;
441
f6bcfd97 442#if wxUSE_CONFIG
3c1866e8
VZ
443 // first try the user-defined settings
444 wxString pathOld;
445 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
446 {
447 wxConfigBase *config = GetConfig();
448
449 // do we have an encoding for this charset?
450 long value = config->Read(charset, -1l);
451 if ( value != -1 )
452 {
3e7fb236
VZ
453 if ( value == wxFONTENCODING_UNKNOWN )
454 {
455 // don't try to find it, in particular don't ask the user
456 return wxFONTENCODING_SYSTEM;
457 }
458
3c1866e8
VZ
459 if ( value >= 0 && value <= wxFONTENCODING_MAX )
460 {
461 encoding = (wxFontEncoding)value;
462 }
463 else
464 {
f6bcfd97 465 wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
1d910ac1 466 value, charset.c_str());
3c1866e8
VZ
467 }
468 }
469
470 if ( encoding == wxFONTENCODING_SYSTEM )
471 {
472 // may be we have an alias?
473 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
474
475 wxString alias = config->Read(charset);
476 if ( !!alias )
477 {
478 // yes, we do - use it instead
479 cs = alias;
480 }
481 }
482
483 RestorePath(pathOld);
484 }
3e7fb236 485#endif // wxUSE_CONFIG
3c1866e8 486
551fe3a6 487 // if didn't find it there, try to recognize it ourselves
3c1866e8
VZ
488 if ( encoding == wxFONTENCODING_SYSTEM )
489 {
551fe3a6
VZ
490 // trim any spaces
491 cs.Trim(TRUE);
492 cs.Trim(FALSE);
493
3ca6a5f0 494 // discard the optional quotes
caa6e137 495 if ( !cs.empty() )
3ca6a5f0
BP
496 {
497 if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
498 {
499 cs = wxString(cs.c_str(), cs.length() - 1);
500 }
501 }
502
3c1866e8
VZ
503 cs.MakeUpper();
504
cafbf6fb 505 if ( cs.empty() || cs == _T("US-ASCII") )
551fe3a6 506 {
3c1866e8 507 encoding = wxFONTENCODING_DEFAULT;
551fe3a6 508 }
bb84929e 509 else if ( cs == wxT("UTF-7") )
551fe3a6 510 {
bb84929e 511 encoding = wxFONTENCODING_UTF7;
551fe3a6 512 }
bb84929e 513 else if ( cs == wxT("UTF-8") )
551fe3a6 514 {
bb84929e 515 encoding = wxFONTENCODING_UTF8;
551fe3a6
VZ
516 }
517 else if ( cs == wxT("KOI8-R") ||
518 cs == wxT("KOI8-U") ||
519 cs == wxT("KOI8-RU") )
520 {
521 // although koi8-ru is not strictly speaking the same as koi8-r,
522 // they are similar enough to make mapping it to koi8 better than
523 // not reckognizing it at all
3c1866e8 524 encoding = wxFONTENCODING_KOI8;
551fe3a6 525 }
58c837a4 526 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
527 {
528 // the dash is optional (or, to be exact, it is not, but
529 // several brokenmails "forget" it)
530 const wxChar *p = cs.c_str() + 3;
58c837a4 531 if ( *p == wxT('-') )
3c1866e8
VZ
532 p++;
533
534 unsigned int value;
58c837a4 535 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8 536 {
daaa6710
VZ
537 // make it 0 based and check that it is strictly positive in
538 // the process (no such thing as iso8859-0 encoding)
539 if ( (value-- > 0) &&
540 (value < wxFONTENCODING_ISO8859_MAX -
541 wxFONTENCODING_ISO8859_1) )
3c1866e8
VZ
542 {
543 // it's a valid ISO8859 encoding
daaa6710 544 value += wxFONTENCODING_ISO8859_1;
3c1866e8
VZ
545 encoding = (wxFontEncoding)value;
546 }
547 }
548 }
551fe3a6 549 else // check for Windows charsets
3c1866e8 550 {
551fe3a6
VZ
551 size_t len;
552 if ( cs.Left(7) == wxT("WINDOWS") )
553 {
554 len = 7;
555 }
556 else if ( cs.Left(2) == wxT("CP") )
3c1866e8 557 {
551fe3a6
VZ
558 len = 2;
559 }
560 else // not a Windows encoding
561 {
562 len = 0;
563 }
564
565 if ( len )
566 {
567 const wxChar *p = cs.c_str() + len;
568 if ( *p == wxT('-') )
569 p++;
570
571 int value;
572 if ( wxSscanf(p, wxT("%u"), &value) == 1 )
3c1866e8 573 {
551fe3a6 574 if ( value >= 1250 )
3c1866e8 575 {
551fe3a6
VZ
576 value -= 1250;
577 if ( value < wxFONTENCODING_CP12_MAX -
578 wxFONTENCODING_CP1250 )
579 {
580 // a valid Windows code page
581 value += wxFONTENCODING_CP1250;
582 encoding = (wxFontEncoding)value;
583 }
3c1866e8 584 }
c7821f94
VZ
585
586 switch ( value )
587 {
588 case 932:
589 encoding = wxFONTENCODING_CP932;
590 break;
591
592 case 936:
593 encoding = wxFONTENCODING_CP936;
594 break;
595
596 case 949:
597 encoding = wxFONTENCODING_CP949;
598 break;
599
600 case 950:
601 encoding = wxFONTENCODING_CP950;
602 break;
603 }
3c1866e8
VZ
604 }
605 }
606 }
607 //else: unknown
608 }
609
f6bcfd97 610#if wxUSE_GUI
3c1866e8
VZ
611 // if still no luck, ask the user - unless disabled
612 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
613 {
614 // prepare the dialog data
615
616 // the dialog title
617 wxString title(m_titleDialog);
618 if ( !title )
619 title << wxTheApp->GetAppName() << _(": unknown charset");
620
621 // the message
622 wxString msg;
f6bcfd97 623 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
624
625 // the list of choices
7beba2fc
VZ
626 size_t count = WXSIZEOF(gs_encodingDescs);
627
628 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
f6bcfd97 629 wxT("inconsitency detected - forgot to update one of the arrays?") );
3c1866e8
VZ
630
631 wxString *encodingNamesTranslated = new wxString[count];
632
11c7d5b6 633 for ( size_t i = 0; i < count; i++ )
3c1866e8 634 {
11c7d5b6 635 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
636 }
637
638 // the parent window
639 wxWindow *parent = m_windowParent;
640 if ( !parent )
641 parent = wxTheApp->GetTopWindow();
642
643 // do ask the user and get back the index in encodings table
644 int n = wxGetSingleChoiceIndex(msg, title,
645 count,
646 encodingNamesTranslated,
647 parent);
648
649 delete [] encodingNamesTranslated;
650
651 if ( n != -1 )
652 {
7beba2fc 653 encoding = gs_encodings[n];
3e7fb236 654 }
1d910ac1 655
f6bcfd97
BP
656#if wxUSE_CONFIG
657 // save the result in the config now
3e7fb236
VZ
658 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
659 {
660 wxConfigBase *config = GetConfig();
1d910ac1 661
3e7fb236
VZ
662 // remember the alt encoding for this charset - or remember that
663 // we don't know it
664 long value = n == -1 ? wxFONTENCODING_UNKNOWN : (long)encoding;
665 if ( !config->Write(charset, value) )
666 {
667 wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
1d910ac1 668 }
3e7fb236
VZ
669
670 RestorePath(pathOld);
3c1866e8 671 }
3e7fb236 672#endif // wxUSE_CONFIG
3c1866e8 673 }
f6bcfd97 674#endif // wxUSE_GUI
3c1866e8
VZ
675
676 return encoding;
677}
678
7beba2fc
VZ
679// ----------------------------------------------------------------------------
680// support for unknown encodings: we maintain a map between the
681// (platform-specific) strings identifying them and our wxFontEncodings they
682// correspond to which is used by GetFontForEncoding() function
683// ----------------------------------------------------------------------------
684
f6bcfd97
BP
685#if wxUSE_GUI
686
7beba2fc
VZ
687bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
688 wxFontEncoding encReplacement,
689 wxNativeEncodingInfo *info)
690{
691 if ( wxGetNativeFontEncoding(encReplacement, info) &&
692 wxTestFontEncoding(*info) )
693 {
f6bcfd97 694#if wxUSE_CONFIG
7beba2fc
VZ
695 // remember the mapping in the config
696 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
697
698 if ( path.IsOk() )
699 {
700 GetConfig()->Write(configEntry, info->ToString());
701 }
f6bcfd97 702#endif // wxUSE_CONFIG
7beba2fc
VZ
703 return TRUE;
704 }
705
706 return FALSE;
707}
708
f6bcfd97
BP
709#if wxUSE_GUI
710class ReentrancyBlocker
711{
712public:
713 ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
714 ~ReentrancyBlocker() { m_b = FALSE; }
715
716private:
717 bool& m_b;
718};
719#endif
720
7beba2fc
VZ
721bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
722 wxNativeEncodingInfo *info,
6648cd46 723 const wxString& facename,
7beba2fc
VZ
724 bool interactive)
725{
f6bcfd97
BP
726#if wxUSE_GUI
727 // we need a flag to prevent infinite recursion which happens, for
728 // example, when GetAltForEncoding() is called from an OnPaint() handler:
729 // in this case, wxYield() which is called from wxMessageBox() we use here
730 // will lead to another call of OnPaint() and hence to another call of
731 // GetAltForEncoding() - and it is impossible to catch this from the user
732 // code because we are called from wxFont ctor implicitly.
733
734 // assume we're always called from the main thread, so that it is safe to
735 // use a static var
736 static bool s_inGetAltForEncoding = FALSE;
737
738 if ( interactive && s_inGetAltForEncoding )
739 return FALSE;
740
741 ReentrancyBlocker blocker(s_inGetAltForEncoding);
742#endif // wxUSE_GUI
743
58c837a4 744 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 745
6648cd46
VS
746 info->facename = facename;
747
97d3f0ee
VZ
748 if ( encoding == wxFONTENCODING_DEFAULT )
749 {
750 encoding = wxFont::GetDefaultEncoding();
751 }
752
753 // if we failed to load the system default encoding, something is really
754 // wrong and we'd better stop now - otherwise we will go into endless
755 // recursion trying to create the font in the msg box with the error
756 // message
757 if ( encoding == wxFONTENCODING_SYSTEM )
758 {
73deed44 759 wxLogFatalError(_("can't load any font, aborting"));
97d3f0ee 760
73deed44 761 // wxLogFatalError doesn't return
97d3f0ee
VZ
762 }
763
a4a6984d
VZ
764 wxString configEntry,
765 encName = GetEncodingName(encoding);
1d910ac1
VZ
766 if ( !!facename )
767 {
768 configEntry = facename + _T("_");
769 }
770 configEntry += encName;
7beba2fc 771
f6bcfd97 772#if wxUSE_CONFIG
7beba2fc
VZ
773 // do we have a font spec for this encoding?
774 wxString pathOld;
775 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
776 {
777 wxConfigBase *config = GetConfig();
778
779 wxString fontinfo = config->Read(configEntry);
780
781 RestorePath(pathOld);
782
6603907d
VZ
783 // this special value means that we don't know of fonts for this
784 // encoding but, moreover, have already asked the user as well and he
785 // didn't specify any font neither
786 if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
1d910ac1 787 {
6603907d 788 interactive = FALSE;
1d910ac1 789 }
6603907d 790 else // use the info entered the last time
7beba2fc 791 {
6603907d 792 if ( !!fontinfo && !!facename )
7beba2fc 793 {
6603907d
VZ
794 // we tried to find a match with facename - now try without it
795 fontinfo = config->Read(encName);
7beba2fc 796 }
6603907d
VZ
797
798 if ( !!fontinfo )
7beba2fc 799 {
6603907d
VZ
800 if ( info->FromString(fontinfo) )
801 {
802 if ( wxTestFontEncoding(*info) )
803 {
804 // ok, got something
805 return TRUE;
806 }
807 //else: no such fonts, look for something else
808 // (should we erase the outdated value?)
809 }
810 else
811 {
812 wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
813 fontinfo.c_str());
814 }
7beba2fc 815 }
6603907d 816 //else: there is no information in config about this encoding
7beba2fc
VZ
817 }
818 }
f6bcfd97 819#endif // wxUSE_CONFIG
7beba2fc 820
3a989c8a
VZ
821 // now try to map this encoding to a compatible one which we have on this
822 // system
823 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
824 size_t count = equiv.GetCount();
825 bool foundEquivEncoding = FALSE;
c6465c96 826 wxFontEncoding equivEncoding = wxFONTENCODING_SYSTEM;
3a989c8a
VZ
827 if ( count )
828 {
829 for ( size_t i = 0; i < count && !foundEquivEncoding; i++ )
830 {
831 // don't test for encoding itself, we already know we don't have it
832 if ( equiv[i] == encoding )
833 continue;
834
835 if ( TestAltEncoding(configEntry, equiv[i], info) )
836 {
837 equivEncoding = equiv[i];
838
839 foundEquivEncoding = TRUE;
840 }
841 }
842 }
843
7beba2fc 844 // ask the user
3379ed37 845#if wxUSE_FONTDLG
7beba2fc
VZ
846 if ( interactive )
847 {
848 wxString title(m_titleDialog);
849 if ( !title )
850 title << wxTheApp->GetAppName() << _(": unknown encoding");
851
3a989c8a
VZ
852 // built the message
853 wxString encDesc = GetEncodingDescription(encoding),
854 msg;
855 if ( foundEquivEncoding )
856 {
857 // ask the user if he wants to override found alternative encoding
858 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)?"),
859 encDesc.c_str(), GetEncodingDescription(equivEncoding).c_str());
860 }
861 else
862 {
863 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)?"),
864 encDesc.c_str());
865 }
7beba2fc 866
3a989c8a
VZ
867 // the question is different in 2 cases so the answer has to be
868 // interpreted differently as well
869 int answer = foundEquivEncoding ? wxNO : wxYES;
7beba2fc
VZ
870
871 if ( wxMessageBox(msg, title,
3a989c8a
VZ
872 wxICON_QUESTION | wxYES_NO,
873 m_windowParent) == answer )
7beba2fc
VZ
874 {
875 wxFontData data;
876 data.SetEncoding(encoding);
877 data.EncodingInfo() = *info;
3a989c8a 878 wxFontDialog dialog(m_windowParent, &data);
7beba2fc
VZ
879 if ( dialog.ShowModal() == wxID_OK )
880 {
881 wxFontData retData = dialog.GetFontData();
882 wxFont font = retData.GetChosenFont();
883
11c7d5b6 884 *info = retData.EncodingInfo();
3a989c8a 885 info->encoding = retData.GetEncoding();
7beba2fc 886
f6bcfd97 887#if wxUSE_CONFIG
6603907d 888 // remember this in the config
7beba2fc
VZ
889 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
890 {
891 GetConfig()->Write(configEntry, info->ToString());
892
893 RestorePath(pathOld);
894 }
bb84929e 895#endif // wxUSE_CONFIG
7beba2fc
VZ
896
897 return TRUE;
898 }
899 //else: the user canceled the font selection dialog
900 }
6603907d
VZ
901 else
902 {
3a989c8a
VZ
903 // the user doesn't want to select a font for this encoding
904 // or selected to use equivalent encoding
905 //
6603907d
VZ
906 // remember it to avoid asking the same question again later
907#if wxUSE_CONFIG
908 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
909 {
3a989c8a
VZ
910 GetConfig()->Write
911 (
912 configEntry,
913 foundEquivEncoding ? info->ToString().c_str()
914 : FONTMAPPER_FONT_DONT_ASK
915 );
6603907d
VZ
916
917 RestorePath(pathOld);
918 }
919#endif // wxUSE_CONFIG
920 }
7beba2fc
VZ
921 }
922 //else: we're in non-interactive mode
3379ed37 923#endif // wxUSE_FONTDLG
7beba2fc 924
3a989c8a 925 return foundEquivEncoding;
7beba2fc 926}
6648cd46 927
6648cd46
VS
928bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
929 wxFontEncoding *alt_encoding,
930 const wxString& facename,
931 bool interactive)
932{
933 wxNativeEncodingInfo info;
934 bool r = GetAltForEncoding(encoding, &info, facename, interactive);
935 *alt_encoding = info.encoding;
936 return r;
937}
938
6648cd46
VS
939bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
940 const wxString& facename)
941{
942 wxNativeEncodingInfo info;
62ea506e 943
551fe3a6 944 if (wxGetNativeFontEncoding(encoding, &info))
62ea506e
VS
945 {
946 info.facename = facename;
947 return wxTestFontEncoding(info);
948 }
3ca6a5f0
BP
949
950 return FALSE;
6648cd46 951}
f6bcfd97
BP
952
953#endif // wxUSE_GUI
1e6feb95
VZ
954
955#endif // wxUSE_FONTMAP