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:
Václav Slavík
2002-01-24 21:14:42 +00:00
parent cc30b233fb
commit 480505bc6d
12 changed files with 252 additions and 82 deletions

View File

@@ -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) : wxObject(), m_root(NULL)
{ {
if (!Load(filename, io_type)) if (!Load(filename, io_type, encoding))
{ {
wxDELETE(m_root); 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) : wxObject(), m_root(NULL)
{ {
if (!Load(stream, io_type)) if (!Load(stream, io_type, encoding))
{ {
wxDELETE(m_root); wxDELETE(m_root);
} }
@@ -341,22 +343,33 @@ wxXmlDocument& wxXmlDocument::operator=(const wxXmlDocument& doc)
void wxXmlDocument::DoCopy(const wxXmlDocument& doc) void wxXmlDocument::DoCopy(const wxXmlDocument& doc)
{ {
m_version = doc.m_version; m_version = doc.m_version;
#if !wxUSE_UNICODE
m_encoding = doc.m_encoding; m_encoding = doc.m_encoding;
#endif
m_fileEncoding = doc.m_fileEncoding;
m_root = new wxXmlNode(*doc.m_root); 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); 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(); wxNode *n = sm_handlers->GetFirst();
while (n) while (n)
{ {
@@ -365,7 +378,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) && if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) &&
h->CanLoad(stream)) h->CanLoad(stream))
{ {
return h->Load(stream, *this); return h->Load(stream, *this, encoding);
} }
n = n->GetNext(); n = n->GetNext();
} }

View File

@@ -101,7 +101,12 @@ bool wxXmlIOHandlerBin::Save(wxOutputStream& stream, const wxXmlDocument& doc)
{ {
WriteHeader(stream, "XMLBIN "); WriteHeader(stream, "XMLBIN ");
wxDataOutputStream ds(stream); 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()); SaveBinNode(ds, doc.GetRoot());
return stream.LastError() == wxSTREAM_NOERROR; 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); ReadHeader(stream);
wxDataInputStream ds(stream); wxDataInputStream ds(stream);
@@ -151,7 +157,7 @@ bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
ds >> tmp; ds >> tmp;
doc.SetVersion(tmp); doc.SetVersion(tmp);
ds >> tmp; ds >> tmp;
doc.SetEncoding(tmp); doc.SetFileEncoding(tmp);
doc.SetRoot(LoadBinNode(ds, NULL)); doc.SetRoot(LoadBinNode(ds, NULL));

View File

@@ -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); ReadHeader(stream);
wxZlibInputStream costr(stream); wxZlibInputStream costr(stream);
return wxXmlIOHandlerBin::Load(costr, doc); return wxXmlIOHandlerBin::Load(costr, doc, encoding);
} }

View File

