[MSXML3] Sync with Wine Staging 1.9.4. CORE-10912
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 3 Mar 2016 14:00:49 +0000 (14:00 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 3 Mar 2016 14:00:49 +0000 (14:00 +0000)
svn path=/trunk/; revision=70885

reactos/dll/win32/msxml3/domdoc.c
reactos/dll/win32/msxml3/httprequest.c
reactos/dll/win32/msxml3/msxml_private.h
reactos/dll/win32/msxml3/node.c
reactos/media/doc/README.WINE

index 670741e..b1ffb33 100644 (file)
@@ -428,7 +428,14 @@ static void sax_characters(void *ctx, const xmlChar *ch, int len)
             (!ctxt->node->last ||
             ((ctxt->node->last && (cur == '<' || ctxt->node->last->type != XML_TEXT_NODE))
            )))
+        {
+            /* Keep information about ignorable whitespace text node in previous or parent node */
+            if (ctxt->node->last)
+                *(DWORD*)&ctxt->node->last->_private |= NODE_PRIV_TRAILING_IGNORABLE_WS;
+            else if (ctxt->node->type != XML_DOCUMENT_NODE)
+                *(DWORD*)&ctxt->node->_private |= NODE_PRIV_CHILD_IGNORABLE_WS;
             return;
+        }
     }
 
     xmlSAX2Characters(ctxt, ch, len);
@@ -1217,8 +1224,31 @@ static HRESULT WINAPI domdoc_cloneNode(
     IXMLDOMNode** outNode)
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
+    xmlNodePtr clone;
+
     TRACE("(%p)->(%d %p)\n", This, deep, outNode);
-    return node_clone( &This->node, deep, outNode );
+
+    if (!outNode)
+        return E_INVALIDARG;
+
+    *outNode = NULL;
+
+    clone = xmlCopyNode((xmlNodePtr)get_doc(This), deep ? 1 : 2);
+    if (!clone)
+        return E_FAIL;
+
+    clone->doc->_private = create_priv();
+    xmldoc_add_orphan(clone->doc, clone);
+    xmldoc_add_ref(clone->doc);
+
+    priv_from_xmlDocPtr(clone->doc)->properties = copy_properties(This->properties);
+    if (!(*outNode = (IXMLDOMNode*)create_domdoc(clone)))
+    {
+        xmldoc_release(clone->doc);
+        return E_FAIL;
+    }
+
+    return S_OK;
 }
 
 
@@ -3613,16 +3643,16 @@ HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
 
 IUnknown* create_domdoc( xmlNodePtr document )
 {
-    void* pObj = NULL;
+    IUnknown *obj = NULL;
     HRESULT hr;
 
     TRACE("(%p)\n", document);
 
-    hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&pObj);
+    hr = get_domdoc_from_xmldoc((xmlDocPtr)document, (IXMLDOMDocument3**)&obj);
     if (FAILED(hr))
         return NULL;
 
-    return pObj;
+    return obj;
 }
 
 #else
index ea22ebf..85f72f7 100644 (file)
@@ -152,6 +152,19 @@ static void free_response_headers(httprequest *This)
     This->raw_respheaders = NULL;
 }
 
