X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7fe8059f5825e58af0864e5933e43e5f0526bc76..47e59154157bb013ce255a4efa7a615574c974f7:/src/richtext/richtextxml.cpp?ds=inline diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp index 516fb41a28..b2205170ed 100644 --- a/src/richtext/richtextxml.cpp +++ b/src/richtext/richtextxml.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: richtext/richtextxml.cpp +// Name: src/richtext/richtextxml.cpp // Purpose: XML and HTML I/O for wxRichTextCtrl // Author: Julian Smart // Modified by: @@ -13,27 +13,25 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif -#ifndef WX_PRECOMP - #include "wx/wx.h" -#endif +#if wxUSE_RICHTEXT && wxUSE_XML -#include "wx/image.h" +#include "wx/richtext/richtextxml.h" -#if wxUSE_RICHTEXT +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/module.h" +#endif #include "wx/filename.h" #include "wx/clipbrd.h" #include "wx/wfstream.h" #include "wx/sstream.h" -#include "wx/module.h" #include "wx/txtstrm.h" #include "wx/xml/xml.h" -#include "wx/richtext/richtextxml.h" - IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler, wxRichTextFileHandler) #if wxUSE_STREAMS @@ -47,7 +45,14 @@ bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStream& s wxXmlDocument* xmlDoc = new wxXmlDocument; bool success = true; - if (!xmlDoc->Load(stream, wxT("ISO-8859-1"))) + // This is the encoding to convert to (memory encoding rather than file encoding) + wxString encoding(wxT("UTF-8")); + +#if !wxUSE_UNICODE && wxUSE_INTL + encoding = wxLocale::GetSystemEncodingName(); +#endif + + if (!xmlDoc->Load(stream, encoding)) { success = false; } @@ -117,19 +122,13 @@ bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node) wxString text2 = textChild->GetContent(); // Strip whitespace from end - if (text2.Length() > 0 && text2[text2.Length()-1] == wxT('\n')) - text2 = text2.Mid(0, text2.Length()-1); + if (!text2.empty() && text2[text2.length()-1] == wxT('\n')) + text2 = text2.Mid(0, text2.length()-1); - if (text2.Length() > 0 && text2[0] == wxT('"')) + if (!text2.empty() && text2[0] == wxT('"')) text2 = text2.Mid(1); - if (text2.Length() > 0 && text2[text2.Length()-1] == wxT('"')) - text2 = text2.Mid(0, text2.Length() - 1); - - // TODO: further entity translation - text2.Replace(wxT("<"), wxT("<")); - text2.Replace(wxT(">"), wxT(">")); - text2.Replace(wxT("&"), wxT("&")); - text2.Replace(wxT("""), wxT("\"")); + if (!text2.empty() && text2[text2.length()-1] == wxT('"')) + text2 = text2.Mid(0, text2.length() - 1); text += text2; } @@ -175,7 +174,7 @@ bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node) wxStringInputStream strStream(data); - imageObj->GetImageBlock().ReadHex(strStream, data.Length(), imageType); + imageObj->GetImageBlock().ReadHex(strStream, data.length(), imageType); } } child = child->GetNext(); @@ -257,14 +256,31 @@ wxString wxRichTextXMLHandler::GetText(wxXmlNode *node, const wxString& param, b return str1; } +// For use with earlier versions of wxWidgets +#ifndef WXUNUSED_IN_UNICODE +#if wxUSE_UNICODE +#define WXUNUSED_IN_UNICODE(x) WXUNUSED(x) +#else +#define WXUNUSED_IN_UNICODE(x) x +#endif +#endif + // write string to output: inline static void OutputString(wxOutputStream& stream, const wxString& str, wxMBConv *WXUNUSED_IN_UNICODE(convMem) = NULL, wxMBConv *convFile = NULL) { if (str.empty()) return; #if wxUSE_UNICODE - const wxWX2MBbuf buf(str.mb_str(convFile ? *convFile : wxConvUTF8)); - stream.Write((const char*)buf, strlen((const char*)buf)); + if (convFile) + { + const wxWX2MBbuf buf(str.mb_str(*convFile)); + stream.Write((const char*)buf, strlen((const char*)buf)); + } + else + { + const wxWX2MBbuf buf(str.mb_str(wxConvUTF8)); + stream.Write((const char*)buf, strlen((const char*)buf)); + } #else if ( convFile == NULL ) stream.Write(str.mb_str(), str.Len()); @@ -290,8 +306,13 @@ static void OutputStringEnt(wxOutputStream& stream, const wxString& str, for (i = 0; i < len; i++) { c = str.GetChar(i); + + // Original code excluded "&" but we _do_ want to convert + // the ampersand beginning & because otherwise when read in, + // the original "&" becomes "&". + if (c == wxT('<') || c == wxT('>') || c == wxT('"') || - (c == wxT('&') && (str.Mid(i+1, 4) != wxT("amp;")))) + (c == wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ )) { OutputString(stream, str.Mid(last, i - last), convMem, convFile); switch (c) @@ -324,26 +345,6 @@ inline static void OutputIndentation(wxOutputStream& stream, int indent) OutputString(stream, str, NULL, NULL); } -static wxOutputStream& operator <<(wxOutputStream& stream, const wxString& s) -{ - stream.Write(s, s.Length()); - return stream; -} - -static wxOutputStream& operator <<(wxOutputStream& stream, long l) -{ - wxString str; - str.Printf(wxT("%ld"), l); - return stream << str; -} - -static wxOutputStream& operator <<(wxOutputStream& stream, const char c) -{ - wxString str; - str.Printf(wxT("%c"), c); - return stream << str; -} - // Convert a colour to a 6-digit hex string static wxString ColourToHexString(const wxColour& col) { @@ -357,7 +358,7 @@ static wxString ColourToHexString(const wxColour& col) } // Convert 6-digit hex string to a colour -wxColour HexStringToColour(const wxString& hex) +static wxColour HexStringToColour(const wxString& hex) { unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2)); unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2)); @@ -372,41 +373,64 @@ bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& return false; wxString version(wxT("1.0") ) ; + + bool deleteConvFile = false; + wxString fileEncoding; + wxMBConv* convFile = NULL; + #if wxUSE_UNICODE - wxString fileencoding(wxT("UTF-8")) ; - wxString memencoding(wxT("UTF-8")) ; + fileEncoding = wxT("UTF-8"); + convFile = & wxConvUTF8; #else - wxString fileencoding(wxT("ISO-8859-1")) ; - wxString memencoding(wxT("ISO-8859-1")) ; + fileEncoding = wxT("ISO-8859-1"); + convFile = & wxConvISO8859_1; #endif - wxString s ; - wxMBConv *convMem = NULL, *convFile = NULL; + // If SetEncoding has been called, change the output encoding. + if (!m_encoding.empty() && m_encoding.Lower() != fileEncoding.Lower()) + { + if (m_encoding == wxT("")) + { + fileEncoding = wxLocale::GetSystemEncodingName(); + } + else + { + fileEncoding = m_encoding; + } + + // GetSystemEncodingName may not have returned a name + if (fileEncoding.empty()) #if wxUSE_UNICODE - convFile = new wxCSConv(fileencoding); + fileEncoding = wxT("UTF-8"); #else - if ( fileencoding != memencoding ) - { - convFile = new wxCSConv(fileencoding); - convMem = new wxCSConv(memencoding); + fileEncoding = wxT("ISO-8859-1"); +#endif + convFile = new wxCSConv(fileEncoding); + deleteConvFile = true; } + +#if !wxUSE_UNICODE + wxMBConv* convMem = wxConvCurrent; +#else + wxMBConv* convMem = NULL; #endif + wxString s ; s.Printf(wxT("\n"), - (const wxChar*) version, (const wxChar*) fileencoding ); + (const wxChar*) version, (const wxChar*) fileEncoding ); OutputString(stream, s, NULL, NULL); OutputString(stream, wxT("") , NULL, NULL); int level = 1; - ExportXML(stream, convMem, convFile, *buffer, level); + bool success = ExportXML(stream, convMem, convFile, *buffer, level); OutputString(stream, wxT("\n") , NULL, NULL); OutputString(stream, wxT("\n"), NULL, NULL); - delete convFile; - delete convMem; + if (deleteConvFile) + delete convFile; - return true; + return success; } /// Recursively export an object @@ -429,18 +453,18 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxRichTextPlainText& text = (wxRichTextPlainText&) obj; OutputIndentation(stream, indent); - stream << wxT("<") << objectName; + OutputString(stream, wxT("<") + objectName, convMem, convFile); wxString style = CreateStyle(obj.GetAttributes(), false); - stream << style << wxT(">"); + OutputString(stream, style + wxT(">"), convMem, convFile); wxString str = text.GetText(); - if (str.Length() > 0 && (str[0] == wxT(' ') || str[str.Length()-1] == wxT(' '))) + if (!str.empty() && (str[0] == wxT(' ') || str[str.length()-1] == wxT(' '))) { - stream << wxT("\""); + OutputString(stream, wxT("\""), convMem, convFile); OutputStringEnt(stream, str, convMem, convFile); - stream << wxT("\""); + OutputString(stream, wxT("\""), convMem, convFile); } else OutputStringEnt(stream, str, convMem, convFile); @@ -453,28 +477,28 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, imageObj.MakeBlock(); OutputIndentation(stream, indent); - stream << wxT("<") << objectName; + OutputString(stream, wxT("<") + objectName, convMem, convFile); if (!imageObj.GetImageBlock().Ok()) { // No data - stream << wxT(">"); + OutputString(stream, wxT(">"), convMem, convFile); } else { - stream << wxString::Format(wxT(" imagetype=\"%d\""), (int) imageObj.GetImageBlock().GetImageType()) << wxT(">"); + OutputString(stream, wxString::Format(wxT(" imagetype=\"%d\">"), (int) imageObj.GetImageBlock().GetImageType())); } OutputIndentation(stream, indent+1); - stream << wxT(""); + OutputString(stream, wxT(""), convMem, convFile); imageObj.GetImageBlock().WriteHex(stream); - stream << wxT(""); + OutputString(stream, wxT(""), convMem, convFile); } else if (obj.IsKindOf(CLASSINFO(wxRichTextCompositeObject))) { OutputIndentation(stream, indent); - stream << wxT("<") << objectName; + OutputString(stream, wxT("<") + objectName, convMem, convFile); bool isPara = false; if (objectName == wxT("paragraph") || objectName == wxT("paragraphlayout")) @@ -482,7 +506,7 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxString style = CreateStyle(obj.GetAttributes(), isPara); - stream << style << wxT(">"); + OutputString(stream, style + wxT(">"), convMem, convFile); wxRichTextCompositeObject& composite = (wxRichTextCompositeObject&) obj; size_t i; @@ -496,7 +520,7 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, if (objectName != wxT("text")) OutputIndentation(stream, indent); - stream << wxT(""); + OutputString(stream, wxT(""), convMem, convFile); return true; } @@ -657,148 +681,7 @@ bool wxRichTextXMLHandler::GetStyle(wxTextAttrEx& attr, wxXmlNode* node, bool is } #endif - -IMPLEMENT_DYNAMIC_CLASS(wxRichTextHTMLHandler, wxRichTextFileHandler) - -/// Can we handle this filename (if using files)? By default, checks the extension. -bool wxRichTextHTMLHandler::CanHandle(const wxString& filename) const -{ - wxString path, file, ext; - wxSplitPath(filename, & path, & file, & ext); - - return (ext.Lower() == wxT("html") || ext.Lower() == wxT("htm")); -} - - -#if wxUSE_STREAMS -bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInputStream& WXUNUSED(stream)) -{ - return false; -} - -/* - * We need to output only _changes_ in character formatting. - */ - -bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream) -{ - buffer->Defragment(); - - wxTextOutputStream str(stream); - - wxTextAttrEx currentParaStyle = buffer->GetAttributes(); - wxTextAttrEx currentCharStyle = buffer->GetAttributes(); - - str << wxT("\n"); - - wxRichTextObjectList::compatibility_iterator node = buffer->GetChildren().GetFirst(); - while (node) - { - wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph); - wxASSERT (para != NULL); - - if (para) - { - OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream, true); - - wxRichTextObjectList::compatibility_iterator node2 = para->GetChildren().GetFirst(); - while (node2) - { - wxRichTextObject* obj = node2->GetData(); - wxRichTextPlainText* textObj = wxDynamicCast(obj, wxRichTextPlainText); - if (textObj && !textObj->IsEmpty()) - { - OutputCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream, true); - - str << textObj->GetText(); - - OutputCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream, false); - } - - node2 = node2->GetNext(); - } - - OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream, false); - - str << wxT("

