Reviewed by Chris Blumenberg.
[WebKit-https.git] / WebCore / khtml / xml / dom_docimpl.cpp
index ac7349ebe8df5ed56e8994491ba54bebcb8e4171..653c2b1b828a429c0ffd9d357c861b88f4ec780f 100644 (file)
@@ -531,72 +531,80 @@ CSSStyleDeclarationImpl *DocumentImpl::createCSSStyleDeclaration()
 
 NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
 {
 
 NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
 {
-       NodeImpl *result = 0;
-
-       if(importedNode->nodeType() == Node::ELEMENT_NODE)
-       {
-               ElementImpl *tempElementImpl = createElementNS(getDocument()->namespaceURI(id()), importedNode->nodeName(), exceptioncode);
-                if (exceptioncode)
-                    return 0;
-               result = tempElementImpl;
-
-               if(static_cast<ElementImpl *>(importedNode)->attributes(true) && static_cast<ElementImpl *>(importedNode)->attributes(true)->length())
-               {
-                       NamedNodeMapImpl *attr = static_cast<ElementImpl *>(importedNode)->attributes();
-
-                       for(unsigned int i = 0; i < attr->length(); i++)
-                       {
-                               DOMString qualifiedName = attr->item(i)->nodeName();
-                               DOMString value = attr->item(i)->nodeValue();
-
-                               int colonpos = qualifiedName.find(':');
-                               DOMString localName = qualifiedName;
-                               if(colonpos >= 0)
-                               {
-                                       localName.remove(0, colonpos + 1);
-                                       // ### extract and set new prefix
-                               }
-
-                               NodeImpl::Id nodeId = getDocument()->attrId(getDocument()->namespaceURI(id()), localName.implementation(), false /* allocate */);
-                               tempElementImpl->setAttribute(nodeId, value.implementation(), exceptioncode);
-
-                               if(exceptioncode != 0)
-                                       break;
-                       }
-               }
-       }
-       else if(importedNode->nodeType() == Node::TEXT_NODE)
-       {
-               result = createTextNode(importedNode->nodeValue());
-               deep = false;
-       }
-       else if(importedNode->nodeType() == Node::CDATA_SECTION_NODE)
-       {
-               result = createCDATASection(importedNode->nodeValue());
-               deep = false;
-       }
-       else if(importedNode->nodeType() == Node::ENTITY_REFERENCE_NODE)
-               result = createEntityReference(importedNode->nodeName());
-       else if(importedNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
-       {
-               result = createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue());
-               deep = false;
-       }
-       else if(importedNode->nodeType() == Node::COMMENT_NODE)
-       {
-               result = createComment(importedNode->nodeValue());
-               deep = false;
-       }
-       else
-               exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+    exceptioncode = 0;
 
 
-       if(deep)
-       {
-               for(Node n = importedNode->firstChild(); !n.isNull(); n = n.nextSibling())
-                       result->appendChild(importNode(n.handle(), true, exceptioncode), exceptioncode);
-       }
+    switch (importedNode->nodeType()) {
+        case Node::TEXT_NODE:
+            return createTextNode(importedNode->nodeValue());
+        case Node::CDATA_SECTION_NODE:
+            return createCDATASection(importedNode->nodeValue());
+        case Node::ENTITY_REFERENCE_NODE:
+            return createEntityReference(importedNode->nodeName());
+        case Node::PROCESSING_INSTRUCTION_NODE:
+            return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue());
+        case Node::COMMENT_NODE:
+            return createComment(importedNode->nodeValue());
+        case Node::ELEMENT_NODE: {
+            ElementImpl *oldElement = static_cast<ElementImpl *>(importedNode);
+            DocumentImpl *oldDoc = oldElement->getDocument();
+            static DOMString HTMLNamespace(XHTML_NAMESPACE);
+            DOMString elementNamespace = oldElement->isHTMLElement() ? HTMLNamespace : oldElement->namespaceURI();
+            ElementImpl *newElement = createElementNS(elementNamespace.implementation(), oldElement->tagName(), exceptioncode);
+            if (exceptioncode != 0)
+                return 0;
+
+            newElement->ref();
+
+            NamedAttrMapImpl *attrs = oldElement->attributes(true);
+            if (attrs) {
+                unsigned length = attrs->length();
+                for (unsigned i = 0; i < length; i++) {
+                    AttrImpl *attr = attrs->item(i);
+                    DOMString qualifiedName = attr->nodeName();
+                    DOMString value = attr->nodeValue();
+
+                    int colonpos = qualifiedName.find(':');
+                    DOMString localName = qualifiedName;
+                    if (colonpos >= 0) {
+                        localName.remove(0, colonpos + 1);
+                        // ### extract and set new prefix
+                    }
+
+                    NodeImpl::Id nodeId = attrId(oldDoc->namespaceURI(attr->attrImpl()->id()), localName.implementation(), false /* allocate */);
+                    newElement->setAttribute(nodeId, value.implementation(), exceptioncode);
+                    if (exceptioncode != 0) {
+                        newElement->deref();
+                        return 0;
+                    }
+                }
+            }
 
 
-       return result;
+            if (deep) {
+                for (NodeImpl *oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
+                    NodeImpl *newChild = importNode(oldChild, true, exceptioncode);
+                    if (exceptioncode != 0) {
+                        newElement->deref();
+                        return 0;
+                    }
+                    newElement->appendChild(newChild, exceptioncode);
+                    if (exceptioncode != 0) {
+                        newElement->deref();
+                        return 0;
+                    }
+                }
+            }
+
+            // Trick to get the result back to the floating state, with 0 refs but not destroyed.
+            newElement->setParent(this);
+            newElement->deref();
+            newElement->setParent(0);
+
+            return newElement;
+        }
+    }
+
+    exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+    return 0;
 }
 
 ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName, int &exceptioncode)
 }
 
 ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName, int &exceptioncode)