+static void free_request_headers(httprequest *This)
+{
+    struct httpheader *header, *header2;
+
+    LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry)
+    {
+        list_remove(&header->entry);
+        SysFreeString(header->header);
+        SysFreeString(header->value);
+        heap_free(header);
+    }
+}
+
 struct BindStatusCallback
 {
     IBindStatusCallback IBindStatusCallback_iface;
@@ -864,6 +877,7 @@ static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
     SysFreeString(This->user);
     SysFreeString(This->password);
     This->user = This->password = NULL;
+    free_request_headers(This);
 
     if (!strcmpiW(method, MethodGetW))
     {
@@ -1249,8 +1263,6 @@ static HRESULT httprequest_put_onreadystatechange(httprequest *This, IDispatch *
 
 static void httprequest_release(httprequest *This)
 {
-    struct httpheader *header, *header2;
-
     if (This->site)
         IUnknown_Release( This->site );
     if (This->uri)
@@ -1262,15 +1274,8 @@ static void httprequest_release(httprequest *This)
     SysFreeString(This->user);
     SysFreeString(This->password);
 
-    /* request headers */
-    LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry)
-    {
-        list_remove(&header->entry);
-        SysFreeString(header->header);
-        SysFreeString(header->value);
-        heap_free(header);
-    }
-    /* response headers */
+    /* cleanup headers lists */
+    free_request_headers(This);
     free_response_headers(This);
     SysFreeString(This->status_text);
 
index add547c..dd124c5 100644 (file)
@@ -559,4 +559,7 @@ HRESULT detach_bsc(bsc_t*) DECLSPEC_HIDDEN;
 /* ... */
 #define E_XML_REQUIRED_ATTRIBUTE_MISSING    0xC00CE020
 
+#define NODE_PRIV_TRAILING_IGNORABLE_WS     0x40000000
+#define NODE_PRIV_CHILD_IGNORABLE_WS        0x80000000
+#define NODE_PRIV_REFCOUNT_MASK             ~(NODE_PRIV_TRAILING_IGNORABLE_WS|NODE_PRIV_CHILD_IGNORABLE_WS)
 #endif /* __MSXML_PRIVATE__ */
index 37bd57b..7e9efae 100644 (file)
@@ -379,7 +379,7 @@ HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret)
 
 static int node_get_inst_cnt(xmlNodePtr node)
 {
-    int ret = *(LONG *)&node->_private;
+    int ret = *(LONG *)&node->_private & NODE_PRIV_REFCOUNT_MASK;
     xmlNodePtr child;
 
     /* add attribute counts */
@@ -410,6 +410,20 @@ int xmlnode_get_inst_cnt(xmlnode *node)
     return node_get_inst_cnt(node->node);
 }
 
+/* _private field holds a number of COM instances spawned from this libxml2 node
+ * most significant bits are used to store information about ignorrable whitespace nodes */
+static void xmlnode_add_ref(xmlNodePtr node)
+{
+    if (node->type == XML_DOCUMENT_NODE) return;
+    InterlockedIncrement((LONG*)&node->_private);
+}
+
+static void xmlnode_release(xmlNodePtr node)
+{
+    if (node->type == XML_DOCUMENT_NODE) return;
+    InterlockedDecrement((LONG*)&node->_private);
+}
+
 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child,
         IXMLDOMNode **ret)
 {
@@ -470,6 +484,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
 
     if(before)
     {
+        xmlNodePtr new_node;
         xmlnode *before_node_obj = get_node_obj(before);
 
         /* refs count including subtree */
@@ -477,19 +492,35 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
             refcount = xmlnode_get_inst_cnt(node_obj);
 
         if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount);
-        node_obj->node = xmlAddPrevSibling(before_node_obj->node, node_obj->node);
+        new_node = xmlAddPrevSibling(before_node_obj->node, node_obj->node);
+        if (new_node != node_obj->node)
+        {
+            if (refcount != 1)
+                FIXME("referenced xmlNode was freed, expect crashes\n");
+            xmlnode_add_ref(new_node);
+            node_obj->node = new_node;
+        }
         if (refcount) xmldoc_release_refs(doc, refcount);
         node_obj->parent = This->parent;
     }
     else
     {
+        xmlNodePtr new_node;
+
         if (doc != This->node->doc)
             refcount = xmlnode_get_inst_cnt(node_obj);
 
         if (refcount) xmldoc_add_refs(This->node->doc, refcount);
         /* xmlAddChild doesn't unlink node from previous parent */
         xmlUnlinkNode(node_obj->node);
-        node_obj->node = xmlAddChild(This->node, node_obj->node);
+        new_node = xmlAddChild(This->node, node_obj->node);
+        if (new_node != node_obj->node)
+        {
+            if (refcount != 1)
+                FIXME("referenced xmlNode was freed, expect crashes\n");
+            xmlnode_add_ref(new_node);
+            node_obj->node = new_node;
+        }
         if (refcount) xmldoc_release_refs(doc, refcount);
         node_obj->parent = This->iface;
     }
@@ -673,48 +704,63 @@ HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode)
     return S_OK;
 }
 