\n"); - } - - node = node->GetNext(); - } - - str << wxT("\n"); - - return true; -} - -/// Output character formatting -void wxRichTextHTMLHandler::OutputCharacterFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream, bool start) -{ - wxTextOutputStream str(stream); - - bool isBold = false; - bool isItalic = false; - bool isUnderline = false; - wxString faceName; - - if (thisStyle.GetFont().Ok()) - { - if (thisStyle.GetFont().GetWeight() == wxBOLD) - isBold = true; - if (thisStyle.GetFont().GetStyle() == wxITALIC) - isItalic = true; - if (thisStyle.GetFont().GetUnderlined()) - isUnderline = true; - - faceName = thisStyle.GetFont().GetFaceName(); - } - - if (start) - { - if (isBold) - str << wxT(""); - if (isItalic) - str << wxT(""); - if (isUnderline) - str << wxT(""); - } - else - { - if (isUnderline) - str << wxT(""); - if (isItalic) - str << wxT(""); - if (isBold) - str << wxT(""); - } -} - -/// Output paragraph formatting -void wxRichTextHTMLHandler::OutputParagraphFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream, bool start) -{ - // TODO: lists, indentation (using tables), fonts, right-align, ... - - wxTextOutputStream str(stream); - bool isCentered = false; - - if (thisStyle.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) - { - isCentered = true; - } - - if (start) - { - if (isCentered) - str << wxT("

"); - } - else - { - if (isCentered) - str << wxT("
"); - } -} - -#endif + // wxUSE_STREAMS #endif - // wxUSE_RICHTEXT + // wxUSE_RICHTEXT && wxUSE_XML