@@ -30,23 +30,32 @@
/* /*
FIXME: FIXME:
- handle unknown encodings
- process all elements, including CDATA - 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. // 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 #if wxUSE_UNICODE
(void)conv;
return wxString(s, wxConvUTF8, len); return wxString(s, wxConvUTF8, len);
#else #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 #endif
} }
@@ -62,21 +71,23 @@ bool wxXmlIOHandlerExpat::CanLoad(wxInputStream& stream)
struct wxXmlParsingContext struct wxXmlParsingContext
{ {
wxMBConv *conv;
wxXmlNode *root; wxXmlNode *root;
wxXmlNode *node; wxXmlNode *node;
wxXmlNode *lastAsText; wxXmlNode *lastAsText;
wxString encoding; wxString encoding;
wxString version; wxString version;
}; };
static void StartElementHnd(void *userData, const char *name, const char **atts) static void StartElementHnd(void *userData, const char *name, const char **atts)
{ {
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; 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; const char **a = atts;
while (*a) while (*a)
{ {
node->AddProperty(CharToString(a[0]), CharToString(a[1])); node->AddProperty(CharToString(ctx->conv, a[0]), CharToString(ctx->conv, a[1]));
a += 2; a += 2;
} }
if (ctx->root == NULL) if (ctx->root == NULL)
@@ -106,7 +117,7 @@ static void TextHnd(void *userData, const char *s, int len)
if (ctx->lastAsText) if (ctx->lastAsText)
{ {
ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() +
CharToString(buf)); CharToString(ctx->conv, buf));
} }
else else
{ {
@@ -120,7 +131,7 @@ static void TextHnd(void *userData, const char *s, int len)
if (!whiteOnly) if (!whiteOnly)
{ {
ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"), ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"),
CharToString(buf)); CharToString(ctx->conv, buf));
ctx->node->AddChild(ctx->lastAsText); 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 // the root element (e.g. wxDesigner's output). We ignore such
// comments, no big deal... // comments, no big deal...
ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE,
wxT("comment"), CharToString(data))); wxT("comment"), CharToString(ctx->conv, data)));
} }
ctx->lastAsText = NULL; ctx->lastAsText = NULL;
} }
@@ -150,7 +161,7 @@ static void DefaultHnd(void *userData, const char *s, int len)
{ {
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
wxString buf = CharToString(s, (size_t)len); wxString buf = CharToString(ctx->conv, s, (size_t)len);
int pos; int pos;
pos = buf.Find(wxT("encoding=")); pos = buf.Find(wxT("encoding="));
if (pos != wxNOT_FOUND) 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; const size_t BUFSIZE = 1024;
char buf[BUFSIZE]; char buf[BUFSIZE];
@@ -170,11 +210,19 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
XML_Parser parser = XML_ParserCreate(NULL); XML_Parser parser = XML_ParserCreate(NULL);
ctx.root = ctx.node = 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_SetUserData(parser, (void*)&ctx);
XML_SetElementHandler(parser, StartElementHnd, EndElementHnd); XML_SetElementHandler(parser, StartElementHnd, EndElementHnd);
XML_SetCharacterDataHandler(parser, TextHnd); XML_SetCharacterDataHandler(parser, TextHnd);
XML_SetCommentHandler(parser, CommentHnd); XML_SetCommentHandler(parser, CommentHnd);
XML_SetDefaultHandler(parser, DefaultHnd); XML_SetDefaultHandler(parser, DefaultHnd);
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
do do
{ {
@@ -190,9 +238,14 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
} while (!done); } while (!done);
doc.SetVersion(ctx.version); doc.SetVersion(ctx.version);
doc.SetEncoding(ctx.encoding); doc.SetFileEncoding(ctx.encoding);
doc.SetRoot(ctx.root); doc.SetRoot(ctx.root);
XML_ParserFree(parser); XML_ParserFree(parser);
#if !wxUSE_UNICODE
if ( ctx.conv )
delete ctx.conv;
#endif
return TRUE; return TRUE;
} }

View File

@@ -100,9 +100,9 @@ bool wxXmlResource::Load(const wxString& filemask)
{ {
#if wxUSE_FILESYSTEM #if wxUSE_FILESYSTEM
if (filemask.Lower().Matches(wxT("*.zip")) || 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")); rt = rt && Load(fnd + wxT("#zip:*.xrc"));
} }
else else
@@ -286,6 +286,17 @@ void wxXmlResource::UpdateResources()
wxFileSystem fsys; wxFileSystem fsys;
# endif # 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++) for (size_t i = 0; i < m_data.GetCount(); i++)
{ {
modif = (m_data[i].Doc == NULL); modif = (m_data[i].Doc == NULL);
@@ -305,7 +316,7 @@ void wxXmlResource::UpdateResources()
if (modif) if (modif)
{ {
wxInputStream *stream = NULL; wxInputStream *stream = NULL;
# if wxUSE_FILESYSTEM # if wxUSE_FILESYSTEM
file = fsys.OpenFile(m_data[i].File); file = fsys.OpenFile(m_data[i].File);
@@ -320,9 +331,10 @@ void wxXmlResource::UpdateResources()
delete m_data[i].Doc; delete m_data[i].Doc;
m_data[i].Doc = new wxXmlDocument; 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); wxDELETE(m_data[i].Doc);
} }
else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource")) else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource"))

View File

@@ -44,22 +44,22 @@ static void OutputStringEnt(wxOutputStream& stream, const wxString& str)
{ {
wxString buf; wxString buf;
size_t i, last, len; size_t i, last, len;
char c; wxChar c;
len = str.Len(); len = str.Len();
last = 0; last = 0;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
c = str.GetChar(i); c = str.GetChar(i);
if (c == '<' || c == '>' || if (c == wxT('<') || c == wxT('>') ||
(c == '&' && str.Mid(i+1, 4) != wxT("amp;"))) (c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;")))
{ {
OutputString(stream, str.Mid(last, i - last)); OutputString(stream, str.Mid(last, i - last));
switch (c) switch (c)
{ {
case '<': OutputString(stream, wxT("&lt;")); break; case wxT('<'): OutputString(stream, wxT("&lt;")); break;
case '>': OutputString(stream, wxT("&gt;")); break; case wxT('>'): OutputString(stream, wxT("&gt;")); break;
case '&': OutputString(stream, wxT("&amp;")); break; case wxT('&'): OutputString(stream, wxT("&amp;")); break;
default: break; default: break;
} }
last = i + 1; last = i + 1;

View File

@@ -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) : wxObject(), m_root(NULL)
{ {
if (!Load(filename, io_type)) if (!Load(filename, io_type, encoding))
{ {
wxDELETE(m_root); 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) : wxObject(), m_root(NULL)
{ {
if (!Load(stream, io_type)) if (!Load(stream, io_type, encoding))
{ {
wxDELETE(m_root); wxDELETE(m_root);
} }
@@ -341,22 +343,33 @@ wxXmlDocument& wxXmlDocument::operator=(const wxXmlDocument& doc)
void wxXmlDocument::DoCopy(const wxXmlDocument& doc) void wxXmlDocument::DoCopy(const wxXmlDocument& doc)
{ {
m_version = doc.m_version; m_version = doc.m_version;
#if !wxUSE_UNICODE
m_encoding = doc.m_encoding; m_encoding = doc.m_encoding;
#endif
m_fileEncoding = doc.m_fileEncoding;
m_root = new wxXmlNode(*doc.m_root); 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); 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(); wxNode *n = sm_handlers->GetFirst();
while (n) while (n)
{ {
@@ -365,7 +378,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, wxXmlIOType io_type)
if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) && if ((io_type == wxXML_IO_AUTO || io_type == h->GetType()) &&
h->CanLoad(stream)) h->CanLoad(stream))
{ {
return h->Load(stream, *this); return h->Load(stream, *this, encoding);
} }
n = n->GetNext(); n = n->GetNext();
} }

View File

@@ -101,7 +101,12 @@ bool wxXmlIOHandlerBin::Save(wxOutputStream& stream, const wxXmlDocument& doc)
{ {
WriteHeader(stream, "XMLBIN "); WriteHeader(stream, "XMLBIN ");
wxDataOutputStream ds(stream); 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()); SaveBinNode(ds, doc.GetRoot());
return stream.LastError() == wxSTREAM_NOERROR; 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); ReadHeader(stream);
wxDataInputStream ds(stream); wxDataInputStream ds(stream);
@@ -151,7 +157,7 @@ bool wxXmlIOHandlerBin::Load(wxInputStream& stream, wxXmlDocument& doc)
ds >> tmp; ds >> tmp;
doc.SetVersion(tmp); doc.SetVersion(tmp);
ds >> tmp; ds >> tmp;
doc.SetEncoding(tmp); doc.SetFileEncoding(tmp);
doc.SetRoot(LoadBinNode(ds, NULL)); doc.SetRoot(LoadBinNode(ds, NULL));

View File

@@ -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); ReadHeader(stream);
wxZlibInputStream costr(stream); wxZlibInputStream costr(stream);
return wxXmlIOHandlerBin::Load(costr, doc); return wxXmlIOHandlerBin::Load(costr, doc, encoding);
} }

View File

@@ -30,23 +30,32 @@
/* /*
FIXME: FIXME:
- handle unknown encodings
- process all elements, including CDATA - 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. // 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 #if wxUSE_UNICODE
(void)conv;
return wxString(s, wxConvUTF8, len); return wxString(s, wxConvUTF8, len);
#else #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 #endif
} }
@@ -62,21 +71,23 @@ bool wxXmlIOHandlerExpat::CanLoad(wxInputStream& stream)
struct wxXmlParsingContext struct wxXmlParsingContext
{ {
wxMBConv *conv;
wxXmlNode *root; wxXmlNode *root;
wxXmlNode *node; wxXmlNode *node;
wxXmlNode *lastAsText; wxXmlNode *lastAsText;
wxString encoding; wxString encoding;
wxString version; wxString version;
}; };
static void StartElementHnd(void *userData, const char *name, const char **atts) static void StartElementHnd(void *userData, const char *name, const char **atts)
{ {
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; 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; const char **a = atts;
while (*a) while (*a)
{ {
node->AddProperty(CharToString(a[0]), CharToString(a[1])); node->AddProperty(CharToString(ctx->conv, a[0]), CharToString(ctx->conv, a[1]));
a += 2; a += 2;
} }
if (ctx->root == NULL) if (ctx->root == NULL)
@@ -106,7 +117,7 @@ static void TextHnd(void *userData, const char *s, int len)
if (ctx->lastAsText) if (ctx->lastAsText)
{ {
ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() +
CharToString(buf)); CharToString(ctx->conv, buf));
} }
else else
{ {
@@ -120,7 +131,7 @@ static void TextHnd(void *userData, const char *s, int len)
if (!whiteOnly) if (!whiteOnly)
{ {
ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"), ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"),
CharToString(buf)); CharToString(ctx->conv, buf));
ctx->node->AddChild(ctx->lastAsText); 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 // the root element (e.g. wxDesigner's output). We ignore such
// comments, no big deal... // comments, no big deal...
ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE,
wxT("comment"), CharToString(data))); wxT("comment"), CharToString(ctx->conv, data)));
} }
ctx->lastAsText = NULL; ctx->lastAsText = NULL;
} }
@@ -150,7 +161,7 @@ static void DefaultHnd(void *userData, const char *s, int len)
{ {
wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
wxString buf = CharToString(s, (size_t)len); wxString buf = CharToString(ctx->conv, s, (size_t)len);
int pos; int pos;
pos = buf.Find(wxT("encoding=")); pos = buf.Find(wxT("encoding="));
if (pos != wxNOT_FOUND) 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; const size_t BUFSIZE = 1024;
char buf[BUFSIZE]; char buf[BUFSIZE];
@@ -170,11 +210,19 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
XML_Parser parser = XML_ParserCreate(NULL); XML_Parser parser = XML_ParserCreate(NULL);
ctx.root = ctx.node = 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_SetUserData(parser, (void*)&ctx);
XML_SetElementHandler(parser, StartElementHnd, EndElementHnd); XML_SetElementHandler(parser, StartElementHnd, EndElementHnd);
XML_SetCharacterDataHandler(parser, TextHnd); XML_SetCharacterDataHandler(parser, TextHnd);
XML_SetCommentHandler(parser, CommentHnd); XML_SetCommentHandler(parser, CommentHnd);
XML_SetDefaultHandler(parser, DefaultHnd); XML_SetDefaultHandler(parser, DefaultHnd);
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
do do
{ {
@@ -190,9 +238,14 @@ bool wxXmlIOHandlerExpat::Load(wxInputStream& stream, wxXmlDocument& doc)
} while (!done); } while (!done);
doc.SetVersion(ctx.version); doc.SetVersion(ctx.version);
doc.SetEncoding(ctx.encoding); doc.SetFileEncoding(ctx.encoding);
doc.SetRoot(ctx.root); doc.SetRoot(ctx.root);
XML_ParserFree(parser); XML_ParserFree(parser);
#if !wxUSE_UNICODE
if ( ctx.conv )
delete ctx.conv;
#endif
return TRUE; return TRUE;
} }

View File

@@ -100,9 +100,9 @@ bool wxXmlResource::Load(const wxString& filemask)
{ {
#if wxUSE_FILESYSTEM #if wxUSE_FILESYSTEM
if (filemask.Lower().Matches(wxT("*.zip")) || 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")); rt = rt && Load(fnd + wxT("#zip:*.xrc"));
} }
else else
@@ -286,6 +286,17 @@ void wxXmlResource::UpdateResources()
wxFileSystem fsys; wxFileSystem fsys;
# endif # 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++) for (size_t i = 0; i < m_data.GetCount(); i++)
{ {
modif = (m_data[i].Doc == NULL); modif = (m_data[i].Doc == NULL);
@@ -305,7 +316,7 @@ void wxXmlResource::UpdateResources()
if (modif) if (modif)
{ {
wxInputStream *stream = NULL; wxInputStream *stream = NULL;
# if wxUSE_FILESYSTEM # if wxUSE_FILESYSTEM
file = fsys.OpenFile(m_data[i].File); file = fsys.OpenFile(m_data[i].File);
@@ -320,9 +331,10 @@ void wxXmlResource::UpdateResources()
delete m_data[i].Doc; delete m_data[i].Doc;
m_data[i].Doc = new wxXmlDocument; 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); wxDELETE(m_data[i].Doc);
} }
else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource")) else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource"))

View File

@@ -44,22 +44,22 @@ static void OutputStringEnt(wxOutputStream& stream, const wxString& str)
{ {
wxString buf; wxString buf;
size_t i, last, len; size_t i, last, len;
char c; wxChar c;
len = str.Len(); len = str.Len();
last = 0; last = 0;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
c = str.GetChar(i); c = str.GetChar(i);
if (c == '<' || c == '>' || if (c == wxT('<') || c == wxT('>') ||
(c == '&' && str.Mid(i+1, 4) != wxT("amp;"))) (c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;")))
{ {
OutputString(stream, str.Mid(last, i - last)); OutputString(stream, str.Mid(last, i - last));
switch (c) switch (c)
{ {
case '<': OutputString(stream, wxT("&lt;")); break; case wxT('<'): OutputString(stream, wxT("&lt;")); break;
case '>': OutputString(stream, wxT("&gt;")); break; case wxT('>'): OutputString(stream, wxT("&gt;")); break;
case '&': OutputString(stream, wxT("&amp;")); break; case wxT('&'): OutputString(stream, wxT("&amp;")); break;
default: break; default: break;
} }
last = i + 1; last = i + 1;