-static inline xmlChar* trim_whitespace(xmlChar* str)
-{
-    xmlChar* ret = str;
-    int len;
-
-    if (!str)
-        return NULL;
-
-    while (*ret && isspace(*ret))
-        ++ret;
-    len = xmlStrlen(ret);
-    if (len)
-        while (isspace(ret[len-1])) --len;
-
-    ret = xmlStrndup(ret, len);
-    xmlFree(str);
-    return ret;
-}
-
-static xmlChar* do_get_text(xmlNodePtr node)
+static xmlChar* do_get_text(xmlNodePtr node, BOOL trim, DWORD *first, DWORD *last, BOOL *trail_ig_ws)
 {
     xmlNodePtr child;
     xmlChar* str;
     BOOL preserving = is_preserving_whitespace(node);
 
+    *first = -1;
+    *last = 0;
+
     if (!node->children)
     {
         str = xmlNodeGetContent(node);
+        *trail_ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS;
     }
     else
     {
-        xmlElementType prev_type = XML_TEXT_NODE;
+        BOOL ig_ws = FALSE;
         xmlChar* tmp;
+        DWORD pos = 0;
         str = xmlStrdup(BAD_CAST "");
+
+        if (node->type != XML_DOCUMENT_NODE)
+            ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS;
+        *trail_ig_ws = FALSE;
+
         for (child = node->children; child != NULL; child = child->next)
         {
             switch (child->type)
             {
-            case XML_ELEMENT_NODE:
-                tmp = do_get_text(child);
+            case XML_ELEMENT_NODE: {
+                DWORD node_first, node_last;
+
+                tmp = do_get_text(child, FALSE, &node_first, &node_last, trail_ig_ws);
+
+                if (node_first!=-1 && pos+node_first<*first)
+                    *first = pos+node_first;
+                if (node_last && pos+node_last>*last)
+                    *last = pos+node_last;
                 break;
+            }
             case XML_TEXT_NODE:
+                tmp = xmlNodeGetContent(child);
+                if (!preserving && tmp[0])
+                {
+                    xmlChar *beg;
+
+                    for (beg = tmp; *beg; beg++)
+                        if (!isspace(*beg)) break;
+
+                    if (!*beg)
+                    {
+                        ig_ws = TRUE;
+                        xmlFree(tmp);
+                        tmp = NULL;
+                    }
+                }
+                break;
             case XML_CDATA_SECTION_NODE:
             case XML_ENTITY_REF_NODE:
             case XML_ENTITY_NODE:
@@ -725,18 +771,33 @@ static xmlChar* do_get_text(xmlNodePtr node)
                 break;
             }
 
-            if (tmp)
+            if ((tmp && *tmp) || child->type==XML_CDATA_SECTION_NODE)
             {
-                if (*tmp)
+                if (ig_ws && str[0])
                 {
-                    if (prev_type == XML_ELEMENT_NODE && child->type == XML_ELEMENT_NODE)
-                        str = xmlStrcat(str, BAD_CAST " ");
-                    str = xmlStrcat(str, tmp);
-                    prev_type = child->type;
+                    str = xmlStrcat(str, BAD_CAST " ");
+                    pos++;
                 }
-                xmlFree(tmp);
+                if (tmp && *tmp) str = xmlStrcat(str, tmp);
+                if (child->type==XML_CDATA_SECTION_NODE && pos<*first)
+                    *first = pos;
+                if (tmp && *tmp) pos += xmlStrlen(tmp);
+                if (child->type==XML_CDATA_SECTION_NODE && pos>*last)
+                    *last = pos;
+                ig_ws = FALSE;
             }
+            if (tmp) xmlFree(tmp);
+
+            if (!ig_ws)
+            {
+                ig_ws = *(DWORD*)&child->_private & NODE_PRIV_TRAILING_IGNORABLE_WS;
+            }
+            if (!ig_ws)
+                ig_ws = *trail_ig_ws;
+            *trail_ig_ws = FALSE;
         }
+
+        *trail_ig_ws = ig_ws;
     }
 
     switch (node->type)
@@ -747,8 +808,24 @@ static xmlChar* do_get_text(xmlNodePtr node)
     case XML_ENTITY_NODE:
     case XML_DOCUMENT_NODE:
     case XML_DOCUMENT_FRAG_NODE:
-        if (!preserving)
-            str = trim_whitespace(str);
+        if (trim && !preserving)
+        {
+            xmlChar* ret = str;
+            int len;
+
+            if (!str)
+                break;
+
+            for (ret = str; *ret && isspace(*ret) && (*first)--; ret++)
+                if (*last) (*last)--;
+            for (len = xmlStrlen(ret)-1; len >= 0 && len >= *last; len--)
+                if(!isspace(ret[len])) break;
+
+            ret = xmlStrndup(ret, len+1);
+            xmlFree(str);
+            str = ret;
+            break;
+        }
         break;
     default:
         break;
@@ -761,10 +838,12 @@ HRESULT node_get_text(const xmlnode *This, BSTR *text)
 {
     BSTR str = NULL;
     xmlChar *content;
+    DWORD first, last;
+    BOOL tmp;
 
     if (!text) return E_INVALIDARG;
 
-    content = do_get_text(This->node);
+    content = do_get_text(This->node, TRUE, &first, &last, &tmp);
     if (content)
     {
         str = bstr_from_xmlChar(content);
@@ -1373,19 +1452,6 @@ HRESULT node_get_base_name(xmlnode *This, BSTR *name)
     return S_OK;
 }
 
-/* _private field holds a number of COM instances spawned from this libxml2 node */
-static void xmlnode_add_ref(xmlNodePtr node)
-{
-    if (node->type == XML_DOCUMENT_NODE) return;
-    InterlockedIncrement((LONG*)&node->_private);
-}
-
-static void xmlnode_release(xmlNodePtr node)
-{
-    if (node->type == XML_DOCUMENT_NODE) return;
-    InterlockedDecrement((LONG*)&node->_private);
-}
-
 void destroy_xmlnode(xmlnode *This)
 {
     if(This->node)
index b1703ec..3697cba 100644 (file)
@@ -131,7 +131,7 @@ reactos/dll/win32/msvfw32             # Synced to WineStaging-1.7.55
 reactos/dll/win32/msvidc32            # Synced to WineStaging-1.7.55
 reactos/dll/win32/msxml               # Synced to WineStaging-1.7.55
 reactos/dll/win32/msxml2              # Synced to WineStaging-1.7.55
-reactos/dll/win32/msxml3              # Synced to WineStaging-1.7.55
+reactos/dll/win32/msxml3              # Synced to WineStaging-1.9.4
 reactos/dll/win32/msxml4              # Synced to WineStaging-1.7.55
 reactos/dll/win32/msxml6              # Synced to WineStaging-1.7.55
 reactos/dll/win32/nddeapi             # Synced to WineStaging-1.7.55