1. added encodings handling to XRC, so that it is possible
to load resources that don't use English+wxLocale for i18n 2. expat interface can now read non-utf-8 encodings as well git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13783 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -300,10 +300,11 @@ wxList *wxXmlDocument::sm_handlers = NULL;
|
||||
|
||||
|
||||
|
||||
wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type)
|
||||
wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
: wxObject(), m_root(NULL)
|
||||
{
|
||||
if (!Load(filename, io_type))
|
||||
if (!Load(filename, io_type, encoding))
|
||||
{
|
||||
wxDELETE(m_root);
|
||||
}
|
||||
@@ -311,10 +312,11 @@ wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type)
|
||||
|
||||
|
||||
|
||||
wxXmlDocument::wxXmlDocument(wxInputStream& stream, wxXmlIOType io_type)
|
||||
wxXmlDocument::wxXmlDocument(wxInputStream& stream, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
: wxObject(), m_root(NULL)
|
||||
{
|
||||
if (!Load(stream, io_type))
|
||||
if (!Load(stream, io_type, encoding))
|
||||
{
|
||||
wxDELETE(m_root);
|
||||
}
|
||||
@@ -341,22 +343,33 @@ wxXmlDocument& wxXmlDocument::operator=(const wxXmlDocument& doc)
|
||||
void wxXmlDocument::DoCopy(const wxXmlDocument& doc)
|
||||
{
|
||||
m_version = doc.m_version;
|
||||
#if !wxUSE_UNICODE
|
||||
m_encoding = doc.m_encoding;
|
||||
#endif
|
||||
m_fileEncoding = doc.m_fileEncoding;
|
||||
m_root = new wxXmlNode(*doc.m_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxXmlDocument::Load(const wxString& filename, wxXmlIOType io_type)
|
||||
bool wxXmlDocument::Load(const wxString& filename, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
{
|
||||
wxFileInputStream stream(filename);
|
||||
return Load(stream, io_type);
|
||||
return Load(stream, io_type, encoding);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
|
||||
bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
(void)encoding;
|
||||
#else
|
||||
m_encoding = encoding;
|
||||
#endif
|
||||
|
||||
wxNode *n = sm_handlers->GetFirst();
|
||||
while (n)
|
||||
{
|
||||
@@ -365,7 +378,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
|
||||
if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) &&
|
||||
h->CanLoad(stream))
|
||||
{
|
||||
return h->Load(stream, *this);
|
||||
return h->Load(stream, *this, encoding);
|
||||
}
|
||||
n = n->GetNext();
|
||||
}
|
||||
|
@@ -101,7 +101,12 @@ bool wxXmlIOHandlerBin::Save(wxOutputStream& stream, const wxXmlDocument& doc)
|
||||
{
|
||||
WriteHeader(stream, "XMLBIN ");
|
||||
wxDataOutputStream ds(stream);
|
||||
ds << doc.GetVersion() << doc.GetEncoding();
|
||||
ds << doc.GetVersion();
|
||||
#if wxUSE_UNICODE
|
||||
ds << wxString(wxT("UTF-8"));
|
||||
#else
|
||||
ds << doc.GetEncoding();
|
||||
#endif
|
||||
SaveBinNode(ds, doc.GetRoot());
|
||||
return stream.LastError() == wxSTREAM_NOERROR;
|
||||
}
|
||||
@@ -142,7 +147,8 @@ static wxXmlNode *LoadBinNode(wxDataInputStream& ds, wxXmlNode *parent)
|
||||
|
||||
|
||||
|
||||
bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
ReadHeader(stream);
|
||||
wxDataInputStream ds(stream);
|
||||
@@ -151,7 +157,7 @@ bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
ds >> tmp;
|
||||
doc.SetVersion(tmp);
|
||||
ds >> tmp;
|
||||
doc.SetEncoding(tmp);
|
||||
doc.SetFileEncoding(tmp);
|
||||
|
||||
doc.SetRoot(LoadBinNode(ds, NULL));
|
||||
|
||||
|
@@ -48,11 +48,12 @@ bool wxXmlIOHandlerBinZ::Save(wxOutputStream& stream, const wxXmlDocument& doc)
|
||||
|
||||
|
||||
|
||||
bool wxXmlIOHandlerBinZ::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
bool wxXmlIOHandlerBinZ::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
ReadHeader(stream);
|
||||
wxZlibInputStream costr(stream);
|
||||
return wxXmlIOHandlerBin::Load(costr, doc);
|
||||
return wxXmlIOHandlerBin::Load(costr, doc, encoding);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -30,23 +30,32 @@
|
||||
/*
|
||||
|
||||
FIXME:
|
||||
|
||||
- handle unknown encodings
|
||||
- process all elements, including CDATA
|
||||
- XRC resources should automatically select desired encoding based on
|
||||
runtime environment (?) (would need BIN and BINZ formats modification,
|
||||
too)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// converts Expat-produced string in UTF-8 into wxString.
|
||||
inline static wxString CharToString(const char *s, size_t len = wxSTRING_MAXLEN)
|
||||
inline static wxString CharToString(wxMBConv *conv,
|
||||
const char *s, size_t len = wxSTRING_MAXLEN)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
(void)conv;
|
||||
return wxString(s, wxConvUTF8, len);
|
||||
#else
|
||||
return wxString(s, len);
|
||||
if ( conv )
|
||||
{
|
||||
size_t nLen = (len != wxSTRING_MAXLEN) ? len :
|
||||
nLen = wxConvUTF8.MB2WC((wchar_t*) NULL, s, 0);
|
||||
|
||||
wchar_t *buf = new wchar_t[nLen+1];
|
||||
wxConvUTF8.MB2WC(buf, s, nLen);
|
||||
buf[nLen] = 0;
|
||||
return wxString(buf, *conv, len);
|
||||
delete[] buf;
|
||||
}
|
||||
else
|
||||
return wxString(s, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -62,21 +71,23 @@ bool wxXmlIOHandlerExpat::CanLoad(wxInputStream& stream)
|
||||
|
||||
struct wxXmlParsingContext
|
||||
{
|
||||
wxMBConv *conv;
|
||||
|
||||
wxXmlNode *root;
|
||||
wxXmlNode *node;
|
||||
wxXmlNode *lastAsText;
|
||||
wxString encoding;
|
||||
wxString version;
|
||||
wxString encoding;
|
||||
wxString version;
|
||||
};
|
||||
|
||||
static void StartElementHnd(void *userData, const char *name, const char **atts)
|
||||
{
|
||||
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, CharToString(name));
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, CharToString(ctx->conv, name));
|
||||
const char **a = atts;
|
||||
while (*a)
|
||||
{
|
||||
node->AddProperty(CharToString(a[0]), CharToString(a[1]));
|
||||
node->AddProperty(CharToString(ctx->conv, a[0]), CharToString(ctx->conv, a[1]));
|
||||
a += 2;
|
||||
}
|
||||
if (ctx->root == NULL)
|
||||
@@ -106,7 +117,7 @@ static void TextHnd(void *userData, const char *s, int len)
|
||||
if (ctx->lastAsText)
|
||||
{
|
||||
ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() +
|
||||
CharToString(buf));
|
||||
CharToString(ctx->conv, buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -120,7 +131,7 @@ static void TextHnd(void *userData, const char *s, int len)
|
||||
if (!whiteOnly)
|
||||
{
|
||||
ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"),
|
||||
CharToString(buf));
|
||||
CharToString(ctx->conv, buf));
|
||||
ctx->node->AddChild(ctx->lastAsText);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +149,7 @@ static void CommentHnd(void *userData, const char *data)
|
||||
// the root element (e.g. wxDesigner's output). We ignore such
|
||||
// comments, no big deal...
|
||||
ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE,
|
||||
wxT("comment"), CharToString(data)));
|
||||
wxT("comment"), CharToString(ctx->conv, data)));
|
||||
}
|
||||
ctx->lastAsText = NULL;
|
||||
}
|
||||
@@ -150,7 +161,7 @@ static void DefaultHnd(void *userData, const char *s, int len)
|
||||
{
|
||||
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
|
||||
|
||||
wxString buf = CharToString(s, (size_t)len);
|
||||
wxString buf = CharToString(ctx->conv, s, (size_t)len);
|
||||
int pos;
|
||||
pos = buf.Find(wxT("encoding="));
|
||||
if (pos != wxNOT_FOUND)
|
||||
@@ -161,7 +172,36 @@ static void DefaultHnd(void *userData, const char *s, int len)
|
||||
}
|
||||
}
|
||||
|
||||
bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
static int UnknownEncodingHnd(void * WXUNUSED(encodingHandlerData),
|
||||
const XML_Char *name, XML_Encoding *info)
|
||||
{
|
||||
// We must build conversion table for expat. The easiest way to do so
|
||||
// is to let wxCSConv convert as string containing all characters to
|
||||
// wide character representation:
|
||||
wxCSConv conv(name);
|
||||
char mbBuf[255];
|
||||
wchar_t wcBuf[255];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 255; i++)
|
||||
mbBuf[i] = i+1;
|
||||
mbBuf[255] = 0;
|
||||
conv.MB2WC(wcBuf, mbBuf, 255);
|
||||
wcBuf[255] = 0;
|
||||
|
||||
info->map[0] = 0;
|
||||
for (i = 0; i < 255; i++)
|
||||
info->map[i+1] = (int)wcBuf[i];
|
||||
|
||||
info->data = NULL;
|
||||
info->convert = NULL;
|
||||
info->release = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
const size_t BUFSIZE = 1024;
|
||||
char buf[BUFSIZE];
|
||||
@@ -170,11 +210,19 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
ctx.root = ctx.node = NULL;
|
||||
ctx.encoding = wxT("UTF-8"); // default in absence of encoding=""
|
||||
ctx.conv = NULL;
|
||||
#if !wxUSE_UNICODE
|
||||
if ( encoding != wxT("UTF-8") && encoding != wxT("utf-8") )
|
||||
ctx.conv = new wxCSConv(encoding);
|
||||
#endif
|
||||
|
||||
XML_SetUserData(parser, (void*)&ctx);
|
||||
XML_SetElementHandler(parser, StartElementHnd, EndElementHnd);
|
||||
XML_SetCharacterDataHandler(parser, TextHnd);
|
||||
XML_SetCommentHandler(parser, CommentHnd);
|
||||
XML_SetDefaultHandler(parser, DefaultHnd);
|
||||
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
|
||||
|
||||
do
|
||||
{
|
||||
@@ -190,9 +238,14 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
} while (!done);
|
||||
|
||||
doc.SetVersion(ctx.version);
|
||||
doc.SetEncoding(ctx.encoding);
|
||||
doc.SetFileEncoding(ctx.encoding);
|
||||
doc.SetRoot(ctx.root);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
#if !wxUSE_UNICODE
|
||||
if ( ctx.conv )
|
||||
delete ctx.conv;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -100,9 +100,9 @@ bool wxXmlResource::Load(const wxString& filemask)
|
||||
{
|
||||
#if wxUSE_FILESYSTEM
|
||||
if (filemask.Lower().Matches(wxT("*.zip")) ||
|
||||
filemask.Lower().Matches(wxT("*.rsc")))
|
||||
filemask.Lower().Matches(wxT("*.xrs")))
|
||||
{
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xmb"));
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xmlbin"));
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xrc"));
|
||||
}
|
||||
else
|
||||
@@ -286,6 +286,17 @@ void wxXmlResource::UpdateResources()
|
||||
wxFileSystem fsys;
|
||||
# endif
|
||||
|
||||
wxString encoding(wxT("UTF-8"));
|
||||
#if !wxUSE_UNICODE && wxUSE_INTL
|
||||
if ( (GetFlags() & wxXRC_USE_LOCALE) == 0 )
|
||||
{
|
||||
// In case we are not using wxLocale to translate strings, convert the strings
|
||||
// GUI's charset. This must not be done when wxXRC_USE_LOCALE is on, because
|
||||
// it could break wxGetTranslation lookup.
|
||||
encoding = wxLocale::GetSystemEncodingName();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < m_data.GetCount(); i++)
|
||||
{
|
||||
modif = (m_data[i].Doc == NULL);
|
||||
@@ -305,7 +316,7 @@ void wxXmlResource::UpdateResources()
|
||||
|
||||
if (modif)
|
||||
{
|
||||
wxInputStream *stream = NULL;
|
||||
wxInputStream *stream = NULL;
|
||||
|
||||
# if wxUSE_FILESYSTEM
|
||||
file = fsys.OpenFile(m_data[i].File);
|
||||
@@ -320,9 +331,10 @@ void wxXmlResource::UpdateResources()
|
||||
delete m_data[i].Doc;
|
||||
m_data[i].Doc = new wxXmlDocument;
|
||||
}
|
||||
if (!stream || !m_data[i].Doc->Load(*stream))
|
||||
if (!stream || !m_data[i].Doc->Load(*stream, wxXML_IO_AUTO, encoding))
|
||||
{
|
||||
wxLogError(_("Cannot load resources from file '%s'."), m_data[i].File.c_str());
|
||||
wxLogError(_("Cannot load resources from file '%s'."),
|
||||
m_data[i].File.c_str());
|
||||
wxDELETE(m_data[i].Doc);
|
||||
}
|
||||
else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource"))
|
||||
|
@@ -44,22 +44,22 @@ static void OutputStringEnt(wxOutputStream& stream, const wxString& str)
|
||||
{
|
||||
wxString buf;
|
||||
size_t i, last, len;
|
||||
char c;
|
||||
wxChar c;
|
||||
|
||||
len = str.Len();
|
||||
last = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
c = str.GetChar(i);
|
||||
if (c == '<' || c == '>' ||
|
||||
(c == '&' && str.Mid(i+1, 4) != wxT("amp;")))
|
||||
if (c == wxT('<') || c == wxT('>') ||
|
||||
(c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;")))
|
||||
{
|
||||
OutputString(stream, str.Mid(last, i - last));
|
||||
switch (c)
|
||||
{
|
||||
case '<': OutputString(stream, wxT("<")); break;
|
||||
case '>': OutputString(stream, wxT(">")); break;
|
||||
case '&': OutputString(stream, wxT("&")); break;
|
||||
case wxT('<'): OutputString(stream, wxT("<")); break;
|
||||
case wxT('>'): OutputString(stream, wxT(">")); break;
|
||||
case wxT('&'): OutputString(stream, wxT("&")); break;
|
||||
default: break;
|
||||
}
|
||||
last = i + 1;
|
||||
|
@@ -300,10 +300,11 @@ wxList *wxXmlDocument::sm_handlers = NULL;
|
||||
|
||||
|
||||
|
||||
wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type)
|
||||
wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
: wxObject(), m_root(NULL)
|
||||
{
|
||||
if (!Load(filename, io_type))
|
||||
if (!Load(filename, io_type, encoding))
|
||||
{
|
||||
wxDELETE(m_root);
|
||||
}
|
||||
@@ -311,10 +312,11 @@ wxXmlDocument::wxXmlDocument(const wxString& filename, wxXmlIOType io_type)
|
||||
|
||||
|
||||
|
||||
wxXmlDocument::wxXmlDocument(wxInputStream& stream, wxXmlIOType io_type)
|
||||
wxXmlDocument::wxXmlDocument(wxInputStream& stream, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
: wxObject(), m_root(NULL)
|
||||
{
|
||||
if (!Load(stream, io_type))
|
||||
if (!Load(stream, io_type, encoding))
|
||||
{
|
||||
wxDELETE(m_root);
|
||||
}
|
||||
@@ -341,22 +343,33 @@ wxXmlDocument& wxXmlDocument::operator=(const wxXmlDocument& doc)
|
||||
void wxXmlDocument::DoCopy(const wxXmlDocument& doc)
|
||||
{
|
||||
m_version = doc.m_version;
|
||||
#if !wxUSE_UNICODE
|
||||
m_encoding = doc.m_encoding;
|
||||
#endif
|
||||
m_fileEncoding = doc.m_fileEncoding;
|
||||
m_root = new wxXmlNode(*doc.m_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxXmlDocument::Load(const wxString& filename, wxXmlIOType io_type)
|
||||
bool wxXmlDocument::Load(const wxString& filename, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
{
|
||||
wxFileInputStream stream(filename);
|
||||
return Load(stream, io_type);
|
||||
return Load(stream, io_type, encoding);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
|
||||
bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type,
|
||||
const wxString& encoding)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
(void)encoding;
|
||||
#else
|
||||
m_encoding = encoding;
|
||||
#endif
|
||||
|
||||
wxNode *n = sm_handlers->GetFirst();
|
||||
while (n)
|
||||
{
|
||||
@@ -365,7 +378,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
|
||||
if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) &&
|
||||
h->CanLoad(stream))
|
||||
{
|
||||
return h->Load(stream, *this);
|
||||
return h->Load(stream, *this, encoding);
|
||||
}
|
||||
n = n->GetNext();
|
||||
}
|
||||
|
@@ -101,7 +101,12 @@ bool wxXmlIOHandlerBin::Save(wxOutputStream& stream, const wxXmlDocument& doc)
|
||||
{
|
||||
WriteHeader(stream, "XMLBIN ");
|
||||
wxDataOutputStream ds(stream);
|
||||
ds << doc.GetVersion() << doc.GetEncoding();
|
||||
ds << doc.GetVersion();
|
||||
#if wxUSE_UNICODE
|
||||
ds << wxString(wxT("UTF-8"));
|
||||
#else
|
||||
ds << doc.GetEncoding();
|
||||
#endif
|
||||
SaveBinNode(ds, doc.GetRoot());
|
||||
return stream.LastError() == wxSTREAM_NOERROR;
|
||||
}
|
||||
@@ -142,7 +147,8 @@ static wxXmlNode *LoadBinNode(wxDataInputStream& ds, wxXmlNode *parent)
|
||||
|
||||
|
||||
|
||||
bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
ReadHeader(stream);
|
||||
wxDataInputStream ds(stream);
|
||||
@@ -151,7 +157,7 @@ bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
ds >> tmp;
|
||||
doc.SetVersion(tmp);
|
||||
ds >> tmp;
|
||||
doc.SetEncoding(tmp);
|
||||
doc.SetFileEncoding(tmp);
|
||||
|
||||
doc.SetRoot(LoadBinNode(ds, NULL));
|
||||
|
||||
|
@@ -48,11 +48,12 @@ bool wxXmlIOHandlerBinZ::Save(wxOutputStream& stream, const wxXmlDocument& doc)
|
||||
|
||||
|
||||
|
||||
bool wxXmlIOHandlerBinZ::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
bool wxXmlIOHandlerBinZ::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
ReadHeader(stream);
|
||||
wxZlibInputStream costr(stream);
|
||||
return wxXmlIOHandlerBin::Load(costr, doc);
|
||||
return wxXmlIOHandlerBin::Load(costr, doc, encoding);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -30,23 +30,32 @@
|
||||
/*
|
||||
|
||||
FIXME:
|
||||
|
||||
- handle unknown encodings
|
||||
- process all elements, including CDATA
|
||||
- XRC resources should automatically select desired encoding based on
|
||||
runtime environment (?) (would need BIN and BINZ formats modification,
|
||||
too)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// converts Expat-produced string in UTF-8 into wxString.
|
||||
inline static wxString CharToString(const char *s, size_t len = wxSTRING_MAXLEN)
|
||||
inline static wxString CharToString(wxMBConv *conv,
|
||||
const char *s, size_t len = wxSTRING_MAXLEN)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
(void)conv;
|
||||
return wxString(s, wxConvUTF8, len);
|
||||
#else
|
||||
return wxString(s, len);
|
||||
if ( conv )
|
||||
{
|
||||
size_t nLen = (len != wxSTRING_MAXLEN) ? len :
|
||||
nLen = wxConvUTF8.MB2WC((wchar_t*) NULL, s, 0);
|
||||
|
||||
wchar_t *buf = new wchar_t[nLen+1];
|
||||
wxConvUTF8.MB2WC(buf, s, nLen);
|
||||
buf[nLen] = 0;
|
||||
return wxString(buf, *conv, len);
|
||||
delete[] buf;
|
||||
}
|
||||
else
|
||||
return wxString(s, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -62,21 +71,23 @@ bool wxXmlIOHandlerExpat::CanLoad(wxInputStream& stream)
|
||||
|
||||
struct wxXmlParsingContext
|
||||
{
|
||||
wxMBConv *conv;
|
||||
|
||||
wxXmlNode *root;
|
||||
wxXmlNode *node;
|
||||
wxXmlNode *lastAsText;
|
||||
wxString encoding;
|
||||
wxString version;
|
||||
wxString encoding;
|
||||
wxString version;
|
||||
};
|
||||
|
||||
static void StartElementHnd(void *userData, const char *name, const char **atts)
|
||||
{
|
||||
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, CharToString(name));
|
||||
wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, CharToString(ctx->conv, name));
|
||||
const char **a = atts;
|
||||
while (*a)
|
||||
{
|
||||
node->AddProperty(CharToString(a[0]), CharToString(a[1]));
|
||||
node->AddProperty(CharToString(ctx->conv, a[0]), CharToString(ctx->conv, a[1]));
|
||||
a += 2;
|
||||
}
|
||||
if (ctx->root == NULL)
|
||||
@@ -106,7 +117,7 @@ static void TextHnd(void *userData, const char *s, int len)
|
||||
if (ctx->lastAsText)
|
||||
{
|
||||
ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() +
|
||||
CharToString(buf));
|
||||
CharToString(ctx->conv, buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -120,7 +131,7 @@ static void TextHnd(void *userData, const char *s, int len)
|
||||
if (!whiteOnly)
|
||||
{
|
||||
ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"),
|
||||
CharToString(buf));
|
||||
CharToString(ctx->conv, buf));
|
||||
ctx->node->AddChild(ctx->lastAsText);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +149,7 @@ static void CommentHnd(void *userData, const char *data)
|
||||
// the root element (e.g. wxDesigner's output). We ignore such
|
||||
// comments, no big deal...
|
||||
ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE,
|
||||
wxT("comment"), CharToString(data)));
|
||||
wxT("comment"), CharToString(ctx->conv, data)));
|
||||
}
|
||||
ctx->lastAsText = NULL;
|
||||
}
|
||||
@@ -150,7 +161,7 @@ static void DefaultHnd(void *userData, const char *s, int len)
|
||||
{
|
||||
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
|
||||
|
||||
wxString buf = CharToString(s, (size_t)len);
|
||||
wxString buf = CharToString(ctx->conv, s, (size_t)len);
|
||||
int pos;
|
||||
pos = buf.Find(wxT("encoding="));
|
||||
if (pos != wxNOT_FOUND)
|
||||
@@ -161,7 +172,36 @@ static void DefaultHnd(void *userData, const char *s, int len)
|
||||
}
|
||||
}
|
||||
|
||||
bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
static int UnknownEncodingHnd(void * WXUNUSED(encodingHandlerData),
|
||||
const XML_Char *name, XML_Encoding *info)
|
||||
{
|
||||
// We must build conversion table for expat. The easiest way to do so
|
||||
// is to let wxCSConv convert as string containing all characters to
|
||||
// wide character representation:
|
||||
wxCSConv conv(name);
|
||||
char mbBuf[255];
|
||||
wchar_t wcBuf[255];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 255; i++)
|
||||
mbBuf[i] = i+1;
|
||||
mbBuf[255] = 0;
|
||||
conv.MB2WC(wcBuf, mbBuf, 255);
|
||||
wcBuf[255] = 0;
|
||||
|
||||
info->map[0] = 0;
|
||||
for (i = 0; i < 255; i++)
|
||||
info->map[i+1] = (int)wcBuf[i];
|
||||
|
||||
info->data = NULL;
|
||||
info->convert = NULL;
|
||||
info->release = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc,
|
||||
const wxString& encoding)
|
||||
{
|
||||
const size_t BUFSIZE = 1024;
|
||||
char buf[BUFSIZE];
|
||||
@@ -170,11 +210,19 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
ctx.root = ctx.node = NULL;
|
||||
ctx.encoding = wxT("UTF-8"); // default in absence of encoding=""
|
||||
ctx.conv = NULL;
|
||||
#if !wxUSE_UNICODE
|
||||
if ( encoding != wxT("UTF-8") && encoding != wxT("utf-8") )
|
||||
ctx.conv = new wxCSConv(encoding);
|
||||
#endif
|
||||
|
||||
XML_SetUserData(parser, (void*)&ctx);
|
||||
XML_SetElementHandler(parser, StartElementHnd, EndElementHnd);
|
||||
XML_SetCharacterDataHandler(parser, TextHnd);
|
||||
XML_SetCommentHandler(parser, CommentHnd);
|
||||
XML_SetDefaultHandler(parser, DefaultHnd);
|
||||
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
|
||||
|
||||
do
|
||||
{
|
||||
@@ -190,9 +238,14 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
|
||||
} while (!done);
|
||||
|
||||
doc.SetVersion(ctx.version);
|
||||
doc.SetEncoding(ctx.encoding);
|
||||
doc.SetFileEncoding(ctx.encoding);
|
||||
doc.SetRoot(ctx.root);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
#if !wxUSE_UNICODE
|
||||
if ( ctx.conv )
|
||||
delete ctx.conv;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -100,9 +100,9 @@ bool wxXmlResource::Load(const wxString& filemask)
|
||||
{
|
||||
#if wxUSE_FILESYSTEM
|
||||
if (filemask.Lower().Matches(wxT("*.zip")) ||
|
||||
filemask.Lower().Matches(wxT("*.rsc")))
|
||||
filemask.Lower().Matches(wxT("*.xrs")))
|
||||
{
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xmb"));
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xmlbin"));
|
||||
rt = rt && Load(fnd + wxT("#zip:*.xrc"));
|
||||
}
|
||||
else
|
||||
@@ -286,6 +286,17 @@ void wxXmlResource::UpdateResources()
|
||||
wxFileSystem fsys;
|
||||
# endif
|
||||
|
||||
wxString encoding(wxT("UTF-8"));
|
||||
#if !wxUSE_UNICODE && wxUSE_INTL
|
||||
if ( (GetFlags() & wxXRC_USE_LOCALE) == 0 )
|
||||
{
|
||||
// In case we are not using wxLocale to translate strings, convert the strings
|
||||
// GUI's charset. This must not be done when wxXRC_USE_LOCALE is on, because
|
||||
// it could break wxGetTranslation lookup.
|
||||
encoding = wxLocale::GetSystemEncodingName();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < m_data.GetCount(); i++)
|
||||
{
|
||||
modif = (m_data[i].Doc == NULL);
|
||||
@@ -305,7 +316,7 @@ void wxXmlResource::UpdateResources()
|
||||
|
||||
if (modif)
|
||||
{
|
||||
wxInputStream *stream = NULL;
|
||||
wxInputStream *stream = NULL;
|
||||
|
||||
# if wxUSE_FILESYSTEM
|
||||
file = fsys.OpenFile(m_data[i].File);
|
||||
@@ -320,9 +331,10 @@ void wxXmlResource::UpdateResources()
|
||||
delete m_data[i].Doc;
|
||||
m_data[i].Doc = new wxXmlDocument;
|
||||
}
|
||||
if (!stream || !m_data[i].Doc->Load(*stream))
|
||||
if (!stream || !m_data[i].Doc->Load(*stream, wxXML_IO_AUTO, encoding))
|
||||
{
|
||||
wxLogError(_("Cannot load resources from file '%s'."), m_data[i].File.c_str());
|
||||
wxLogError(_("Cannot load resources from file '%s'."),
|
||||
m_data[i].File.c_str());
|
||||
wxDELETE(m_data[i].Doc);
|
||||
}
|
||||
else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource"))
|
||||
|
@@ -44,22 +44,22 @@ static void OutputStringEnt(wxOutputStream& stream, const wxString& str)
|
||||
{
|
||||
wxString buf;
|
||||
size_t i, last, len;
|
||||
char c;
|
||||
wxChar c;
|
||||
|
||||
len = str.Len();
|
||||
last = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
c = str.GetChar(i);
|
||||
if (c == '<' || c == '>' ||
|
||||
(c == '&' && str.Mid(i+1, 4) != wxT("amp;")))
|
||||
if (c == wxT('<') || c == wxT('>') ||
|
||||
(c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;")))
|
||||
{
|
||||
OutputString(stream, str.Mid(last, i - last));
|
||||
switch (c)
|
||||
{
|
||||
case '<': OutputString(stream, wxT("<")); break;
|
||||
case '>': OutputString(stream, wxT(">")); break;
|
||||
case '&': OutputString(stream, wxT("&")); break;
|
||||
case wxT('<'): OutputString(stream, wxT("<")); break;
|
||||
case wxT('>'): OutputString(stream, wxT(">")); break;
|
||||
case wxT('&'): OutputString(stream, wxT("&")); break;
|
||||
default: break;
|
||||
}
|
||||
last = i + 1;
|
||||
|
Reference in New Issue
Block a user