]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmap.cpp
Unicode compilation fixes
[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
31#ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35#endif // PCH
36
37#include "wx/fontmap.h"
38#include "wx/config.h"
7beba2fc
VZ
39
40#include "wx/msgdlg.h"
41#include "wx/fontdlg.h"
3c1866e8 42#include "wx/choicdlg.h"
82545b58 43#include "wx/encconv.h"
3c1866e8
VZ
44
45// ----------------------------------------------------------------------------
46// constants
47// ----------------------------------------------------------------------------
48
49// the config paths we use
511f273f
OK
50static const wxChar* FONTMAPPER_ROOT_PATH = wxT("FontMapper");
51static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
52static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
53static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
7beba2fc
VZ
54
55// encodings supported by GetEncodingDescription
56static wxFontEncoding gs_encodings[] =
57{
58 wxFONTENCODING_ISO8859_1,
59 wxFONTENCODING_ISO8859_2,
60 wxFONTENCODING_ISO8859_3,
61 wxFONTENCODING_ISO8859_4,
62 wxFONTENCODING_ISO8859_5,
63 wxFONTENCODING_ISO8859_6,
64 wxFONTENCODING_ISO8859_7,
65 wxFONTENCODING_ISO8859_8,
66 wxFONTENCODING_ISO8859_9,
67 wxFONTENCODING_ISO8859_10,
68 wxFONTENCODING_ISO8859_11,
69 wxFONTENCODING_ISO8859_12,
70 wxFONTENCODING_ISO8859_13,
71 wxFONTENCODING_ISO8859_14,
72 wxFONTENCODING_ISO8859_15,
73 wxFONTENCODING_KOI8,
74 wxFONTENCODING_CP1250,
75 wxFONTENCODING_CP1251,
76 wxFONTENCODING_CP1252,
77 wxFONTENCODING_CP1253,
78 wxFONTENCODING_CP1254,
79 wxFONTENCODING_CP1255,
80 wxFONTENCODING_CP1256,
81 wxFONTENCODING_CP1257,
82};
83
84// the descriptions for them
85static const wxChar* gs_encodingDescs[] =
86{
87 wxTRANSLATE( "West European (ISO-8859-1/Latin 1)" ),
88 wxTRANSLATE( "Central European (ISO-8859-2/Latin 2)" ),
89 wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
90 wxTRANSLATE( "Baltic (ISO-8859-4)" ),
91 wxTRANSLATE( "Cyrillic (Latin 5)" ),
92 wxTRANSLATE( "Arabic (ISO-8859-6)" ),
93 wxTRANSLATE( "Greek (ISO-8859-7)" ),
94 wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
95 wxTRANSLATE( "Turkish (ISO-8859-9)" ),
96 wxTRANSLATE( "Baltic II (ISO-8859-10)" ),
97 wxTRANSLATE( "Thai (ISO-8859-11)" ),
98 wxTRANSLATE( "ISO-8859-12" ),
99 wxTRANSLATE( "ISO-8859-13" ),
100 wxTRANSLATE( "ISO-8859-14" ),
101 wxTRANSLATE( "West European new (ISO-8859-15/Latin 0)" ),
102 wxTRANSLATE( "KOI8-R" ),
103 wxTRANSLATE( "Windows Latin 2 (CP 1250)" ),
104 wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
105 wxTRANSLATE( "Windows Latin 1 (CP 1252)" ),
106 wxTRANSLATE( "Windows Greek (CP 1253)" ),
107 wxTRANSLATE( "Windows Turkish (CP 1254)" ),
108 wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
109 wxTRANSLATE( "Windows Arabic (CP 1256)" ),
110 wxTRANSLATE( "Windows Baltic (CP 1257)" ),
111};
112
113// and the internal names
114static const wxChar* gs_encodingNames[] =
115{
511f273f
OK
116 wxT( "iso8859-1" ),
117 wxT( "iso8859-2" ),
118 wxT( "iso8859-3" ),
119 wxT( "iso8859-4" ),
120 wxT( "iso8859-5" ),
121 wxT( "iso8859-6" ),
122 wxT( "iso8859-7" ),
123 wxT( "iso8859-8" ),
124 wxT( "iso8859-9" ),
125 wxT( "iso8859-10" ),
126 wxT( "iso8859-11" ),
127 wxT( "iso8859-12" ),
128 wxT( "iso8859-13" ),
129 wxT( "iso8859-14" ),
130 wxT( "iso8859-15" ),
131 wxT( "koi8-r" ),
132 wxT( "windows1250" ),
133 wxT( "windows1251" ),
134 wxT( "windows1252" ),
135 wxT( "windows1253" ),
136 wxT( "windows1254" ),
137 wxT( "windows1255" ),
138 wxT( "windows1256" ),
139 wxT( "windows1257" ),
7beba2fc
VZ
140};
141
142// ----------------------------------------------------------------------------
143// global data
144// ----------------------------------------------------------------------------
145
146// private object
147static wxFontMapper gs_fontMapper;
148
149// and public pointer
b40b0f5b 150wxFontMapper * wxTheFontMapper = &gs_fontMapper;
7beba2fc
VZ
151
152// ----------------------------------------------------------------------------
153// private classes
154// ----------------------------------------------------------------------------
155
156// change the config path during the lifetime of this object
157class wxFontMapperPathChanger
158{
159public:
160 wxFontMapperPathChanger(wxFontMapper *fontMapper, const wxString& path)
161 {
162 m_fontMapper = fontMapper;
163 m_ok = m_fontMapper->ChangePath(path, &m_pathOld);
164 }
165
166 bool IsOk() const { return m_ok; }
167
168 ~wxFontMapperPathChanger()
169 {
170 if ( IsOk() )
171 m_fontMapper->RestorePath(m_pathOld);
172 }
173
174private:
175 wxFontMapper *m_fontMapper;
176 bool m_ok;
177 wxString m_pathOld;
178};
3c1866e8
VZ
179
180// ============================================================================
181// implementation
182// ============================================================================
183
184// ----------------------------------------------------------------------------
185// ctor and dtor
186// ----------------------------------------------------------------------------
187
188wxFontMapper::wxFontMapper()
189{
190 m_config = NULL;
191 m_windowParent = NULL;
192}
193
194wxFontMapper::~wxFontMapper()
195{
196}
197
198// ----------------------------------------------------------------------------
199// customisation
200// ----------------------------------------------------------------------------
201
202/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
203{
204 return FONTMAPPER_ROOT_PATH;
205}
206
207void wxFontMapper::SetConfigPath(const wxString& prefix)
208{
209 wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
58c837a4 210 wxT("an absolute path should be given to "
3c1866e8
VZ
211 "wxFontMapper::SetConfigPath()") );
212
213 m_configRootPath = prefix;
214}
215
216
217// ----------------------------------------------------------------------------
218// get config object and path for it
219// ----------------------------------------------------------------------------
220
221wxConfigBase *wxFontMapper::GetConfig()
222{
223 if ( !m_config )
224 {
225 // try the default
226 m_config = wxConfig::Get();
227 }
228
229 return m_config;
230}
231
232const wxString& wxFontMapper::GetConfigPath()
233{
234 if ( !m_configRootPath )
235 {
236 // use the default
237 m_configRootPath = GetDefaultConfigPath();
238 }
239
240 return m_configRootPath;
241}
242
243bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
244{
245 wxConfigBase *config = GetConfig();
246 if ( !config )
247 return FALSE;
248
249 *pathOld = config->GetPath();
250
251 wxString path = GetConfigPath();
252 if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
253 {
254 path += wxCONFIG_PATH_SEPARATOR;
255 }
256
257 wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
58c837a4 258 wxT("should be a relative path") );
3c1866e8
VZ
259
260 path += pathNew;
261
262 config->SetPath(path);
263
264 return TRUE;
265}
266
267void wxFontMapper::RestorePath(const wxString& pathOld)
268{
269 GetConfig()->SetPath(pathOld);
270}
271
272// ----------------------------------------------------------------------------
273// charset/encoding correspondence
274// ----------------------------------------------------------------------------
275
7beba2fc
VZ
276/* static */
277wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
278{
279 size_t count = WXSIZEOF(gs_encodingDescs);
280
281 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
58c837a4 282 wxT("inconsitency detected - forgot to update one of "
7beba2fc
VZ
283 "the arrays?") );
284
285 for ( size_t i = 0; i < count; i++ )
286 {
287 if ( gs_encodings[i] == encoding )
288 {
289 return wxGetTranslation(gs_encodingDescs[i]);
290 }
291 }
292
293 wxString str;
294 str.Printf(_("Unknown encoding (%d)"), encoding);
295
296 return str;
297}
298
299/* static */
300wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
301{
302 size_t count = WXSIZEOF(gs_encodingNames);
303
304 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
58c837a4 305 wxT("inconsitency detected - forgot to update one of "
7beba2fc
VZ
306 "the arrays?") );
307
308 for ( size_t i = 0; i < count; i++ )
309 {
310 if ( gs_encodings[i] == encoding )
311 {
312 return wxGetTranslation(gs_encodingNames[i]);
313 }
314 }
315
316 wxString str;
317 str.Printf(_("unknown-%d"), encoding);
318
319 return str;
320}
321
3c1866e8
VZ
322wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
323 bool interactive)
324{
325 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
326
327 // we're going to modify it, make a copy
328 wxString cs = charset;
329
330 // first try the user-defined settings
331 wxString pathOld;
332 if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
333 {
334 wxConfigBase *config = GetConfig();
335
336 // do we have an encoding for this charset?
337 long value = config->Read(charset, -1l);
338 if ( value != -1 )
339 {
340 if ( value >= 0 && value <= wxFONTENCODING_MAX )
341 {
342 encoding = (wxFontEncoding)value;
343 }
344 else
345 {
58c837a4 346 wxLogDebug(wxT("corrupted config data - invalid encoding %ld "
3c1866e8
VZ
347 "for charset '%s'"), value, charset.c_str());
348 }
349 }
350
351 if ( encoding == wxFONTENCODING_SYSTEM )
352 {
353 // may be we have an alias?
354 config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
355
356 wxString alias = config->Read(charset);
357 if ( !!alias )
358 {
359 // yes, we do - use it instead
360 cs = alias;
361 }
362 }
363
364 RestorePath(pathOld);
365 }
366
367 // if didn't find it there, try to reckognise it ourselves
368 if ( encoding == wxFONTENCODING_SYSTEM )
369 {
370 cs.MakeUpper();
371
58c837a4 372 if ( !cs || cs == wxT("US-ASCII") )
3c1866e8 373 encoding = wxFONTENCODING_DEFAULT;
58c837a4 374 else if ( cs == wxT("KOI8-R") || cs == wxT("KOI8-U") )
3c1866e8 375 encoding = wxFONTENCODING_KOI8;
58c837a4 376 else if ( cs.Left(3) == wxT("ISO") )
3c1866e8
VZ
377 {
378 // the dash is optional (or, to be exact, it is not, but
379 // several brokenmails "forget" it)
380 const wxChar *p = cs.c_str() + 3;
58c837a4 381 if ( *p == wxT('-') )
3c1866e8
VZ
382 p++;
383
384 unsigned int value;
58c837a4 385 if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
3c1866e8
VZ
386 {
387 if ( value < wxFONTENCODING_ISO8859_MAX -
388 wxFONTENCODING_ISO8859_1 )
389 {
390 // it's a valid ISO8859 encoding
391 value += wxFONTENCODING_ISO8859_1 - 1;
392 encoding = (wxFontEncoding)value;
393 }
394 }
395 }
58c837a4 396 else if ( cs.Left(8) == wxT("WINDOWS-") )
3c1866e8
VZ
397 {
398 int value;
511f273f 399 if ( wxSscanf(cs.c_str() + 8, wxT("%u"), &value) == 1 )
3c1866e8
VZ
400 {
401 if ( value >= 1250 )
402 {
403 value -= 1250;
404 if ( value < wxFONTENCODING_CP12_MAX -
405 wxFONTENCODING_CP1250 - 1 )
406 {
407 // a valid Windows code page
408 value += wxFONTENCODING_CP1250;
409 encoding = (wxFontEncoding)value;
410 }
411 }
412 }
413 }
414 //else: unknown
415 }
416
417 // if still no luck, ask the user - unless disabled
418 if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
419 {
420 // prepare the dialog data
421
422 // the dialog title
423 wxString title(m_titleDialog);
424 if ( !title )
425 title << wxTheApp->GetAppName() << _(": unknown charset");
426
427 // the message
428 wxString msg;
429 msg.Printf(_("The charset '%s' is unknown. You may select another "
430 "charset to replace it with or choose [Cancel] if it "
431 "cannot be replaced"), charset.c_str());
432
433 // the list of choices
7beba2fc
VZ
434 size_t count = WXSIZEOF(gs_encodingDescs);
435
436 wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
58c837a4 437 wxT("inconsitency detected - forgot to update one of "
3c1866e8
VZ
438 "the arrays?") );
439
440 wxString *encodingNamesTranslated = new wxString[count];
441
11c7d5b6 442 for ( size_t i = 0; i < count; i++ )
3c1866e8 443 {
11c7d5b6 444 encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
3c1866e8
VZ
445 }
446
447 // the parent window
448 wxWindow *parent = m_windowParent;
449 if ( !parent )
450 parent = wxTheApp->GetTopWindow();
451
452 // do ask the user and get back the index in encodings table
453 int n = wxGetSingleChoiceIndex(msg, title,
454 count,
455 encodingNamesTranslated,
456 parent);
457
458 delete [] encodingNamesTranslated;
459
460 if ( n != -1 )
461 {
7beba2fc
VZ
462 // TODO save the result in the config!
463
464 encoding = gs_encodings[n];
3c1866e8
VZ
465 }
466 //else: cancelled
467 }
468
469 return encoding;
470}
471
7beba2fc
VZ
472// ----------------------------------------------------------------------------
473// support for unknown encodings: we maintain a map between the
474// (platform-specific) strings identifying them and our wxFontEncodings they
475// correspond to which is used by GetFontForEncoding() function
476// ----------------------------------------------------------------------------
477
478bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
479 wxFontEncoding encReplacement,
480 wxNativeEncodingInfo *info)
481{
482 if ( wxGetNativeFontEncoding(encReplacement, info) &&
483 wxTestFontEncoding(*info) )
484 {
485 // remember the mapping in the config
486 wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
487
488 if ( path.IsOk() )
489 {
490 GetConfig()->Write(configEntry, info->ToString());
491 }
492
493 return TRUE;
494 }
495
496 return FALSE;
497}
498
499bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
500 wxNativeEncodingInfo *info,
501 bool interactive)
502{
58c837a4 503 wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
7beba2fc 504
97d3f0ee
VZ
505 if ( encoding == wxFONTENCODING_DEFAULT )
506 {
507 encoding = wxFont::GetDefaultEncoding();
508 }
509
510 // if we failed to load the system default encoding, something is really
511 // wrong and we'd better stop now - otherwise we will go into endless
512 // recursion trying to create the font in the msg box with the error
513 // message
514 if ( encoding == wxFONTENCODING_SYSTEM )
515 {
516 wxFatalError(_("can't load any font, aborting"));
517
518 // wxFatalError doesn't return
519 }
520
7beba2fc
VZ
521 wxString configEntry = GetEncodingName(encoding);
522
523 // do we have a font spec for this encoding?
524 wxString pathOld;
525 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
526 {
527 wxConfigBase *config = GetConfig();
528
529 wxString fontinfo = config->Read(configEntry);
530
531 RestorePath(pathOld);
532
533 if ( !!fontinfo )
534 {
535 if ( info->FromString(fontinfo) )
536 {
537 if ( wxTestFontEncoding(*info) )
538 {
539 // ok, got something
540 return TRUE;
541 }
542 //else: no such fonts, look for something else
543 }
544 else
545 {
58c837a4 546 wxLogDebug(wxT("corrupted config data: string '%s' is not "
7beba2fc
VZ
547 "a valid font encoding info"), fontinfo.c_str());
548 }
549 }
550 }
551
552 // ask the user
553 if ( interactive )
554 {
555 wxString title(m_titleDialog);
556 if ( !title )
557 title << wxTheApp->GetAppName() << _(": unknown encoding");
558
559 // the message
560 wxString msg;
561 msg.Printf(_("The encoding '%s' is unknown.\n"
562 "Would you like to select a font to be used for this "
563 "encoding\n"
564 "(otherwise the text in this encoding will not be "
565 "shown correctly)?"),
566 GetEncodingDescription(encoding).c_str());
567
568 wxWindow *parent = m_windowParent;
569 if ( !parent )
570 parent = wxTheApp->GetTopWindow();
571
572 if ( wxMessageBox(msg, title,
573 wxICON_QUESTION | wxYES_NO, parent) == wxYES )
574 {
575 wxFontData data;
576 data.SetEncoding(encoding);
577 data.EncodingInfo() = *info;
578 wxFontDialog dialog(parent, &data);
579 if ( dialog.ShowModal() == wxID_OK )
580 {
581 wxFontData retData = dialog.GetFontData();
582 wxFont font = retData.GetChosenFont();
583
11c7d5b6 584 *info = retData.EncodingInfo();
7beba2fc
VZ
585
586 // remember this in the config
587 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
588 {
589 GetConfig()->Write(configEntry, info->ToString());
590
591 RestorePath(pathOld);
592 }
593
594 return TRUE;
595 }
596 //else: the user canceled the font selection dialog
597 }
598 //else: the user doesn't want to select a font
599 }
600 //else: we're in non-interactive mode
601
7beba2fc 602
82545b58
VS
603 // now try the default mappings:
604
605 wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
606 for ( unsigned i = (equiv[0] == encoding) ? 1 : 0; i < equiv.GetCount(); i++ )
607 if ( TestAltEncoding(configEntry, equiv[i], info) )
608 return TRUE;
7beba2fc
VZ
609
610 return FALSE;
611}