File indexing completed on 2024-04-28 11:39:35

0001 /*
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
0005  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
0006  *           (C) 2001 Dirk Mueller (mueller@kde.org)
0007  *           (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
0008  *           (C) 2005, 2009, 2010 Maksim Orlovich (maksim@kde.org)
0009  *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
0010  *
0011  * This library is free software; you can redistribute it and/or
0012  * modify it under the terms of the GNU Library General Public
0013  * License as published by the Free Software Foundation; either
0014  * version 2 of the License, or (at your option) any later version.
0015  *
0016  * This library is distributed in the hope that it will be useful,
0017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019  * Library General Public License for more details.
0020  *
0021  * You should have received a copy of the GNU Library General Public License
0022  * along with this library; see the file COPYING.LIB.  If not, write to
0023  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0024  * Boston, MA 02110-1301, USA.
0025  */
0026 
0027 #include "dom_nodeimpl.h"
0028 
0029 #include <dom/dom_exception.h>
0030 #include "dom_elementimpl.h"
0031 #include "dom_textimpl.h"
0032 #include "dom2_eventsimpl.h"
0033 #include "dom_docimpl.h"
0034 #include "dom_nodelistimpl.h"
0035 #include "xml/dom_position.h"
0036 #include "xml/dom_selection.h"
0037 #include "xml/wa_selectors.h"
0038 #include "dom_restyler.h"
0039 #include "html/html_objectimpl.h"
0040 
0041 #include "khtml_debug.h"
0042 
0043 #include <rendering/render_text.h>
0044 #include <rendering/render_flow.h>
0045 #include <rendering/render_line.h>
0046 
0047 #include <ecma/kjs_proxy.h>
0048 #include <khtmlview.h>
0049 #include <khtml_part.h>
0050 //Added by qt3to4:
0051 #include <QMouseEvent>
0052 #include <QKeyEvent>
0053 #include <QEvent>
0054 
0055 #if 0
0056 // from khtml_caret_p.h
0057 namespace khtml
0058 {
0059 void /*KHTML_NO_EXPORT*/ mapDOMPosToRenderPos(DOM::NodeImpl *node, long offset,
0060         khtml::RenderObject *&r, long &r_ofs, bool &outside, bool &outsideEnd);
0061 }
0062 #endif
0063 
0064 using namespace DOM;
0065 using namespace khtml;
0066 
0067 NodeImpl::NodeImpl(DocumentImpl *doc)
0068     : m_document(doc),
0069       m_previous(nullptr),
0070       m_next(nullptr),
0071       m_render(nullptr),
0072       m_hasId(false),
0073       m_attached(false),
0074       m_closed(false),
0075       m_changed(false),
0076       m_hasChangedChild(false),
0077       m_changedAscendentAttribute(false),
0078       m_inDocument(false),
0079       m_hasAnchor(false),
0080       m_hovered(false),
0081       m_focused(false),
0082       m_active(false),
0083       m_implicit(false),
0084       m_htmlCompat(false),
0085       m_hasClass(false),
0086       m_hasCombinedStyle(false),
0087       m_hasHoverDependency(false),
0088       m_elementHasRareData(false),
0089       m_needsStyleAttributeUpdate(false)
0090 {
0091 }
0092 
0093 NodeImpl::~NodeImpl()
0094 {
0095     if (m_render) {
0096         detach();
0097     }
0098     if (m_previous) {
0099         m_previous->setNextSibling(nullptr);
0100     }
0101     if (m_next) {
0102         m_next->setPreviousSibling(nullptr);
0103     }
0104 }
0105 
0106 DOMString NodeImpl::nodeValue() const
0107 {
0108     return DOMString();
0109 }
0110 
0111 void NodeImpl::setNodeValue(const DOMString &/*_nodeValue*/, int &/*exceptioncode*/)
0112 {
0113     // by default nodeValue is null, so setting it has no effect
0114     // don't throw NO_MODIFICATION_ALLOWED_ERR from here, DOMTS-Core-Level1's hc_nodevalue03
0115     // (createEntityReference().setNodeValue())) says it would be wrong.
0116     // This must be done by subclasses instead.
0117 }
0118 
0119 DOMString NodeImpl::nodeName() const
0120 {
0121     return DOMString();
0122 }
0123 
0124 unsigned short NodeImpl::nodeType() const
0125 {
0126     return 0;
0127 }
0128 
0129 WTF::PassRefPtr<DOM::NodeListImpl> NodeImpl::childNodes()
0130 {
0131     return new ChildNodeListImpl(this);
0132 }
0133 
0134 NodeImpl *NodeImpl::firstChild() const
0135 {
0136     return nullptr;
0137 }
0138 
0139 NodeImpl *NodeImpl::lastChild() const
0140 {
0141     return nullptr;
0142 }
0143 
0144 NodeImpl *NodeImpl::insertBefore(NodeImpl *, NodeImpl *, int &exceptioncode)
0145 {
0146     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0147     return nullptr;
0148 }
0149 
0150 void NodeImpl::replaceChild(NodeImpl *, NodeImpl *, int &exceptioncode)
0151 {
0152     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0153 }
0154 
0155 void NodeImpl::removeChild(NodeImpl *, int &exceptioncode)
0156 {
0157     exceptioncode = DOMException::NOT_FOUND_ERR;
0158 }
0159 
0160 NodeImpl *NodeImpl::appendChild(NodeImpl *, int &exceptioncode)
0161 {
0162     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0163     return nullptr;
0164 }
0165 
0166 void NodeImpl::remove(int &exceptioncode)
0167 {
0168     exceptioncode = 0;
0169     if (!parentNode()) {
0170         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0171         return;
0172     }
0173 
0174     parentNode()->removeChild(this, exceptioncode);
0175 }
0176 
0177 bool NodeImpl::hasChildNodes() const
0178 {
0179     return false;
0180 }
0181 
0182 void NodeImpl::normalize()
0183 {
0184     // ### normalize attributes? (when we store attributes using child nodes)
0185     int exceptioncode = 0;
0186     NodeImpl *child = firstChild();
0187 
0188     // Recursively go through the subtree beneath us, normalizing all nodes. In the case
0189     // where there are two adjacent text nodes, they are merged together
0190     while (child) {
0191         NodeImpl *nextChild = child->nextSibling();
0192 
0193         if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
0194             // Current child and the next one are both text nodes... merge them
0195             TextImpl *currentText = static_cast<TextImpl *>(child);
0196             TextImpl *nextText = static_cast<TextImpl *>(nextChild);
0197 
0198             currentText->appendData(nextText->data(), exceptioncode);
0199             if (exceptioncode) {
0200                 return;
0201             }
0202 
0203             removeChild(nextChild, exceptioncode);
0204             if (exceptioncode) {
0205                 return;
0206             }
0207         } else {
0208             child->normalize();
0209             child = nextChild;
0210         }
0211     }
0212 }
0213 
0214 DOMString NodeImpl::prefix() const
0215 {
0216     // For nodes other than elements and attributes, the prefix is always null
0217     return DOMString();
0218 }
0219 
0220 DOMString NodeImpl::namespaceURI() const
0221 {
0222     return DOMString();
0223 }
0224 
0225 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode)
0226 {
0227     // The spec says that for nodes other than elements and attributes, prefix is always null.
0228     // It does not say what to do when the user tries to set the prefix on another type of
0229     // node, however mozilla throws a NAMESPACE_ERR exception
0230     exceptioncode = DOMException::NAMESPACE_ERR;
0231 }
0232 
0233 DOMString NodeImpl::textContent() const
0234 {
0235     switch (nodeType()) {
0236     case Node::TEXT_NODE:
0237     case Node::CDATA_SECTION_NODE:
0238     case Node::COMMENT_NODE:
0239     case Node::PROCESSING_INSTRUCTION_NODE:
0240         return nodeValue();
0241 
0242     case Node::ELEMENT_NODE:
0243     case Node::ATTRIBUTE_NODE:
0244     case Node::ENTITY_NODE:
0245     case Node::ENTITY_REFERENCE_NODE:
0246     case Node::DOCUMENT_FRAGMENT_NODE: {
0247         DOMString s = "";
0248 
0249         for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) {
0250             if (child->nodeType() == Node::COMMENT_NODE ||
0251                     child->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
0252                 continue;
0253             }
0254 
0255             s += child->textContent();
0256         }
0257 
0258         return s;
0259     }
0260 
0261     case Node::DOCUMENT_NODE:
0262     case Node::DOCUMENT_TYPE_NODE:
0263     case Node::NOTATION_NODE:
0264     default:
0265         return DOMString();
0266     }
0267 }
0268 
0269 void NodeImpl::setTextContent(const DOMString &text, int &ec)
0270 {
0271     if (isReadOnly()) {
0272         ec = DOMException::NO_MODIFICATION_ALLOWED_ERR;
0273         return;
0274     }
0275 
0276     switch (nodeType()) {
0277     case Node::TEXT_NODE:
0278     case Node::CDATA_SECTION_NODE:
0279     case Node::COMMENT_NODE:
0280     case Node::PROCESSING_INSTRUCTION_NODE:
0281         setNodeValue(text, ec);
0282         break;
0283     case Node::ELEMENT_NODE:
0284     case Node::ATTRIBUTE_NODE:
0285     case Node::ENTITY_NODE:
0286     case Node::ENTITY_REFERENCE_NODE:
0287     case Node::DOCUMENT_FRAGMENT_NODE: {
0288         NodeBaseImpl *container = static_cast<NodeBaseImpl *>(this);
0289 
0290         container->removeChildren();
0291 
0292         if (!text.isEmpty()) {
0293             appendChild(document()->createTextNode(text.implementation()), ec);
0294         }
0295         break;
0296     }
0297     case Node::DOCUMENT_NODE:
0298     case Node::DOCUMENT_TYPE_NODE:
0299     case Node::NOTATION_NODE:
0300     default:
0301         // Do nothing
0302         break;
0303     }
0304 }
0305 
0306 DOMString NodeImpl::localName() const
0307 {
0308     return DOMString();
0309 }
0310 
0311 void NodeImpl::setFirstChild(NodeImpl *)
0312 {
0313 }
0314 
0315 void NodeImpl::setLastChild(NodeImpl *)
0316 {
0317 }
0318 
0319 NodeImpl *NodeImpl::addChild(NodeImpl *)
0320 {
0321     return nullptr;
0322 }
0323 
0324 void NodeImpl::getCaret(int /*offset*/, bool override, int &_x, int &_y, int &width, int &height)
0325 {
0326     if (m_render) {
0327         RenderObject *r = nullptr;
0328         long r_ofs = 0;
0329         bool outside, outsideEnd;
0330 #if 0
0331 // qCDebug(KHTML_LOG) << "getCaret: node " << this << " " << nodeName().string() << " offset: " << offset;
0332 #endif
0333 //         mapDOMPosToRenderPos(this, offset, r, r_ofs, outside, outsideEnd);
0334         outside = false;
0335         outsideEnd = false;
0336 #if 0
0337 // qCDebug(KHTML_LOG) << "getCaret: r " << r << " " << (r?r->renderName():QString()) << " r_ofs: " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd;
0338 #endif
0339         if (r) {
0340             r->caretPos(r_ofs, override * RenderObject::CFOverride
0341                         + outside * RenderObject::CFOutside
0342                         + outsideEnd * RenderObject::CFOutsideEnd, _x, _y, width, height);
0343         } else {
0344             _x = _y = height = -1, width = 1;
0345         }
0346     } else {
0347         _x = _y = height = -1, width = 1;
0348     }
0349 }
0350 
0351 bool NodeImpl::isContentEditable() const
0352 {
0353     return parentNode() ? parentNode()->isContentEditable() : false;
0354 }
0355 
0356 QRect NodeImpl::getRect() const
0357 {
0358     int _x, _y;
0359     if (m_render && m_render->absolutePosition(_x, _y))
0360         return QRect(_x + m_render->inlineXPos(), _y + m_render->inlineYPos(),
0361                      m_render->width(), m_render->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra());
0362 
0363     return QRect();
0364 }
0365 
0366 void NodeImpl::setChanged(bool b)
0367 {
0368     if (b && !attached()) { // changed compared to what?
0369         return;
0370     }
0371 
0372     m_changed = b;
0373     if (b) {
0374         NodeImpl *p = parentNode();
0375         while (p) {
0376             p->setHasChangedChild(true);
0377             p = p->parentNode();
0378         }
0379         document()->setDocumentChanged();
0380     }
0381 }
0382 
0383 bool NodeImpl::isInline() const
0384 {
0385     if (m_render) {
0386         return m_render->style()->display() == khtml::INLINE;
0387     }
0388     return !isElementNode();
0389 }
0390 
0391 unsigned long NodeImpl::nodeIndex() const
0392 {
0393     NodeImpl *_tempNode = previousSibling();
0394     unsigned long count = 0;
0395     for (count = 0; _tempNode; count++) {
0396         _tempNode = _tempNode->previousSibling();
0397     }
0398     return count;
0399 }
0400 
0401 DocumentImpl *NodeImpl::eventTargetDocument()
0402 {
0403     return document();
0404 }
0405 
0406 void NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
0407 {
0408     evt->setTarget(this);
0409 
0410     dispatchGenericEvent(evt, exceptioncode);
0411 
0412     KHTMLPart *part = document()->part();
0413     // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
0414     // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
0415     // So there is no need for the interpreter to keep the event in its cache
0416     if (tempEvent && part && part->jScript()) {
0417         part->jScript()->finishedWithEvent(evt);
0418     }
0419 }
0420 
0421 void NodeImpl::dispatchGenericEvent(EventImpl *evt, int &/*exceptioncode */)
0422 {
0423     // ### check that type specified
0424 
0425     ref();
0426 
0427     // work out what nodes to send event to
0428     QList<EventTargetImpl *> nodeChain;
0429 
0430     if (evt->target()->eventTargetType() != DOM_NODE) {
0431         // The target is the only thing that goes into the chain.
0432         nodeChain.prepend(evt->target());
0433         evt->target()->ref();
0434 
0435         // ... except, well, load events lie and say their target is the document,
0436         // so we patch that up now (since we want it as Window before we got here
0437         if (evt->id() == EventImpl::LOAD_EVENT && evt->target()->eventTargetType() == WINDOW) {
0438             evt->setTarget(document());
0439         }
0440     } else if (inDocument()) {
0441         for (NodeImpl *n = this; n; n = n->parentNode()) {
0442             n->ref();
0443             nodeChain.prepend(n);
0444         }
0445 
0446         // If the event isn't a load event, we propagate it up to window as well.
0447         // The exclusion is so that things like image load events don't make it
0448         // all the way upto window.onload. Meanwhile, the main load event
0449         // is dispatched specially, via dispatchWindowEvent, with the case
0450         // above doing the necessary fiddling for it.
0451         if (evt->id() != EventImpl::LOAD_EVENT) {
0452             EventTargetImpl *t = document()->windowEventTarget();
0453             t->ref();
0454             nodeChain.prepend(t);
0455         }
0456     } else {
0457         // if node is not in the document just send event to itself
0458         ref();
0459         nodeChain.prepend(this);
0460     }
0461 
0462     // trigger any capturing event handlers on our way down
0463     evt->setEventPhase(Event::CAPTURING_PHASE);
0464     QListIterator<EventTargetImpl *> it(nodeChain);
0465     while (it.hasNext()) {
0466         EventTargetImpl *cur = it.next();
0467         if (cur == this || evt->propagationStopped()) {
0468             break;
0469         }
0470         evt->setCurrentTarget(cur);
0471         cur->handleLocalEvents(evt, true);
0472     }
0473 
0474     // dispatch to the actual target node
0475     it.toBack();
0476     EventTargetImpl *curn = it.hasPrevious() ? it.previous() : nullptr;
0477     EventTargetImpl *propagationSentinel = nullptr;
0478     if (curn && !evt->propagationStopped()) {
0479         evt->setEventPhase(Event::AT_TARGET);
0480         evt->setCurrentTarget(curn);
0481         curn->handleLocalEvents(evt, true);
0482         if (!evt->propagationStopped()) {
0483             curn->handleLocalEvents(evt, false);
0484         } else {
0485             propagationSentinel = curn;
0486         }
0487     }
0488 
0489     curn = it.hasPrevious() ? it.previous() : nullptr;
0490 
0491     if (evt->bubbles()) {
0492         evt->setEventPhase(Event::BUBBLING_PHASE);
0493         while (curn && !evt->propagationStopped()) {
0494             if (evt->propagationStopped()) {
0495                 propagationSentinel = curn;
0496             }
0497             evt->setCurrentTarget(curn);
0498             curn->handleLocalEvents(evt, false);
0499             curn = it.hasPrevious() ? it.previous() : nullptr;
0500         }
0501 
0502         // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
0503         evt->setCurrentTarget(nullptr);
0504         evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
0505 
0506         it.toBack();
0507         while (it.hasPrevious()) {
0508             curn = it.previous();
0509             if (curn == propagationSentinel || evt->defaultPrevented() || evt->defaultHandled()) {
0510                 break;
0511             }
0512             curn->defaultEventHandler(evt);
0513         }
0514 
0515         if (evt->id() == EventImpl::CLICK_EVENT && !evt->defaultPrevented() &&
0516                 static_cast<MouseEventImpl *>(evt)->button() == 0) { // LMB click
0517             dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, static_cast<UIEventImpl *>(evt)->detail());
0518         }
0519     }
0520 
0521     // deref all nodes in chain
0522     it.toFront();
0523     while (it.hasNext()) {
0524         it.next()->deref();    // this may delete us
0525     }
0526 
0527     DocumentImpl::updateDocumentsRendering();
0528 
0529     deref();
0530 }
0531 
0532 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
0533 {
0534     int exceptioncode = 0;
0535     EventImpl *const evt = new EventImpl(static_cast<EventImpl::EventId>(_id), canBubbleArg, cancelableArg);
0536     evt->ref();
0537     dispatchEvent(evt, exceptioncode, true);
0538     bool ret = !evt->defaultPrevented();
0539     evt->deref();
0540     return ret;
0541 }
0542 
0543 void NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
0544 {
0545     EventImpl *const evt = new EventImpl(static_cast<EventImpl::EventId>(_id), canBubbleArg, cancelableArg);
0546     dispatchWindowEvent(evt);
0547 }
0548 
0549 void NodeImpl::dispatchWindowEvent(EventImpl *evt)
0550 {
0551     evt->setTarget(document()->windowEventTarget());
0552     evt->ref();
0553 
0554     int exceptioncode = 0;
0555     dispatchGenericEvent(evt, exceptioncode);
0556 
0557     if (evt->id() == EventImpl::LOAD_EVENT) {
0558         // Trigger Load Event on the enclosing frame if there is one
0559         DOM::HTMLPartContainerElementImpl *elt = document()->ownerElement();
0560         if (elt) {
0561             elt->slotEmitLoadEvent();
0562         }
0563     }
0564 
0565     evt->deref();
0566 }
0567 
0568 void NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
0569 {
0570     bool cancelable = true;
0571     int detail = overrideDetail; // defaults to 0
0572     EventImpl::EventId evtId;
0573     if (overrideId) {
0574         evtId = static_cast<EventImpl::EventId>(overrideId);
0575     } else {
0576         switch (_mouse->type()) {
0577         case QEvent::MouseButtonPress:
0578             evtId = EventImpl::MOUSEDOWN_EVENT;
0579             break;
0580         case QEvent::MouseButtonRelease:
0581             evtId = EventImpl::MOUSEUP_EVENT;
0582             break;
0583         case QEvent::MouseButtonDblClick:
0584             evtId = EventImpl::CLICK_EVENT;
0585             detail = 1; // ### support for multiple double clicks
0586             break;
0587         case QEvent::MouseMove:
0588             evtId = EventImpl::MOUSEMOVE_EVENT;
0589             cancelable = false;
0590             break;
0591         default:
0592             return;
0593         }
0594     }
0595 
0596     int exceptioncode = 0;
0597     int pageX = _mouse->x();
0598     int pageY = _mouse->y();
0599     if (document()->view()) {
0600         document()->view()->revertTransforms(pageX, pageY);
0601     }
0602     int clientX = pageX;
0603     int clientY = pageY;
0604     if (document()->view()) {
0605         document()->view()->contentsToViewport(pageX, pageY, pageX, pageY);
0606     }
0607 
0608     int screenX = _mouse->globalX();
0609     int screenY = _mouse->globalY();
0610 
0611     int button = -1;
0612     switch (_mouse->button()) {
0613     case Qt::LeftButton:
0614         button = 0;
0615         break;
0616     case Qt::MidButton:
0617         button = 1;
0618         break;
0619     case Qt::RightButton:
0620         button = 2;
0621         break;
0622     default:
0623         break;
0624     }
0625     bool ctrlKey = (_mouse->modifiers() & Qt::ControlModifier);
0626     bool altKey = (_mouse->modifiers() & Qt::AltModifier);
0627     bool shiftKey = (_mouse->modifiers() & Qt::ShiftModifier);
0628     bool metaKey = (_mouse->modifiers() & Qt::MetaModifier);
0629 
0630     EventImpl *const evt = new MouseEventImpl(evtId, true, cancelable, document()->defaultView(),
0631             detail, screenX, screenY, clientX, clientY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey,
0632             button, nullptr);
0633     evt->ref();
0634     dispatchEvent(evt, exceptioncode, true);
0635     evt->deref();
0636 }
0637 
0638 void NodeImpl::dispatchUIEvent(int _id, int detail)
0639 {
0640     assert(!((_id != EventImpl::DOMFOCUSIN_EVENT &&
0641               _id != EventImpl::DOMFOCUSOUT_EVENT &&
0642               _id != EventImpl::DOMACTIVATE_EVENT)));
0643 
0644     bool cancelable = false;
0645     if (_id == EventImpl::DOMACTIVATE_EVENT) {
0646         cancelable = true;
0647     }
0648 
0649     int exceptioncode = 0;
0650     UIEventImpl *const evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id), true,
0651             cancelable, document()->defaultView(), detail);
0652     evt->ref();
0653     dispatchEvent(evt, exceptioncode, true);
0654     evt->deref();
0655 }
0656 
0657 void NodeImpl::dispatchSubtreeModifiedEvent()
0658 {
0659     childrenChanged();
0660     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
0661     if (!document()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER)) {
0662         return;
0663     }
0664     int exceptioncode = 0;
0665     ref();
0666     MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT, true,
0667             false, nullptr, DOMString(), DOMString(), DOMString(), 0);
0668     evt->ref();
0669     dispatchEvent(evt, exceptioncode, true);
0670     evt->deref();
0671     derefOnly();
0672 }
0673 
0674 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key, bool keypress)
0675 {
0676     int exceptioncode = 0;
0677     //qCDebug(KHTML_LOG) << "DOM::NodeImpl: dispatching keyboard event";
0678     EventImpl *keyEventImpl;
0679     if (keypress) {
0680         keyEventImpl = new TextEventImpl(key, document()->defaultView());
0681     } else {
0682         keyEventImpl = new KeyboardEventImpl(key, document()->defaultView());
0683     }
0684     keyEventImpl->ref();
0685     dispatchEvent(keyEventImpl, exceptioncode, true);
0686     bool r = keyEventImpl->defaultHandled() || keyEventImpl->defaultPrevented();
0687     keyEventImpl->deref();
0688     return r;
0689 }
0690 
0691 unsigned long NodeImpl::childNodeCount()
0692 {
0693     return 0;
0694 }
0695 
0696 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
0697 {
0698     return nullptr;
0699 }
0700 
0701 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
0702 {
0703     if (firstChild() || stayWithin == this) {
0704         return firstChild();
0705     } else if (nextSibling()) {
0706         return nextSibling();
0707     } else {
0708         const NodeImpl *n = this;
0709         while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin)) {
0710             n = n->parentNode();
0711         }
0712         if (n) {
0713             return n->nextSibling();
0714         }
0715     }
0716     return nullptr;
0717 }
0718 
0719 NodeImpl *NodeImpl::traversePreviousNode() const
0720 {
0721     if (previousSibling()) {
0722         NodeImpl *n = previousSibling();
0723         while (n->lastChild()) {
0724             n = n->lastChild();
0725         }
0726         return n;
0727     } else if (parentNode()) {
0728         return parentNode();
0729     } else {
0730         return nullptr;
0731     }
0732 }
0733 
0734 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
0735 {
0736     // Perform error checking as required by spec for setting Node.prefix. Used by
0737     // ElementImpl::setPrefix() and AttrImpl::setPrefix()
0738 
0739     // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
0740     if (!Element::khtmlValidPrefix(_prefix)) {
0741         exceptioncode = DOMException::INVALID_CHARACTER_ERR;
0742         return;
0743     }
0744 
0745     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
0746     if (isReadOnly()) {
0747         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
0748         return;
0749     }
0750 
0751     // NAMESPACE_ERR: - Raised if the specified prefix is malformed
0752     // - if the namespaceURI of this node is null,
0753     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
0754     //   "http://www.w3.org/XML/1998/namespace",
0755     // - if this node is an attribute and the specified prefix is "xmlns" and
0756     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
0757     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
0758     if (Element::khtmlMalformedPrefix(_prefix) || /*FIXME: use IDString somehow here (namespacePart(id()) == defaultNamespace && id() > ID_LAST_TAG) ||*/
0759             (_prefix == "xml" && namespaceURI() != "http://www.w3.org/XML/1998/namespace")) {
0760         exceptioncode = DOMException::NAMESPACE_ERR;
0761         return;
0762     }
0763 }
0764 
0765 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
0766 {
0767     // Perform error checking as required by spec for adding a new child. Used by
0768     // appendChild(), replaceChild() and insertBefore()
0769 
0770     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
0771     if (!newChild) {
0772         exceptioncode = DOMException::NOT_FOUND_ERR;
0773         return;
0774     }
0775 
0776     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
0777     if (isReadOnly()) {
0778         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
0779         return;
0780     }
0781 
0782     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
0783     // created this node.
0784     // We assume that if newChild is a DocumentFragment, all children are created from the same document
0785     // as the fragment itself (otherwise they could not have been added as children)
0786     if (newChild->document() != document()) {
0787         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
0788         return;
0789     }
0790 
0791     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
0792     // newChild node, or if the node to append is one of this node's ancestors.
0793 
0794     // check for ancestor/same node
0795     if (isAncestor(newChild)) {
0796         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0797         return;
0798     }
0799 
0800     // check node allowed
0801     if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
0802         // newChild is a DocumentFragment... check all its children instead of newChild itself
0803         NodeImpl *child;
0804         for (child = newChild->firstChild(); child; child = child->nextSibling()) {
0805             if (!childTypeAllowed(child->nodeType())) {
0806                 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0807                 return;
0808             }
0809         }
0810     } else {
0811         // newChild is not a DocumentFragment... check if it's allowed directly
0812         if (!childTypeAllowed(newChild->nodeType())) {
0813             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
0814             return;
0815         }
0816     }
0817 }
0818 
0819 bool NodeImpl::isAncestor(NodeImpl *other) const
0820 {
0821     // Return true if other is the same as this node or an ancestor of it, otherwise false
0822     const NodeImpl *n;
0823     for (n = this; n; n = n->parentNode()) {
0824         if (n == other) {
0825             return true;
0826         }
0827     }
0828     return false;
0829 }
0830 
0831 bool NodeImpl::childAllowed(NodeImpl *newChild)
0832 {
0833     return childTypeAllowed(newChild->nodeType());
0834 }
0835 
0836 NodeImpl::StyleChange NodeImpl::diff(khtml::RenderStyle *s1, khtml::RenderStyle *s2)
0837 {
0838     // This method won't work when a style contains noninherited properties with "inherit" value.
0839     StyleChange ch = NoInherit;
0840 
0841     EDisplay display1 = s1 ? s1->display() : NONE;
0842     EDisplay display2 = s2 ? s2->display() : NONE;
0843     EPosition position1 = s1 ? s1->position() : PSTATIC;
0844     EPosition position2 = s2 ? s2->position() : PSTATIC;
0845 
0846     if (display1 != display2 || position1 != position2) {
0847         ch = Detach;
0848     } else if (!s1 || !s2) {
0849         ch = Inherit;
0850     } else if (*s1 == *s2) {
0851         ch = NoChange;
0852     } else if (s1->useNormalContent() != s2->useNormalContent()) {
0853         ch = Detach;    // when we add generated content all children must be detached
0854     } else if (s1->inheritedNotEqual(s2)) {
0855         ch = Inherit;
0856     }
0857 
0858     // Because the first-letter implementation is so f..ked up, the easiest way
0859     // to update first-letter is to remove the entire node and readd it.
0860     if (ch < Detach && pseudoDiff(s1, s2, khtml::RenderStyle::FIRST_LETTER)) {
0861         ch = Detach;
0862     }
0863     // If the other pseudoStyles have changed, we want to return NoInherit
0864     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::BEFORE)) {
0865         ch = NoInherit;
0866     }
0867     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::AFTER)) {
0868         ch = NoInherit;
0869     }
0870     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::MARKER)) {
0871         ch = NoInherit;
0872     }
0873     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::SELECTION)) {
0874         ch = NoInherit;
0875     }
0876     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::FIRST_LINE)) {
0877         ch = NoInherit;
0878     }
0879 
0880     return ch;
0881 }
0882 
0883 bool NodeImpl::pseudoDiff(khtml::RenderStyle *s1, khtml::RenderStyle *s2, unsigned int pid)
0884 {
0885     khtml::RenderStyle *ps1 = s1 ? s1->getPseudoStyle((khtml::RenderStyle::PseudoId)pid) : nullptr;
0886     khtml::RenderStyle *ps2 = s2 ? s2->getPseudoStyle((khtml::RenderStyle::PseudoId)pid) : nullptr;
0887 
0888     if (ps1 == ps2) {
0889         return false;
0890     } else if (ps1 && ps2) {
0891         if (*ps1 == *ps2) {
0892             return false;
0893         } else {
0894             return true;
0895         }
0896     } else {
0897         return true;
0898     }
0899 }
0900 
0901 bool NodeImpl::affectedByNoInherit() const
0902 {
0903     if (m_render && m_render->style()) {
0904         return m_render->style()->inheritedNoninherited();
0905     } else {
0906         return false;
0907     }
0908 }
0909 
0910 void NodeImpl::close()
0911 {
0912     if (m_render) {
0913         m_render->close();
0914     }
0915     m_closed = true;
0916 }
0917 
0918 void NodeImpl::attach()
0919 {
0920     assert(!attached());
0921     assert(!m_render || (m_render->style() && m_render->parent()));
0922     if (m_render) { // set states to match node
0923         if (closed()) {
0924             m_render->close();
0925         }
0926         if (hovered()) {
0927             m_render->setMouseInside();
0928         }
0929     }
0930     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
0931     m_attached = true;
0932 }
0933 
0934 void NodeImpl::detach()
0935 {
0936 //    assert(m_attached);
0937 
0938     if (m_render) {
0939         m_render->detach();
0940     }
0941 
0942     m_render = nullptr;
0943     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
0944     m_attached = false;
0945 }
0946 
0947 bool NodeImpl::maintainsState()
0948 {
0949     return false;
0950 }
0951 
0952 QString NodeImpl::state()
0953 {
0954     return QString();
0955 }
0956 
0957 void NodeImpl::restoreState(const QString &/*state*/)
0958 {
0959 }
0960 
0961 void NodeImpl::insertedIntoDocument()
0962 {
0963     setInDocument(true);
0964 }
0965 
0966 void NodeImpl::removedFromDocument()
0967 {
0968     setInDocument(false);
0969 }
0970 
0971 void NodeImpl::childrenChanged()
0972 {
0973     if (parentNode()) {
0974         parentNode()->childrenChanged();
0975     }
0976 }
0977 
0978 bool NodeImpl::isReadOnly()
0979 {
0980     // Entity & Entity Reference nodes and their descendants are read-only
0981     NodeImpl *n = this;
0982     while (n) {
0983         if (n->nodeType() == Node::ENTITY_NODE ||
0984                 n->nodeType() == Node::ENTITY_REFERENCE_NODE) {
0985             return true;
0986         }
0987         n = n->parentNode();
0988     }
0989     return false;
0990 }
0991 
0992 NodeImpl *NodeImpl::previousEditable() const
0993 {
0994     NodeImpl *node = previousLeafNode();
0995     while (node) {
0996         if (node->document()->part()->isCaretMode() || node->isContentEditable()) {
0997             return node;
0998         }
0999         node = node->previousLeafNode();
1000     }
1001     return nullptr;
1002 }
1003 
1004 NodeImpl *NodeImpl::nextEditable() const
1005 {
1006     NodeImpl *node = nextLeafNode();
1007     while (node) {
1008         if (node->document()->part()->isCaretMode() || node->isContentEditable()) {
1009             return node;
1010         }
1011         node = node->nextLeafNode();
1012     }
1013     return nullptr;
1014 }
1015 
1016 RenderObject *NodeImpl::previousRenderer()
1017 {
1018     for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1019         if (n->renderer()) {
1020             return n->renderer();
1021         }
1022     }
1023     return nullptr;
1024 }
1025 
1026 RenderObject *NodeImpl::nextRenderer()
1027 {
1028     for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1029         if (n->renderer()) {
1030             return n->renderer();
1031         }
1032     }
1033     return nullptr;
1034 }
1035 
1036 void NodeImpl::createRendererIfNeeded()
1037 {
1038 #ifdef APPLE_CHANGES
1039     if (!document()->shouldCreateRenderers()) {
1040         return;
1041     }
1042 #endif
1043 
1044     assert(!m_render);
1045 
1046     NodeImpl *parent = parentNode();
1047     assert(parent);
1048 
1049     RenderObject *parentRenderer = parent->renderer();
1050     if (parentRenderer && parentRenderer->childAllowed()) {
1051         RenderStyle *style = styleForRenderer(parentRenderer);
1052         style->ref();
1053         if (rendererIsNeeded(style)) {
1054             m_render = createRenderer(document()->renderArena(), style);
1055             m_render->setStyle(style);
1056             parentRenderer->addChild(m_render, nextRenderer());
1057         }
1058         style->deref();
1059     }
1060 }
1061 
1062 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1063 {
1064     return parent->style();
1065 }
1066 
1067 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1068 {
1069     return (document()->documentElement() == this) || (style->display() != NONE);
1070 }
1071 
1072 RenderObject *NodeImpl::createRenderer(RenderArena * /*arena*/, RenderStyle * /*style*/)
1073 {
1074     assert(false);
1075     return nullptr;
1076 }
1077 
1078 RenderStyle *NodeImpl::computedStyle()
1079 {
1080     return parentNode() ? parentNode()->computedStyle() : nullptr;
1081 }
1082 
1083 NodeImpl *NodeImpl::previousLeafNode() const
1084 {
1085     NodeImpl *node = traversePreviousNode();
1086     while (node) {
1087         if (!node->hasChildNodes()) {
1088             return node;
1089         }
1090         node = node->traversePreviousNode();
1091     }
1092     return nullptr;
1093 }
1094 
1095 NodeImpl *NodeImpl::nextLeafNode() const
1096 {
1097     NodeImpl *node = traverseNextNode();
1098     while (node) {
1099         if (!node->hasChildNodes()) {
1100             return node;
1101         }
1102         node = node->traverseNextNode();
1103     }
1104     return nullptr;
1105 }
1106 
1107 long NodeImpl::maxOffset() const
1108 {
1109     return 1;
1110 }
1111 
1112 long NodeImpl::caretMinOffset() const
1113 {
1114     return renderer() ? renderer()->caretMinOffset() : 0;
1115 }
1116 
1117 long NodeImpl::caretMaxOffset() const
1118 {
1119     return renderer() ? renderer()->caretMaxOffset() : 1;
1120 }
1121 
1122 unsigned long NodeImpl::caretMaxRenderedOffset() const
1123 {
1124     return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1125 }
1126 
1127 bool NodeImpl::isBlockFlow() const
1128 {
1129     return renderer() && renderer()->isBlockFlow();
1130 }
1131 
1132 bool NodeImpl::isEditableBlock() const
1133 {
1134     return isBlockFlow() && isContentEditable();
1135 }
1136 
1137 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1138 {
1139     NodeImpl *n = const_cast<NodeImpl *>(this);
1140     if (isBlockFlow()) {
1141         return static_cast<ElementImpl *>(n);
1142     }
1143 
1144     while (1) {
1145         n = n->parentNode();
1146         if (!n) {
1147             break;
1148         }
1149         if (n->isBlockFlow() || n->id() == ID_BODY) {
1150             return static_cast<ElementImpl *>(n);
1151         }
1152     }
1153     return nullptr;
1154 }
1155 
1156 ElementImpl *NodeImpl::rootEditableElement() const
1157 {
1158     if (!isContentEditable()) {
1159         return nullptr;
1160     }
1161 
1162     NodeImpl *n = const_cast<NodeImpl *>(this);
1163     NodeImpl *result = n->isEditableBlock() ? n : nullptr;
1164     while (1) {
1165         n = n->parentNode();
1166         if (!n || !n->isContentEditable()) {
1167             break;
1168         }
1169         if (n->id() == ID_BODY) {
1170             result = n;
1171             break;
1172         }
1173         if (n->isBlockFlow()) {
1174             result = n;
1175         }
1176     }
1177     return static_cast<ElementImpl *>(result);
1178 }
1179 
1180 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1181 {
1182     return n ? rootEditableElement() == n->rootEditableElement() : false;
1183 }
1184 
1185 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1186 {
1187     return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1188 }
1189 
1190 RenderPosition NodeImpl::positionForCoordinates(int x, int y) const
1191 {
1192     if (renderer()) {
1193         return renderer()->positionForCoordinates(x, y);
1194     }
1195 
1196     return RenderPosition();
1197 }
1198 
1199 bool NodeImpl::isPointInsideSelection(int x, int y, const Selection &sel) const
1200 {
1201     if (sel.state() != Selection::RANGE) {
1202         return false;
1203     }
1204 
1205     RenderPosition pos(positionForCoordinates(x, y));
1206     if (pos.isEmpty()) {
1207         return false;
1208     }
1209 
1210     NodeImpl *n = sel.start().node();
1211     while (n) {
1212         if (n == pos.node()) {
1213             if ((n == sel.start().node() && pos.domOffset() < sel.start().offset()) ||
1214                     (n == sel.end().node() && pos.domOffset() > sel.end().offset())) {
1215                 return false;
1216             }
1217             return true;
1218         }
1219         if (n == sel.end().node()) {
1220             break;
1221         }
1222         n = n->traverseNextNode();
1223     }
1224 
1225     return false;
1226 
1227 }
1228 
1229 NodeListImpl *NodeImpl::getElementsByTagName(const DOMString &tagName)
1230 {
1231     LocalName localname;
1232     PrefixName prefixname;
1233     if (tagName == "*") {
1234         localname = LocalName::fromId(anyLocalName);
1235         prefixname = PrefixName::fromId(emptyPrefix);
1236     } else {
1237         splitPrefixLocalName(tagName, prefixname, localname, m_htmlCompat);
1238     }
1239     return new TagNodeListImpl(this, NamespaceName::fromId(0), localname, prefixname);
1240 }
1241 
1242 NodeListImpl *NodeImpl::getElementsByTagNameNS(const DOMString &namespaceURI, const DOMString &localName)
1243 {
1244     return new TagNodeListImpl(this, namespaceURI, localName);
1245 }
1246 
1247 NodeListImpl *NodeImpl::getElementsByClassName(const DOMString &name)
1248 {
1249     return new ClassNodeListImpl(this, name);
1250 }
1251 
1252 bool NodeImpl::hasAttributes() const
1253 {
1254     return false;
1255 }
1256 
1257 bool NodeImpl::isSupported(const DOMString &feature, const DOMString &version)
1258 {
1259     return DOMImplementationImpl::hasFeature(feature, version);
1260 }
1261 
1262 DocumentImpl *NodeImpl::ownerDocument() const
1263 {
1264     // braindead DOM spec says that ownerDocument
1265     // should return null if called on the document node
1266     // we thus have our nicer document, and hack it here
1267     // for DOMy clients in one central place
1268     DocumentImpl *doc = document();
1269     if (doc == this) {
1270         return nullptr;
1271     } else {
1272         return doc;
1273     }
1274 }
1275 
1276 // Helper for compareDocumentPosition --- this extends the notion of a parent node
1277 // beyond structural to also include elements containing attributes, etc.
1278 static const NodeImpl *logicalParentNode(const DOM::NodeImpl *node)
1279 {
1280     NodeImpl *parent = node->parentNode();
1281     if (parent) {
1282         return parent;
1283     }
1284 
1285     switch (node->nodeType()) {
1286     case Node::ATTRIBUTE_NODE:
1287         return static_cast<const AttrImpl *>(node)->ownerElement();
1288 
1289     case Node::ENTITY_NODE:
1290     case Node::NOTATION_NODE:
1291         return node->ownerDocument()->doctype();
1292 
1293     default:
1294         return nullptr;
1295     }
1296 }
1297 
1298 unsigned NodeImpl::compareDocumentPosition(const DOM::NodeImpl *other)
1299 {
1300     if (other == this) {
1301         return 0;
1302     }
1303 
1304     // First, collect paths of the parents of this and other to the root of their subtrees.
1305     // Root goes first, hence the use of QList, with its fast prepends
1306     QList<const NodeImpl *> thisPath;
1307     for (const NodeImpl *cur = this; cur; cur = logicalParentNode(cur)) {
1308         thisPath.prepend(cur);
1309     }
1310 
1311     QList<const NodeImpl *> otherPath;
1312     for (const NodeImpl *cur = other; cur; cur = logicalParentNode(cur)) {
1313         otherPath.prepend(cur);
1314     }
1315 
1316     // if the roots aren't the same, we're disconnected. We're also supposed to
1317     // return IMPLEMENTATION_SPECIFIC here, and, reading tea leaves, make some
1318     // sort of a stable decision to get a total order.
1319     if (thisPath[0] != otherPath[0]) {
1320         return Node::DOCUMENT_POSITION_DISCONNECTED | Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
1321                (this > other ? Node::DOCUMENT_POSITION_PRECEDING : Node::DOCUMENT_POSITION_FOLLOWING);
1322     }
1323 
1324     // Now find our common container.
1325     const NodeImpl *common = nullptr;
1326     int   diffPos = -1;
1327     for (int pos = 0; pos < thisPath.size() && pos < otherPath.size(); ++pos) {
1328         if (thisPath[pos] == otherPath[pos]) {
1329             common = thisPath[pos];
1330         } else {
1331             diffPos = pos;
1332             break;
1333         }
1334     }
1335 
1336     // Do we have direct containment?
1337     if (common == this) {
1338         return Node::DOCUMENT_POSITION_CONTAINED_BY | Node::DOCUMENT_POSITION_FOLLOWING;
1339     } else if (common == other) {
1340         return Node::DOCUMENT_POSITION_CONTAINS | Node::DOCUMENT_POSITION_PRECEDING;
1341     }
1342 
1343     // OK, so now we are not nested, so there are ancestors of both nodes
1344     // below common that are different. Since some of those may be logically and not
1345     // physically contained in common, we have to treat the logical containment case specially.
1346     const NodeImpl *thisAnc  = thisPath [diffPos];
1347     const NodeImpl *otherAnc = otherPath[diffPos];
1348 
1349     bool thisAncLogical  = thisAnc->parentNode() == nullptr;
1350     bool otherAncLogical = otherAnc->parentNode() == nullptr;
1351     //qCDebug(KHTML_LOG) << thisAncLogical << otherAncLogical;
1352 
1353     if (thisAncLogical && otherAncLogical) {
1354         // First, try to order by nodeType.
1355         if (thisAnc->nodeType() != otherAnc->nodeType())
1356             return (thisAnc->nodeType() < otherAnc->nodeType()) ?
1357                    Node::DOCUMENT_POSITION_FOLLOWING : Node::DOCUMENT_POSITION_PRECEDING;
1358 
1359         // If both are argument nodes, they have to be in the same element,
1360         // as otherwise the first difference would be in two different elements
1361         // or above, which would not have logical parents unless they were
1362         // disconnected, which would have been handled above.
1363         // In this case, order them by their position in the
1364         // attribute list. This is helpful for XPath.
1365 
1366         if (thisAnc->nodeType() == Node::ATTRIBUTE_NODE) {
1367             const AttrImpl *thisAncAttr  = static_cast<const AttrImpl *>(thisAnc);
1368             const AttrImpl *otherAncAttr = static_cast<const AttrImpl *>(otherAnc);
1369 
1370             NamedAttrMapImpl *attrs = thisAncAttr->ownerElement()->attributes();
1371 
1372             unsigned l = attrs->length();
1373             for (unsigned i = 0; i < l; ++i) {
1374                 if (attrs->attrAt(i) == thisAncAttr) {
1375                     return Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node::DOCUMENT_POSITION_FOLLOWING;
1376                 }
1377                 if (attrs->attrAt(i) == otherAncAttr) {
1378                     return Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node::DOCUMENT_POSITION_PRECEDING;
1379                 }
1380             }
1381             assert(false);
1382         }
1383 
1384         // If not, another implementation-specific order.
1385         return Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
1386                (this > other ? Node::DOCUMENT_POSITION_PRECEDING : Node::DOCUMENT_POSITION_FOLLOWING);
1387     }
1388 
1389     if (thisAncLogical) {
1390         return Node::DOCUMENT_POSITION_FOLLOWING;
1391     }
1392 
1393     if (otherAncLogical) {
1394         return Node::DOCUMENT_POSITION_PRECEDING;
1395     }
1396 
1397     // Uff. And now the normal case -- just order thisAnc and otherAnc based on their tree order
1398     // see if otherAnc follows thisAnc)
1399     for (const NodeImpl *cur = thisAnc; cur; cur = cur->nextSibling()) {
1400         if (cur == otherAnc) {
1401             return Node::DOCUMENT_POSITION_FOLLOWING;
1402         }
1403     }
1404 
1405     return Node::DOCUMENT_POSITION_PRECEDING;
1406 }
1407 
1408 static NodeImpl *rootForSelectorQuery(DOM::NodeImpl *arg)
1409 {
1410     if (arg->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1411         return static_cast<DOM::DocumentImpl *>(arg)->documentElement();
1412     } else {
1413         return arg;
1414     }
1415 }
1416 
1417 WTF::PassRefPtr<DOM::ElementImpl>  NodeImpl::querySelector(const DOM::DOMString &query, int &ec)
1418 {
1419     return khtml::SelectorQuery::querySelector(rootForSelectorQuery(this),
1420             query, ec);
1421 }
1422 
1423 WTF::PassRefPtr<DOM::NodeListImpl> NodeImpl::querySelectorAll(const DOM::DOMString &query, int &ec)
1424 {
1425     return khtml::SelectorQuery::querySelectorAll(rootForSelectorQuery(this),
1426             query, ec);
1427 }
1428 
1429 void NodeImpl::setDocument(DocumentImpl *doc)
1430 {
1431     if (m_document == doc) {
1432         return;
1433     }
1434 
1435 #if 1 // implemented for one special case only so far
1436     assert(m_document == nullptr && doc != nullptr &&
1437            nodeType() == Node::DOCUMENT_TYPE_NODE);
1438     m_document = doc;
1439 #else // for general use do something like this
1440     m_document = 0;
1441     if (inDocument()) {
1442         removedFromDocument();
1443     }
1444 
1445     ScriptInterpreter::updateDOMNodeDocument(this, m_document, doc);
1446 
1447     m_document = doc;
1448     insertedIntoDocument();
1449 #endif
1450 }
1451 
1452 DOM::DOMString DOM::NodeImpl::lookupNamespaceURI(const DOM::DOMString &prefix)
1453 {
1454     //for details see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespaceURIAlgo
1455 
1456     // check if this is one of the hard defined prefixes
1457     PrefixName ppn = PrefixName::fromString(prefix);
1458     if (ppn.id() == xmlPrefix) {
1459         return DOM::DOMString(XML_NAMESPACE);
1460     }
1461     if (ppn.id() == xmlnsPrefix) {
1462         return DOM::DOMString(XMLNS_NAMESPACE);
1463     }
1464 
1465     switch (this->nodeType()) {
1466     case Node::ELEMENT_NODE:
1467         if (!this->namespaceURI().isNull() && this->prefix() == prefix) {
1468             return this->namespaceURI();
1469         }
1470         if (this->hasAttributes()) {
1471             ElementImpl *node = static_cast<ElementImpl *>(this);
1472 
1473             NamedAttrMapImpl *attributes = node->attributes(true /*readonly*/);
1474             if (ppn.id() != emptyPrefix) {
1475                 LocalName pln = LocalName::fromString(prefix);
1476                 PrefixName xmlns = PrefixName::fromId(xmlnsNamespace);
1477 
1478                 DOM::DOMString result = attributes->getValue(pln.id(), xmlns);
1479                 if (!result.isNull()) {
1480                     return result;
1481                 }
1482             } else {
1483                 DOM::DOMString result = attributes->getValue(ATTR_XMLNS);
1484                 if (!result.isEmpty()) {
1485                     return result;
1486                 }
1487             }
1488         }
1489         {
1490             NodeImpl *ancestor = findNextElementAncestor(this);
1491             if (ancestor) {
1492                 return ancestor->lookupNamespaceURI(prefix);
1493             }
1494         }
1495         return DOM::DOMString();
1496 
1497     case Node::DOCUMENT_NODE: {
1498         DocumentImpl *node = static_cast<DocumentImpl *>(this);
1499         return node->documentElement()->lookupNamespaceURI(prefix);
1500     }
1501 
1502     case Node::ATTRIBUTE_NODE: {
1503         NodeImpl *ancestor = this->parentNode();
1504         if (ancestor) {
1505             return ancestor->lookupNamespaceURI(prefix);
1506         } else {
1507             return DOM::DOMString();
1508         }
1509     }
1510 
1511     case Node::ENTITY_NODE:
1512     case Node::NOTATION_NODE:
1513     case Node::DOCUMENT_TYPE_NODE:
1514     case Node::DOCUMENT_FRAGMENT_NODE:
1515         return DOM::DOMString();
1516 
1517     default: {
1518         NodeImpl *ancestor = findNextElementAncestor(this);
1519         if (ancestor) {
1520             return ancestor->lookupNamespaceURI(prefix);
1521         }
1522         return DOM::DOMString();
1523     }
1524     }
1525 }
1526 
1527 DOM::NodeImpl *DOM::NodeImpl::findNextElementAncestor(NodeImpl *node)
1528 {
1529     NodeImpl *iterator = node->parentNode();
1530     while (iterator) {
1531         if (iterator->nodeType() == Node::ELEMENT_NODE) {
1532             return iterator;
1533         }
1534         iterator = iterator->parentNode();
1535     }
1536     return nullptr;
1537 }
1538 
1539 //-------------------------------------------------------------------------
1540 
1541 NodeBaseImpl::~NodeBaseImpl()
1542 {
1543     //qCDebug(KHTML_LOG) << "NodeBaseImpl destructor";
1544     // we have to tell all children, that the parent has died...
1545     NodeImpl *n;
1546     NodeImpl *next;
1547 
1548     for (n = _first; n != nullptr; n = next) {
1549         next = n->nextSibling();
1550         n->setPreviousSibling(nullptr);
1551         n->setNextSibling(nullptr);
1552         n->setParent(nullptr);
1553         if (!n->refCount()) {
1554             delete n;
1555         }
1556     }
1557 }
1558 
1559 NodeImpl *NodeBaseImpl::firstChild() const
1560 {
1561     return _first;
1562 }
1563 
1564 NodeImpl *NodeBaseImpl::lastChild() const
1565 {
1566     return _last;
1567 }
1568 
1569 NodeImpl *NodeBaseImpl::insertBefore(NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode)
1570 {
1571     exceptioncode = 0;
1572 
1573     // insertBefore(...,null) is equivalent to appendChild()
1574     if (!refChild) {
1575         return appendChild(newChild, exceptioncode);
1576     }
1577 
1578     // Make sure adding the new child is ok
1579     checkAddChild(newChild, exceptioncode);
1580     if (exceptioncode) {
1581         return nullptr;
1582     }
1583 
1584     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1585     if (refChild->parentNode() != this) {
1586         exceptioncode = DOMException::NOT_FOUND_ERR;
1587         return nullptr;
1588     }
1589 
1590     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1591 
1592     // If newChild is a DocumentFragment with no children.... there's nothing to do.
1593     // Just return the document fragment
1594     if (isFragment && !newChild->firstChild()) {
1595         return newChild;
1596     }
1597 
1598     // Now actually add the child(ren)
1599     NodeImpl *nextChild;
1600     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1601 
1602     NodeImpl *prev = refChild->previousSibling();
1603     if (prev == newChild || refChild == newChild) { // nothing to do
1604         return newChild;
1605     }
1606 
1607     while (child) {
1608         nextChild = isFragment ? child->nextSibling() : nullptr;
1609 
1610         // If child is already present in the tree, first remove it
1611         NodeImpl *newParent = child->parentNode();
1612 
1613         //...guard it in case we need to move it..
1614         SharedPtr<NodeImpl> guard(child);
1615 
1616         if (newParent) {
1617             newParent->removeChild(child, exceptioncode);
1618         }
1619         if (exceptioncode) {
1620             return nullptr;
1621         }
1622 
1623         // Add child in the correct position
1624         if (prev) {
1625             prev->setNextSibling(child);
1626         } else {
1627             _first = child;
1628         }
1629         refChild->setPreviousSibling(child);
1630         child->setParent(this);
1631         child->setPreviousSibling(prev);
1632         child->setNextSibling(refChild);
1633 
1634         // Add child to the rendering tree
1635         // ### should we detach() it first if it's already attached?
1636         if (attached() && !child->attached()) {
1637             child->attach();
1638         }
1639 
1640         // Dispatch the mutation events
1641         dispatchChildInsertedEvents(child, exceptioncode);
1642 
1643         prev = child;
1644         child = nextChild;
1645     }
1646 
1647     if (!newChild->closed()) {
1648         newChild->close();
1649     }
1650 
1651     structureChanged();
1652 
1653     // ### set style in case it's attached
1654     dispatchSubtreeModifiedEvent();
1655     return newChild;
1656 }
1657 
1658 void NodeBaseImpl::replaceChild(NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode)
1659 {
1660     exceptioncode = 0;
1661 
1662     if (oldChild == newChild) { // nothing to do
1663         return;
1664     }
1665 
1666     // Make sure adding the new child is ok
1667     checkAddChild(newChild, exceptioncode);
1668     if (exceptioncode) {
1669         return;
1670     }
1671 
1672     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1673     if (!oldChild || oldChild->parentNode() != this) {
1674         exceptioncode = DOMException::NOT_FOUND_ERR;
1675         return;
1676     }
1677 
1678     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1679     NodeImpl *nextChild;
1680     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1681 
1682     // Remove the old child
1683     NodeImpl *prev = oldChild->previousSibling();
1684     NodeImpl *next = oldChild->nextSibling();
1685 
1686     removeChild(oldChild, exceptioncode);
1687     if (exceptioncode) {
1688         return;
1689     }
1690 
1691     // Add the new child(ren)
1692     while (child) {
1693         nextChild = isFragment ? child->nextSibling() : nullptr;
1694 
1695         // If child is already present in the tree, first remove it
1696         NodeImpl *newParent = child->parentNode();
1697         if (child == next) {
1698             next = child->nextSibling();
1699         }
1700         if (child == prev) {
1701             prev = child->previousSibling();
1702         }
1703         //...guard it in case we need to move it..
1704         SharedPtr<NodeImpl> guard(child);
1705         if (newParent) {
1706             newParent->removeChild(child, exceptioncode);
1707         }
1708         if (exceptioncode) {
1709             return;
1710         }
1711 
1712         // Add child in the correct position
1713         if (prev) {
1714             prev->setNextSibling(child);
1715         }
1716         if (next) {
1717             next->setPreviousSibling(child);
1718         }
1719         if (!prev) {
1720             _first = child;
1721         }
1722         if (!next) {
1723             _last = child;
1724         }
1725         child->setParent(this);
1726         child->setPreviousSibling(prev);
1727         child->setNextSibling(next);
1728 
1729         // Add child to the rendering tree
1730         // ### should we detach() it first if it's already attached?
1731         if (attached() && !child->attached()) {
1732             child->attach();
1733         }
1734 
1735         // Dispatch the mutation events
1736         dispatchChildInsertedEvents(child, exceptioncode);
1737 
1738         prev = child;
1739         child = nextChild;
1740     }
1741 
1742     if (!newChild->closed()) {
1743         newChild->close();
1744     }
1745 
1746     structureChanged();
1747 
1748     // ### set style in case it's attached
1749     dispatchSubtreeModifiedEvent();
1750     return;
1751 }
1752 
1753 void NodeBaseImpl::removeChild(NodeImpl *oldChild, int &exceptioncode)
1754 {
1755     exceptioncode = 0;
1756 
1757     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1758     if (isReadOnly()) {
1759         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1760         return;
1761     }
1762 
1763     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1764     if (!oldChild || oldChild->parentNode() != this) {
1765         exceptioncode = DOMException::NOT_FOUND_ERR;
1766         return;
1767     }
1768 
1769     dispatchChildRemovalEvents(oldChild, exceptioncode);
1770     if (exceptioncode) {
1771         return;
1772     }
1773 
1774     SharedPtr<NodeImpl> memManage(oldChild); //Make sure to free if needed
1775 
1776     // Remove from rendering tree
1777     if (oldChild->attached()) {
1778         oldChild->detach();
1779     }
1780 
1781     // Remove the child
1782     NodeImpl *prev, *next;
1783     prev = oldChild->previousSibling();
1784     next = oldChild->nextSibling();
1785 
1786     if (next) {
1787         next->setPreviousSibling(prev);
1788     }
1789     if (prev) {
1790         prev->setNextSibling(next);
1791     }
1792     if (_first == oldChild) {
1793         _first = next;
1794     }
1795     if (_last == oldChild) {
1796         _last = prev;
1797     }
1798 
1799     oldChild->setPreviousSibling(nullptr);
1800     oldChild->setNextSibling(nullptr);
1801     oldChild->setParent(nullptr);
1802 
1803     structureChanged();
1804 
1805     // Dispatch post-removal mutation events
1806     dispatchSubtreeModifiedEvent();
1807 
1808     NodeImpl *p = this;
1809     while (p->parentNode()) {
1810         p = p->parentNode();
1811     }
1812     if (p->nodeType() == Node::DOCUMENT_NODE) {
1813         for (NodeImpl *c = oldChild; c; c = c->traverseNextNode(oldChild)) {
1814             c->removedFromDocument();
1815         }
1816     }
1817 }
1818 
1819 void NodeBaseImpl::removeChildren()
1820 {
1821     bool inDoc = inDocument();
1822     NodeImpl *n, *next;
1823     for (n = _first, _first = nullptr; n; n = next) {
1824         next = n->nextSibling();
1825         if (n->attached()) {
1826             n->detach();
1827         }
1828         n->setPreviousSibling(nullptr);
1829         n->setNextSibling(nullptr);
1830         n->setParent(nullptr);
1831 
1832         if (inDoc)
1833             for (NodeImpl *c = n; c; c = c->traverseNextNode(n)) {
1834                 c->removedFromDocument();
1835             }
1836 
1837         if (!n->refCount()) {
1838             delete n;
1839         }
1840     }
1841     _last = nullptr;
1842 }
1843 
1844 NodeImpl *NodeBaseImpl::appendChild(NodeImpl *newChild, int &exceptioncode)
1845 {
1846     exceptioncode = 0;
1847 
1848     // Make sure adding the new child is ok
1849     checkAddChild(newChild, exceptioncode);
1850     if (exceptioncode) {
1851         return nullptr;
1852     }
1853 
1854     if (newChild == _last) { // nothing to do
1855         return newChild;
1856     }
1857 
1858     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1859 
1860     // If newChild is a DocumentFragment with no children.... there's nothing to do.
1861     // Just return the document fragment
1862     if (isFragment && !newChild->firstChild()) {
1863         return newChild;
1864     }
1865 
1866     // Now actually add the child(ren)
1867     NodeImpl *nextChild;
1868     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1869 
1870     while (child) {
1871         nextChild = isFragment ? child->nextSibling() : nullptr;
1872 
1873         // If child is already present in the tree, first remove it
1874         NodeImpl *oldParent = child->parentNode();
1875         SharedPtr<NodeImpl> guard(child); //Guard in case we move it
1876         if (oldParent) {
1877             oldParent->removeChild(child, exceptioncode);
1878             if (exceptioncode) {
1879                 return nullptr;
1880             }
1881         }
1882 
1883         // Append child to the end of the list
1884         child->setParent(this);
1885 
1886         if (_last) {
1887             child->setPreviousSibling(_last);
1888             _last->setNextSibling(child);
1889             _last = child;
1890         } else {
1891             _first = _last = child;
1892         }
1893 
1894         // Add child to the rendering tree
1895         // ### should we detach() it first if it's already attached?
1896         if (attached() && !child->attached()) {
1897             child->attach();
1898         }
1899 
1900         // Dispatch the mutation events
1901         dispatchChildInsertedEvents(child, exceptioncode);
1902 
1903         child = nextChild;
1904     }
1905 
1906     if (!newChild->closed()) {
1907         newChild->close();
1908     }
1909 
1910     backwardsStructureChanged();
1911 
1912     // ### set style in case it's attached
1913     dispatchSubtreeModifiedEvent();
1914     return newChild;
1915 }
1916 
1917 bool NodeBaseImpl::hasChildNodes() const
1918 {
1919     return _first != nullptr;
1920 }
1921 
1922 // not part of the DOM
1923 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1924 {
1925     _first = child;
1926 }
1927 
1928 void NodeBaseImpl::setLastChild(NodeImpl *child)
1929 {
1930     _last = child;
1931 }
1932 
1933 // check for same source document:
1934 bool NodeBaseImpl::checkSameDocument(NodeImpl *newChild, int &exceptioncode)
1935 {
1936     exceptioncode = 0;
1937     DocumentImpl *ownerDocThis = document();
1938     DocumentImpl *ownerDocNew = newChild->document();
1939     if (ownerDocThis != ownerDocNew) {
1940         // qCDebug(KHTML_LOG)<< "not same document, newChild = " << newChild << "document = " << document();
1941         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1942         return true;
1943     }
1944     return false;
1945 }
1946 
1947 // check for being child:
1948 bool NodeBaseImpl::checkIsChild(NodeImpl *oldChild, int &exceptioncode)
1949 {
1950     if (!oldChild || oldChild->parentNode() != this) {
1951         exceptioncode = DOMException::NOT_FOUND_ERR;
1952         return true;
1953     }
1954     return false;
1955 }
1956 
1957 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1958 {
1959     // do not add applyChanges here! This function is only used during parsing
1960 
1961     // short check for consistency with DTD
1962     if (document()->isHTMLDocument() && !childAllowed(newChild)) {
1963         //qCDebug(KHTML_LOG) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id();
1964         return nullptr;
1965     }
1966 
1967     // just add it...
1968     newChild->setParent(this);
1969 
1970     if (_last) {
1971         newChild->setPreviousSibling(_last);
1972         _last->setNextSibling(newChild);
1973         _last = newChild;
1974     } else {
1975         _first = _last = newChild;
1976     }
1977 
1978     if (inDocument()) {
1979         newChild->insertedIntoDocument();
1980     }
1981     childrenChanged();
1982 
1983     if (newChild->nodeType() == Node::ELEMENT_NODE) {
1984         return newChild;
1985     }
1986     return this;
1987 }
1988 
1989 void NodeBaseImpl::attach()
1990 {
1991     NodeImpl *child = _first;
1992     while (child != nullptr) {
1993         child->attach();
1994         child = child->nextSibling();
1995     }
1996     NodeImpl::attach();
1997 }
1998 
1999 void NodeBaseImpl::detach()
2000 {
2001     NodeImpl *child = _first;
2002     while (child != nullptr) {
2003         NodeImpl *prev = child;
2004         child = child->nextSibling();
2005         prev->detach();
2006     }
2007     NodeImpl::detach();
2008 }
2009 
2010 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
2011 {
2012     int exceptioncode = 0;
2013     NodeImpl *n;
2014     for (n = firstChild(); n && !exceptioncode; n = n->nextSibling()) {
2015         clone->appendChild(n->cloneNode(true).get(), exceptioncode);
2016     }
2017 }
2018 
2019 // I don't like this way of implementing the method, but I didn't find any
2020 // other way. Lars
2021 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
2022 {
2023     if (!m_render) {
2024         return false;
2025     }
2026     RenderObject *o = m_render;
2027     xPos = yPos = 0;
2028     if (!o->isInline() || o->isReplaced()) {
2029         o->absolutePosition(xPos, yPos);
2030         return true;
2031     }
2032 
2033     // find the next text/image child, to get a position
2034     while (o) {
2035         if (o->firstChild()) {
2036             o = o->firstChild();
2037         } else if (o->nextSibling()) {
2038             o = o->nextSibling();
2039         } else {
2040             RenderObject *next = nullptr;
2041             while (!next) {
2042                 o = o->parent();
2043                 if (!o) {
2044                     return false;
2045                 }
2046                 next = o->nextSibling();
2047             }
2048             o = next;
2049         }
2050         if ((o->isText() && !o->isBR()) || o->isReplaced()) {
2051             o->container()->absolutePosition(xPos, yPos);
2052             if (o->isText()) {
2053                 xPos += o->inlineXPos();
2054                 yPos += o->inlineYPos();
2055             } else {
2056                 xPos += o->xPos();
2057                 yPos += o->yPos();
2058             }
2059             return true;
2060         }
2061     }
2062     return true;
2063 }
2064 
2065 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2066 {
2067     if (!m_render) {
2068         return false;
2069     }
2070 
2071     RenderObject *o = m_render;
2072     xPos = yPos = 0;
2073     if (!o->isInline() || o->isReplaced()) {
2074         o->absolutePosition(xPos, yPos);
2075         xPos += o->width();
2076         yPos += o->height() + o->borderTopExtra() + o->borderBottomExtra();
2077         return true;
2078     }
2079     // find the last text/image child, to get a position
2080     while (o) {
2081         if (o->lastChild()) {
2082             o = o->lastChild();
2083         } else if (o->previousSibling()) {
2084             o = o->previousSibling();
2085         } else {
2086             RenderObject *prev = nullptr;
2087             while (!prev) {
2088                 o = o->parent();
2089                 if (!o) {
2090                     return false;
2091                 }
2092                 prev = o->previousSibling();
2093             }
2094             o = prev;
2095         }
2096         if ((o->isText() && !o->isBR()) || o->isReplaced()) {
2097             o->container()->absolutePosition(xPos, yPos);
2098             if (o->isText()) {
2099                 xPos += o->inlineXPos() + o->width();
2100                 yPos += o->inlineYPos() + o->height();
2101             } else {
2102                 xPos += o->xPos() + o->width();
2103                 yPos += o->yPos() + o->height();
2104             }
2105             return true;
2106         }
2107     }
2108     return true;
2109 }
2110 
2111 void NodeBaseImpl::setFocus(bool received)
2112 {
2113     if (m_focused == received) {
2114         return;
2115     }
2116 
2117     NodeImpl::setFocus(received);
2118 
2119     // note that we need to recalc the style
2120     setChanged(); // *:focus is a default style, so we just assume personal dependency
2121     if (isElementNode()) {
2122         document()->dynamicDomRestyler().restyleDependent(static_cast<ElementImpl *>(this), OtherStateDependency);
2123     }
2124 }
2125 
2126 void NodeBaseImpl::setActive(bool down)
2127 {
2128     if (down == active()) {
2129         return;
2130     }
2131 
2132     NodeImpl::setActive(down);
2133 
2134     // note that we need to recalc the style
2135     if (isElementNode()) {
2136         document()->dynamicDomRestyler().restyleDependent(static_cast<ElementImpl *>(this), ActiveDependency);
2137     }
2138 }
2139 
2140 void NodeBaseImpl::setHovered(bool hover)
2141 {
2142     if (hover == hovered()) {
2143         return;
2144     }
2145 
2146     NodeImpl::setHovered(hover);
2147 
2148     // note that we need to recalc the style
2149     if (isElementNode()) {
2150         document()->dynamicDomRestyler().restyleDependent(static_cast<ElementImpl *>(this), HoverDependency);
2151     }
2152 }
2153 
2154 unsigned long NodeBaseImpl::childNodeCount()
2155 {
2156     unsigned long count = 0;
2157     NodeImpl *n;
2158     for (n = firstChild(); n; n = n->nextSibling()) {
2159         count++;
2160     }
2161     return count;
2162 }
2163 
2164 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2165 {
2166     unsigned long i;
2167     NodeImpl *n = firstChild();
2168     for (i = 0; n && i < index; i++) {
2169         n = n->nextSibling();
2170     }
2171     return n;
2172 }
2173 
2174 void NodeBaseImpl::dispatchChildInsertedEvents(NodeImpl *child, int &exceptioncode)
2175 {
2176     if (document()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2177         // We need to weak-guard ourselves since 'this' may be a fresh node, so
2178         // we don't want the mutation event to delete it.
2179         ref();
2180         MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT, true, false, this, DOMString(), DOMString(), DOMString(), 0);
2181         evt->ref();
2182         child->dispatchEvent(evt, exceptioncode, true);
2183         evt->deref();
2184         derefOnly();
2185         if (exceptioncode) {
2186             return;
2187         }
2188     }
2189 
2190     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
2191     bool hasInsertedListeners = document()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2192     NodeImpl *p = this;
2193     while (p->parentNode()) {
2194         p = p->parentNode();
2195     }
2196     if (p->nodeType() == Node::DOCUMENT_NODE) {
2197         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2198             c->insertedIntoDocument();
2199 
2200             if (hasInsertedListeners) {
2201                 ref();
2202                 MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT, false, false, nullptr, DOMString(), DOMString(), DOMString(), 0);
2203                 evt->ref();
2204                 c->dispatchEvent(evt, exceptioncode, true);
2205                 evt->deref();
2206                 derefOnly();
2207                 if (exceptioncode) {
2208                     return;
2209                 }
2210             }
2211         }
2212     }
2213 }
2214 
2215 void NodeBaseImpl::dispatchChildRemovalEvents(NodeImpl *child, int &exceptioncode)
2216 {
2217     // Dispatch pre-removal mutation events
2218     document()->notifyBeforeNodeRemoval(child); // ### use events instead
2219     if (document()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2220         ref();
2221         MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT, true, false, this, DOMString(), DOMString(), DOMString(), 0);
2222         evt->ref();
2223         child->dispatchEvent(evt, exceptioncode, true);
2224         evt->deref();
2225         derefOnly();
2226         if (exceptioncode) {
2227             return;
2228         }
2229     }
2230 
2231     bool hasRemovalListeners = document()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2232 
2233     // dispatch the DOMNodeRemovedFromDocument event to all descendants
2234     NodeImpl *p = this;
2235     while (p->parentNode()) {
2236         p = p->parentNode();
2237     }
2238     if (p->nodeType() == Node::DOCUMENT_NODE) {
2239         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2240             if (hasRemovalListeners) {
2241                 ref();
2242                 MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT, false, false, nullptr, DOMString(), DOMString(), DOMString(), 0);
2243                 evt->ref();
2244                 c->dispatchEvent(evt, exceptioncode, true);
2245                 evt->deref();
2246                 derefOnly();
2247                 if (exceptioncode) {
2248                     return;
2249                 }
2250             }
2251         }
2252     }
2253 }
2254 
2255 // ---------------------------------------------------------------------------
2256 
2257 NamedNodeMapImpl::NamedNodeMapImpl()
2258 {
2259 }
2260 
2261 NamedNodeMapImpl::~NamedNodeMapImpl()
2262 {
2263 }
2264 
2265 NodeImpl *NamedNodeMapImpl::getNamedItem(const DOMString &name)
2266 {
2267     PrefixName prefix;
2268     LocalName  localName;
2269     splitPrefixLocalName(name, prefix, localName, htmlCompat());
2270 
2271     return getNamedItem(localName.id(), prefix, false);
2272 }
2273 
2274 Node NamedNodeMapImpl::setNamedItem(const Node &arg, int &exceptioncode)
2275 {
2276     if (!arg.handle()) {
2277         exceptioncode = DOMException::NOT_FOUND_ERR;
2278         return nullptr;
2279     }
2280 
2281     Node r = setNamedItem(arg.handle(), emptyPrefixName, false, exceptioncode);
2282     return r;
2283 }
2284 
2285 Node NamedNodeMapImpl::removeNamedItem(const DOMString &name, int &exceptioncode)
2286 {
2287     PrefixName prefix;
2288     LocalName  localName;
2289     splitPrefixLocalName(name, prefix, localName, htmlCompat());
2290 
2291     Node r = removeNamedItem(localName.id(), prefix, false, exceptioncode);
2292     return r;
2293 }
2294 
2295 Node NamedNodeMapImpl::getNamedItemNS(const DOMString &namespaceURI, const DOMString &localName)
2296 {
2297     LocalName localname = LocalName::fromString(localName);
2298     NamespaceName namespacename = NamespaceName::fromString(namespaceURI);
2299     return getNamedItem(makeId(namespacename.id(), localname.id()), emptyPrefixName, true);
2300 }
2301 
2302 Node NamedNodeMapImpl::setNamedItemNS(const Node &arg, int &exceptioncode)
2303 {
2304     return setNamedItem(arg.handle(), emptyPrefixName, true, exceptioncode);
2305 }
2306 
2307 Node NamedNodeMapImpl::removeNamedItemNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode)
2308 {
2309     LocalName localname = LocalName::fromString(localName);
2310     NamespaceName namespacename = NamespaceName::fromString(namespaceURI);
2311     return removeNamedItem(makeId(namespacename.id(), localname.id()), emptyPrefixName, true, exceptioncode);
2312 }
2313 
2314 // ----------------------------------------------------------------------------
2315 
2316 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentImpl *doc)
2317     : NamedNodeMapImpl()
2318 {
2319     m_doc = doc;
2320     m_contents = new QList<NodeImpl *>;
2321 }
2322 
2323 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2324 {
2325     while (!m_contents->isEmpty()) {
2326         m_contents->takeLast()->deref();
2327     }
2328 
2329     delete m_contents;
2330 }
2331 
2332 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem(NodeImpl::Id id, const PrefixName & /*prefix*/, bool /*nsAware*/)
2333 {
2334     // ## do we need namespace support in this class?
2335     QListIterator<NodeImpl *> it(*m_contents);
2336     while (it.hasNext())
2337         if (it.next()->id() == id) {
2338             return it.peekPrevious();
2339         }
2340     return nullptr;
2341 }
2342 
2343 Node GenericRONamedNodeMapImpl::setNamedItem(NodeImpl * /*arg*/, const PrefixName & /*prefix*/, bool /*nsAware*/, int &exceptioncode)
2344 {
2345     // can't modify this list through standard DOM functions
2346     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2347     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2348     return nullptr;
2349 }
2350 
2351 Node GenericRONamedNodeMapImpl::removeNamedItem(NodeImpl::Id /*id*/, const PrefixName & /*prefix*/, bool /*nsAware*/, int &exceptioncode)
2352 {
2353     // can't modify this list through standard DOM functions
2354     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2355     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2356     return nullptr;
2357 }
2358 
2359 NodeImpl *GenericRONamedNodeMapImpl::item(unsigned index)
2360 {
2361     if (index >= (unsigned int) m_contents->count()) {
2362         return nullptr;
2363     }
2364 
2365     return m_contents->at(index);
2366 }
2367 
2368 unsigned GenericRONamedNodeMapImpl::length() const
2369 {
2370     return m_contents->count();
2371 }
2372 
2373 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2374 {
2375     // The spec says that in the case of duplicates we only keep the first one
2376     if (getNamedItem(n->id(), emptyPrefixName, false)) {
2377         return;
2378     }
2379 
2380     n->ref();
2381     m_contents->append(n);
2382 }
2383