]> git.saurik.com Git - wxWidgets.git/blobdiff - src/xml/xml.cpp
move default OnInternalIdle processing to wxWindowBase
[wxWidgets.git] / src / xml / xml.cpp
index a37225c3dd7c7af074c02f35b69d5b1af23bca45..922332b1d623ed20a0d9d770e12daea772d8c6e6 100644 (file)
@@ -30,6 +30,7 @@
 #include "wx/zstream.h"
 #include "wx/strconv.h"
 #include "wx/scopedptr.h"
+#include "wx/versioninfo.h"
 
 #include "expat.h" // from Expat
 
@@ -54,7 +55,8 @@ wxXmlNode::wxXmlNode(wxXmlNode *parent,wxXmlNodeType type,
     : m_type(type), m_name(name), m_content(content),
       m_attrs(attrs), m_parent(parent),
       m_children(NULL), m_next(next),
-      m_lineNo(lineNo)
+      m_lineNo(lineNo),
+      m_noConversion(false)
 {
     if (m_parent)
     {
@@ -74,7 +76,7 @@ wxXmlNode::wxXmlNode(wxXmlNodeType type, const wxString& name,
     : m_type(type), m_name(name), m_content(content),
       m_attrs(NULL), m_parent(NULL),
       m_children(NULL), m_next(NULL),
-      m_lineNo(lineNo)
+      m_lineNo(lineNo), m_noConversion(false)
 {}
 
 wxXmlNode::wxXmlNode(const wxXmlNode& node)
@@ -115,6 +117,7 @@ void wxXmlNode::DoCopy(const wxXmlNode& node)
     m_name = node.m_name;
     m_content = node.m_content;
     m_lineNo = node.m_lineNo;
+    m_noConversion = node.m_noConversion;
     m_children = NULL;
 
     wxXmlNode *n = node.m_children;
@@ -618,6 +621,17 @@ static void StartCdataHnd(void *userData)
     ctx->lastChild= ctx->lastAsText = textnode;
 }
 
+static void EndCdataHnd(void *userData)
+{
+    wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
+
+    // we need to reset this pointer so that subsequent text nodes don't append
+    // their contents to this one but create new wxXML_TEXT_NODE objects (or
+    // not create anything at all if only white space follows the CDATA section
+    // and wxXMLDOC_KEEP_WHITESPACE_NODES is not used as is commonly the case)
+    ctx->lastAsText = NULL;
+}
+
 static void CommentHnd(void *userData, const char *data)
 {
     wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData;
@@ -717,7 +731,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding, int fl
     XML_SetUserData(parser, (void*)&ctx);
     XML_SetElementHandler(parser, StartElementHnd, EndElementHnd);
     XML_SetCharacterDataHandler(parser, TextHnd);
-    XML_SetStartCdataSectionHandler(parser, StartCdataHnd);
+    XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd);;
     XML_SetCommentHandler(parser, CommentHnd);
     XML_SetDefaultHandler(parser, DefaultHnd);
     XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL);
@@ -733,7 +747,7 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding, int fl
                            *wxConvCurrent);
             wxLogError(_("XML parsing error: '%s' at line %d"),
                        error.c_str(),
-                       XML_GetCurrentLineNumber(parser));
+                       (int)XML_GetCurrentLineNumber(parser));
             ok = false;
             break;
         }
@@ -810,62 +824,69 @@ bool OutputString(wxOutputStream& stream,
     return stream.IsOk();
 }
 
-// flags for OutputStringEnt()
-enum
+enum EscapingMode
 {
-    XML_ESCAPE_QUOTES = 1
+    Escape_Text,
+    Escape_Attribute
 };
 
 // Same as above, but create entities first.