@@ -1894,7 +1902,7 @@ void DocumentImpl::processHttpEquiv(const DOMString &equiv, const DOMString &con
 {
     assert(!equiv.isNull() && !content.isNull());
 
 {
     assert(!equiv.isNull() && !content.isNull());
 
-    KHTMLPart *part = getDocument()->part();
+    KHTMLPart *part = this->part();
 
     if (strcasecmp(equiv, "default-style") == 0) {
         // The preferred style set has been overridden as per section 
 
     if (strcasecmp(equiv, "default-style") == 0) {
         // The preferred style set has been overridden as per section 
@@ -1941,9 +1949,9 @@ void DocumentImpl::processHttpEquiv(const DOMString &equiv, const DOMString &con
             if ( ok && part )
 #if APPLE_CHANGES
                 // We want a new history item if the refresh timeout > 1 second
             if ( ok && part )
 #if APPLE_CHANGES
                 // We want a new history item if the refresh timeout > 1 second
-                part->scheduleRedirection(delay, getDocument()->completeURL( str ), delay <= 1);
+                part->scheduleRedirection(delay, completeURL( str ), delay <= 1);
 #else
 #else
-                part->scheduleRedirection(delay, getDocument()->completeURL( str ));
+                part->scheduleRedirection(delay, completeURL( str ));
 #endif
         }
     }
 #endif
         }
     }
@@ -2122,8 +2130,7 @@ DOMString DocumentImpl::attrName(NodeImpl::Id _id) const
 
     // Attribute names are always lowercase in the DOM for both
     // HTML and XHTML.
 
     // Attribute names are always lowercase in the DOM for both
     // HTML and XHTML.
-    if (getDocument()->isHTMLDocument() ||
-        getDocument()->htmlMode() == DocumentImpl::XHtml)
+    if (isHTMLDocument() || htmlMode() == XHtml)
         return result.lower();
 
     return result;
         return result.lower();
 
     return result;
@@ -2198,7 +2205,7 @@ DOMString DocumentImpl::tagName(NodeImpl::Id _id) const
         return m_elementNames[localNamePart(_id) - (ID_LAST_TAG + 1)];
     else {
         // ### put them in a cache
         return m_elementNames[localNamePart(_id) - (ID_LAST_TAG + 1)];
     else {
         // ### put them in a cache
-        if (getDocument()->htmlMode() == DocumentImpl::XHtml)
+        if (htmlMode() == XHtml)
             return getTagName(_id).lower();
         else
             return getTagName(_id);
             return getTagName(_id).lower();
         else
             return getTagName(_id);
@@ -2223,14 +2230,12 @@ StyleSheetListImpl* DocumentImpl::styleSheets()
     return m_styleSheets;
 }
 
     return m_styleSheets;
 }
 
-DOMString 
-DocumentImpl::preferredStylesheetSet()
+DOMString DocumentImpl::preferredStylesheetSet()
 {
   return m_preferredStylesheetSet;
 }
 
 {
   return m_preferredStylesheetSet;
 }
 
-DOMString 
-DocumentImpl::selectedStylesheetSet()
+DOMString DocumentImpl::selectedStylesheetSet()
 {
   return view() ? view()->part()->d->m_sheetUsed : DOMString();
 }
 {
   return view() ? view()->part()->d->m_sheetUsed : DOMString();
 }
@@ -2499,8 +2504,8 @@ bool DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
     // Remove focus from the existing focus node (if any)
     if (oldFocusNode) {
         // This goes hand in hand with the Qt focus setting below.
     // Remove focus from the existing focus node (if any)
     if (oldFocusNode) {
         // This goes hand in hand with the Qt focus setting below.
-        if (!newFocusNode && getDocument()->view()) {
-            getDocument()->view()->setFocus();
+        if (!newFocusNode && view()) {
+            view()->setFocus();
         }
 
         if (oldFocusNode->active())
         }
 
         if (oldFocusNode->active())
@@ -2562,20 +2567,20 @@ bool DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
         m_focusNode->setFocus();
         // eww, I suck. set the qt focus correctly
         // ### find a better place in the code for this
         m_focusNode->setFocus();
         // eww, I suck. set the qt focus correctly
         // ### find a better place in the code for this
-        if (getDocument()->view()) {
+        if (view()) {
             QWidget *focusWidget = widgetForNode(m_focusNode);
             if (focusWidget) {
                 // Make sure a widget has the right size before giving it focus.
                 // Otherwise, we are testing edge cases of the QWidget code.
                 // Specifically, in WebCore this does not work well for text fields.
             QWidget *focusWidget = widgetForNode(m_focusNode);
             if (focusWidget) {
                 // Make sure a widget has the right size before giving it focus.
                 // Otherwise, we are testing edge cases of the QWidget code.
                 // Specifically, in WebCore this does not work well for text fields.
-                getDocument()->updateLayout();
+                updateLayout();
                 // Re-get the widget in case updating the layout changed things.
                 focusWidget = widgetForNode(m_focusNode);
             }
             if (focusWidget)
                 focusWidget->setFocus();
             else
                 // Re-get the widget in case updating the layout changed things.
                 focusWidget = widgetForNode(m_focusNode);
             }
             if (focusWidget)
                 focusWidget->setFocus();
             else
-                getDocument()->view()->setFocus();
+                view()->setFocus();
         }
    }
 
         }
    }