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