-// Translates '<' to "&lt;", '>' to "&gt;" and '&' to "&amp;"
-bool OutputStringEnt(wxOutputStream& stream,
-                     const wxString& str,
-                     wxMBConv *convMem,
-                     wxMBConv *convFile,
-                     int flags = 0)
-{
-    const size_t len = str.length();
-    size_t i,
-           last = 0;
-    for (i = 0; i < len; i++)
-    {
-        wxChar c = str.GetChar(i);
-        if (c == wxS('<') || c == wxS('>') ||
-            (c == wxS('&') && str.substr(i+1, 4) != wxS("amp;")) ||
-            ((flags & XML_ESCAPE_QUOTES) && c == wxS('"')))
-        {
-            if ( !OutputString(stream, str.substr(last, i - last),
-                               convMem, convFile) )
-                return false;
+// Translates '<' to "&lt;", '>' to "&gt;" and so on, according to the spec:
+// http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping
+bool OutputEscapedString(wxOutputStream& stream,
+                         const wxString& str,
+                         wxMBConv *convMem,
+                         wxMBConv *convFile,
+                         EscapingMode mode)
+{
+    wxString escaped;
+    escaped.reserve(str.length());
 
-            const char *escaped;
-            switch ( c )
-            {
-                case wxS('<'):
-                    escaped = "&lt;";
-                    break;
-                case wxS('>'):
-                    escaped = "&gt;";
-                    break;
-                case wxS('&'):
-                    escaped = "&amp;";
-                    break;
-                case wxS('"'):
-                    escaped = "&quot;";
-                    break;
-                default:
-                    wxFAIL_MSG( "logic error in the code" );
-                    return false;
-            }
+    for ( wxString::const_iterator i = str.begin(); i != str.end(); ++i )
+    {
+        const wxChar c = *i;
 
-            if ( !OutputString(stream, escaped, convMem, convFile) )
-                return false;
+        switch ( c )
+        {
+            case wxS('<'):
+                escaped.append(wxS("&lt;"));
+                break;
+            case wxS('>'):
+                escaped.append(wxS("&gt;"));
+                break;
+            case wxS('&'):
+                escaped.append(wxS("&amp;"));
+                break;
+            case wxS('\r'):
+                escaped.append(wxS("&#xD;"));
+                break;
+            default:
+                if ( mode == Escape_Attribute )
+                {
+                    switch ( c )
+                    {
+                        case wxS('"'):
+                            escaped.append(wxS("&quot;"));
+                            break;
+                        case wxS('\t'):
+                            escaped.append(wxS("&#x9;"));
+                            break;
+                        case wxS('\n'):
+                            escaped.append(wxS("&#xA;"));
+                            break;
+                        default:
+                            escaped.append(c);
+                    }
 
-            last = i + 1;
+                }
+                else
+                {
+                    escaped.append(c);
+                }
         }
     }
 
-    return OutputString(stream, str.substr(last, i - last), convMem, convFile);
+    return OutputString(stream, escaped, convMem, convFile);
 }
 
 bool OutputIndentation(wxOutputStream& stream,
@@ -874,7 +895,7 @@ bool OutputIndentation(wxOutputStream& stream,
                        wxMBConv *convFile)
 {
     wxString str(wxS("\n"));
-    str += wxString(2*indent, wxS(' '));
+    str += wxString(indent, wxS(' '));
     return OutputString(stream, str, convMem, convFile);
 }
 
@@ -895,7 +916,15 @@ bool OutputNode(wxOutputStream& stream,
             break;
 
         case wxXML_TEXT_NODE:
-            rc = OutputStringEnt(stream, node->GetContent(), convMem, convFile);
+            if (node->GetNoConversion())
+            {
+                stream.Write(node->GetContent().c_str(), node->GetContent().Length());
+                rc = true;
+            }
+            else
+                rc = OutputEscapedString(stream, node->GetContent(),
+                                     convMem, convFile,
+                                     Escape_Text);
             break;
 
         case wxXML_ELEMENT_NODE:
@@ -911,9 +940,9 @@ bool OutputNode(wxOutputStream& stream,
                     rc = OutputString(stream,
                                       wxS(" ") + attr->GetName() +  wxS("=\""),
                                       convMem, convFile) &&
-                         OutputStringEnt(stream, attr->GetValue(),
-                                         convMem, convFile,
-                                         XML_ESCAPE_QUOTES) &&
+                         OutputEscapedString(stream, attr->GetValue(),
+                                             convMem, convFile,
+                                             Escape_Attribute) &&
                          OutputString(stream, wxS("\""), convMem, convFile);
                 }
             }
@@ -1007,4 +1036,12 @@ bool wxXmlDocument::Save(wxOutputStream& stream, int indentstep) const
            OutputString(stream, wxS("\n"), convMem.get(), convFile.get());
 }
 
+/*static*/ wxVersionInfo wxXmlDocument::GetLibraryVersionInfo()
+{
+    return wxVersionInfo("expat",
+                         XML_MAJOR_VERSION,
+                         XML_MINOR_VERSION,
+                         XML_MICRO_VERSION);
+}
+
 #endif // wxUSE_XML