Files
wxWidgets/src/common/fontmap.cpp
Vadim Zeitlin 11c7d5b6d1 1. wxFontMapper seems to work for wxMSW
2. font functions moved into a separate file, duplicated code in font.cpp
   and fontdlg.cpp removed
3. wxCustomDataObject docs finished


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4382 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1999-11-06 00:43:31 +00:00

653 lines
19 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: common/fontmap.cpp
// Purpose: wxFontMapper class
// Author: Vadim Zeitlin
// Modified by:
// Created: 04.11.99
// RCS-ID: $Id$
// Copyright: (c) Vadim Zeitlin
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "fontmap.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/log.h"
#include "wx/intl.h"
#endif // PCH
#include "wx/fontmap.h"
#include "wx/config.h"
#include "wx/msgdlg.h"
#include "wx/fontdlg.h"
#include "wx/choicdlg.h"
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// the config paths we use
static const char* FONTMAPPER_ROOT_PATH = _T("FontMapper");
static const char* FONTMAPPER_CHARSET_PATH = _T("Charsets");
static const char* FONTMAPPER_CHARSET_ALIAS_PATH = _T("Aliases");
static const char* FONTMAPPER_FONT_FROM_ENCODING_PATH = _T("Encodings");
// encodings supported by GetEncodingDescription
static wxFontEncoding gs_encodings[] =
{
wxFONTENCODING_ISO8859_1,
wxFONTENCODING_ISO8859_2,
wxFONTENCODING_ISO8859_3,
wxFONTENCODING_ISO8859_4,
wxFONTENCODING_ISO8859_5,
wxFONTENCODING_ISO8859_6,
wxFONTENCODING_ISO8859_7,
wxFONTENCODING_ISO8859_8,
wxFONTENCODING_ISO8859_9,
wxFONTENCODING_ISO8859_10,
wxFONTENCODING_ISO8859_11,
wxFONTENCODING_ISO8859_12,
wxFONTENCODING_ISO8859_13,
wxFONTENCODING_ISO8859_14,
wxFONTENCODING_ISO8859_15,
wxFONTENCODING_KOI8,
wxFONTENCODING_CP1250,
wxFONTENCODING_CP1251,
wxFONTENCODING_CP1252,
wxFONTENCODING_CP1253,
wxFONTENCODING_CP1254,
wxFONTENCODING_CP1255,
wxFONTENCODING_CP1256,
wxFONTENCODING_CP1257,
};
// the descriptions for them
static const wxChar* gs_encodingDescs[] =
{
wxTRANSLATE( "West European (ISO-8859-1/Latin 1)" ),
wxTRANSLATE( "Central European (ISO-8859-2/Latin 2)" ),
wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
wxTRANSLATE( "Baltic (ISO-8859-4)" ),
wxTRANSLATE( "Cyrillic (Latin 5)" ),
wxTRANSLATE( "Arabic (ISO-8859-6)" ),
wxTRANSLATE( "Greek (ISO-8859-7)" ),
wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
wxTRANSLATE( "Turkish (ISO-8859-9)" ),
wxTRANSLATE( "Baltic II (ISO-8859-10)" ),
wxTRANSLATE( "Thai (ISO-8859-11)" ),
wxTRANSLATE( "ISO-8859-12" ),
wxTRANSLATE( "ISO-8859-13" ),
wxTRANSLATE( "ISO-8859-14" ),
wxTRANSLATE( "West European new (ISO-8859-15/Latin 0)" ),
wxTRANSLATE( "KOI8-R" ),
wxTRANSLATE( "Windows Latin 2 (CP 1250)" ),
wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
wxTRANSLATE( "Windows Latin 1 (CP 1252)" ),
wxTRANSLATE( "Windows Greek (CP 1253)" ),
wxTRANSLATE( "Windows Turkish (CP 1254)" ),
wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
wxTRANSLATE( "Windows Arabic (CP 1256)" ),
wxTRANSLATE( "Windows Baltic (CP 1257)" ),
};
// and the internal names
static const wxChar* gs_encodingNames[] =
{
"iso8859-1",
"iso8859-2",
"iso8859-3",
"iso8859-4",
"iso8859-5",
"iso8859-6",
"iso8859-7",
"iso8859-8",
"iso8859-9",
"iso8859-10",
"iso8859-11",
"iso8859-12",
"iso8859-13",
"iso8859-14",
"iso8859-15",
"koi8-r",
"windows1250",
"windows1251",
"windows1252",
"windows1253",
"windows1254",
"windows1255",
"windows1256",
"windows1257",
};
// ----------------------------------------------------------------------------
// global data
// ----------------------------------------------------------------------------
// private object
static wxFontMapper gs_fontMapper;
// and public pointer
wxFontMapper * WXDLLEXPORT wxTheFontMapper = &gs_fontMapper;
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// change the config path during the lifetime of this object
class wxFontMapperPathChanger
{
public:
wxFontMapperPathChanger(wxFontMapper *fontMapper, const wxString& path)
{
m_fontMapper = fontMapper;
m_ok = m_fontMapper->ChangePath(path, &m_pathOld);
}
bool IsOk() const { return m_ok; }
~wxFontMapperPathChanger()
{
if ( IsOk() )
m_fontMapper->RestorePath(m_pathOld);
}
private:
wxFontMapper *m_fontMapper;
bool m_ok;
wxString m_pathOld;
};
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// ctor and dtor
// ----------------------------------------------------------------------------
wxFontMapper::wxFontMapper()
{
m_config = NULL;
m_windowParent = NULL;
}
wxFontMapper::~wxFontMapper()
{
}
// ----------------------------------------------------------------------------
// customisation
// ----------------------------------------------------------------------------
/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
{
return FONTMAPPER_ROOT_PATH;
}
void wxFontMapper::SetConfigPath(const wxString& prefix)
{
wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
_T("an absolute path should be given to "
"wxFontMapper::SetConfigPath()") );
m_configRootPath = prefix;
}
// ----------------------------------------------------------------------------
// get config object and path for it
// ----------------------------------------------------------------------------
wxConfigBase *wxFontMapper::GetConfig()
{
if ( !m_config )
{
// try the default
m_config = wxConfig::Get();
}
return m_config;
}
const wxString& wxFontMapper::GetConfigPath()
{
if ( !m_configRootPath )
{
// use the default
m_configRootPath = GetDefaultConfigPath();
}
return m_configRootPath;
}
bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
{
wxConfigBase *config = GetConfig();
if ( !config )
return FALSE;
*pathOld = config->GetPath();
wxString path = GetConfigPath();
if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR )
{
path += wxCONFIG_PATH_SEPARATOR;
}
wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
_T("should be a relative path") );
path += pathNew;
config->SetPath(path);
return TRUE;
}
void wxFontMapper::RestorePath(const wxString& pathOld)
{
GetConfig()->SetPath(pathOld);
}
// ----------------------------------------------------------------------------
// charset/encoding correspondence
// ----------------------------------------------------------------------------
/* static */
wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
{
size_t count = WXSIZEOF(gs_encodingDescs);
wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
_T("inconsitency detected - forgot to update one of "
"the arrays?") );
for ( size_t i = 0; i < count; i++ )
{
if ( gs_encodings[i] == encoding )
{
return wxGetTranslation(gs_encodingDescs[i]);
}
}
wxString str;
str.Printf(_("Unknown encoding (%d)"), encoding);
return str;
}
/* static */
wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
{
size_t count = WXSIZEOF(gs_encodingNames);
wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
_T("inconsitency detected - forgot to update one of "
"the arrays?") );
for ( size_t i = 0; i < count; i++ )
{
if ( gs_encodings[i] == encoding )
{
return wxGetTranslation(gs_encodingNames[i]);
}
}
wxString str;
str.Printf(_("unknown-%d"), encoding);
return str;
}
wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
bool interactive)
{
wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
// we're going to modify it, make a copy
wxString cs = charset;
// first try the user-defined settings
wxString pathOld;
if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
{
wxConfigBase *config = GetConfig();
// do we have an encoding for this charset?
long value = config->Read(charset, -1l);
if ( value != -1 )
{
if ( value >= 0 && value <= wxFONTENCODING_MAX )
{
encoding = (wxFontEncoding)value;
}
else
{
wxLogDebug(_T("corrupted config data - invalid encoding %ld "
"for charset '%s'"), value, charset.c_str());
}
}
if ( encoding == wxFONTENCODING_SYSTEM )
{
// may be we have an alias?
config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH);
wxString alias = config->Read(charset);
if ( !!alias )
{
// yes, we do - use it instead
cs = alias;
}
}
RestorePath(pathOld);
}
// if didn't find it there, try to reckognise it ourselves
if ( encoding == wxFONTENCODING_SYSTEM )
{
cs.MakeUpper();
if ( !cs || cs == _T("US-ASCII") )
encoding = wxFONTENCODING_DEFAULT;
else if ( cs == _T("KOI8-R") || cs == _T("KOI8-U") )
encoding = wxFONTENCODING_KOI8;
else if ( cs.Left(3) == _T("ISO") )
{
// the dash is optional (or, to be exact, it is not, but
// several brokenmails "forget" it)
const wxChar *p = cs.c_str() + 3;
if ( *p == _T('-') )
p++;
unsigned int value;
if ( wxSscanf(p, _T("8859-%u"), &value) == 1 )
{
if ( value < wxFONTENCODING_ISO8859_MAX -
wxFONTENCODING_ISO8859_1 )
{
// it's a valid ISO8859 encoding
value += wxFONTENCODING_ISO8859_1 - 1;
encoding = (wxFontEncoding)value;
}
}
}
else if ( cs.Left(8) == _T("WINDOWS-") )
{
int value;
if ( wxSscanf(cs.c_str() + 8, "%u", &value) == 1 )
{
if ( value >= 1250 )
{
value -= 1250;
if ( value < wxFONTENCODING_CP12_MAX -
wxFONTENCODING_CP1250 - 1 )
{
// a valid Windows code page
value += wxFONTENCODING_CP1250;
encoding = (wxFontEncoding)value;
}
}
}
}
//else: unknown
}
// if still no luck, ask the user - unless disabled
if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
{
// prepare the dialog data
// the dialog title
wxString title(m_titleDialog);
if ( !title )
title << wxTheApp->GetAppName() << _(": unknown charset");
// the message
wxString msg;
msg.Printf(_("The charset '%s' is unknown. You may select another "
"charset to replace it with or choose [Cancel] if it "
"cannot be replaced"), charset.c_str());
// the list of choices
size_t count = WXSIZEOF(gs_encodingDescs);
wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
_T("inconsitency detected - forgot to update one of "
"the arrays?") );
wxString *encodingNamesTranslated = new wxString[count];
for ( size_t i = 0; i < count; i++ )
{
encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]);
}
// the parent window
wxWindow *parent = m_windowParent;
if ( !parent )
parent = wxTheApp->GetTopWindow();
// do ask the user and get back the index in encodings table
int n = wxGetSingleChoiceIndex(msg, title,
count,
encodingNamesTranslated,
parent);
delete [] encodingNamesTranslated;
if ( n != -1 )
{
// TODO save the result in the config!
encoding = gs_encodings[n];
}
//else: cancelled
}
return encoding;
}
// ----------------------------------------------------------------------------
// support for unknown encodings: we maintain a map between the
// (platform-specific) strings identifying them and our wxFontEncodings they
// correspond to which is used by GetFontForEncoding() function
// ----------------------------------------------------------------------------
bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
wxFontEncoding encReplacement,
wxNativeEncodingInfo *info)
{
if ( wxGetNativeFontEncoding(encReplacement, info) &&
wxTestFontEncoding(*info) )
{
// remember the mapping in the config
wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
if ( path.IsOk() )
{
GetConfig()->Write(configEntry, info->ToString());
}
return TRUE;
}
return FALSE;
}
bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
wxNativeEncodingInfo *info,
bool interactive)
{
wxCHECK_MSG( info, FALSE, _T("bad pointer in GetAltForEncoding") );
wxString configEntry = GetEncodingName(encoding);
// do we have a font spec for this encoding?
wxString pathOld;
if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
{
wxConfigBase *config = GetConfig();
wxString fontinfo = config->Read(configEntry);
RestorePath(pathOld);
if ( !!fontinfo )
{
if ( info->FromString(fontinfo) )
{
if ( wxTestFontEncoding(*info) )
{
// ok, got something
return TRUE;
}
//else: no such fonts, look for something else
}
else
{
wxLogDebug(_T("corrupted config data: string '%s' is not "
"a valid font encoding info"), fontinfo.c_str());
}
}
}
// ask the user
if ( interactive )
{
wxString title(m_titleDialog);
if ( !title )
title << wxTheApp->GetAppName() << _(": unknown encoding");
// the message
wxString msg;
msg.Printf(_("The encoding '%s' is unknown.\n"
"Would you like to select a font to be used for this "
"encoding\n"
"(otherwise the text in this encoding will not be "
"shown correctly)?"),
GetEncodingDescription(encoding).c_str());
wxWindow *parent = m_windowParent;
if ( !parent )
parent = wxTheApp->GetTopWindow();
if ( wxMessageBox(msg, title,
wxICON_QUESTION | wxYES_NO, parent) == wxYES )
{
wxFontData data;
data.SetEncoding(encoding);
data.EncodingInfo() = *info;
wxFontDialog dialog(parent, &data);
if ( dialog.ShowModal() == wxID_OK )
{
wxFontData retData = dialog.GetFontData();
wxFont font = retData.GetChosenFont();
*info = retData.EncodingInfo();
// remember this in the config
if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
{
GetConfig()->Write(configEntry, info->ToString());
RestorePath(pathOld);
}
return TRUE;
}
//else: the user canceled the font selection dialog
}
//else: the user doesn't want to select a font
}
//else: we're in non-interactive mode
// now try the default mappings
switch ( encoding )
{
case wxFONTENCODING_ISO8859_15:
// iso8859-15 is slightly modified iso8859-1
if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_1, info) )
return TRUE;
// fall through
case wxFONTENCODING_ISO8859_1:
// iso8859-1 is identical to CP1252
if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1252, info) )
return TRUE;
break;
case wxFONTENCODING_CP1252:
if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_1, info) )
return TRUE;
break;
// iso8859-13 is quite similar to WinBaltic
case wxFONTENCODING_ISO8859_13:
if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1257, info) )
return TRUE;
break;
case wxFONTENCODING_CP1257:
if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_13, info) )
return TRUE;
break;
// iso8859-8 is almost identical to WinHebrew
case wxFONTENCODING_ISO8859_8:
if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1255, info) )
return TRUE;
break;
case wxFONTENCODING_CP1255:
if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_8, info) )
return TRUE;
break;
// and iso8859-7 is not too different from WinGreek
case wxFONTENCODING_ISO8859_7:
if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1253, info) )
return TRUE;
break;
case wxFONTENCODING_CP1253:
if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_7, info) )
return TRUE;
break;
default:
// TODO add other mappings...
;
}
return FALSE;
}