1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2001 Dirk Mueller (mueller@kde.org)
7  *           (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
8  *           (C) 2005, 2009, 2010 Maksim Orlovich (maksim@kde.org)
9  *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 
27 #include "dom_nodeimpl.h"
28 
29 #include <dom/dom_exception.h>
30 #include "dom_elementimpl.h"
31 #include "dom_textimpl.h"
32 #include "dom2_eventsimpl.h"
33 #include "dom_docimpl.h"
34 #include "dom_nodelistimpl.h"
35 #include "xml/dom_position.h"
36 #include "xml/dom_selection.h"
37 #include "xml/wa_selectors.h"
38 #include "dom_restyler.h"
39 #include "html/html_objectimpl.h"
40 
41 #include "khtml_debug.h"
42 
43 #include <rendering/render_text.h>
44 #include <rendering/render_flow.h>
45 #include <rendering/render_line.h>
46 
47 #include <ecma/kjs_proxy.h>
48 #include <khtmlview.h>
49 #include <khtml_part.h>
50 //Added by qt3to4:
51 #include <QMouseEvent>
52 #include <QKeyEvent>
53 #include <QEvent>
54 
55 #if 0
56 // from khtml_caret_p.h
57 namespace khtml
58 {
59 void /*KHTML_NO_EXPORT*/ mapDOMPosToRenderPos(DOM::NodeImpl *node, long offset,
60         khtml::RenderObject *&r, long &r_ofs, bool &outside, bool &outsideEnd);
61 }
62 #endif
63 
64 using namespace DOM;
65 using namespace khtml;
66 
NodeImpl(DocumentImpl * doc)67 NodeImpl::NodeImpl(DocumentImpl *doc)
68     : m_document(doc),
69       m_previous(nullptr),
70       m_next(nullptr),
71       m_render(nullptr),
72       m_hasId(false),
73       m_attached(false),
74       m_closed(false),
75       m_changed(false),
76       m_hasChangedChild(false),
77       m_changedAscendentAttribute(false),
78       m_inDocument(false),
79       m_hasAnchor(false),
80       m_hovered(false),
81       m_focused(false),
82       m_active(false),
83       m_implicit(false),
84       m_htmlCompat(false),
85       m_hasClass(false),
86       m_hasCombinedStyle(false),
87       m_hasHoverDependency(false),
88       m_elementHasRareData(false),
89       m_needsStyleAttributeUpdate(false)
90 {
91 }
92 
~NodeImpl()93 NodeImpl::~NodeImpl()
94 {
95     if (m_render) {
96         detach();
97     }
98     if (m_previous) {
99         m_previous->setNextSibling(nullptr);
100     }
101     if (m_next) {
102         m_next->setPreviousSibling(nullptr);
103     }
104 }
105 
nodeValue() const106 DOMString NodeImpl::nodeValue() const
107 {
108     return DOMString();
109 }
110 
setNodeValue(const DOMString &,int &)111 void NodeImpl::setNodeValue(const DOMString &/*_nodeValue*/, int &/*exceptioncode*/)
112 {
113     // by default nodeValue is null, so setting it has no effect
114     // don't throw NO_MODIFICATION_ALLOWED_ERR from here, DOMTS-Core-Level1's hc_nodevalue03
115     // (createEntityReference().setNodeValue())) says it would be wrong.
116     // This must be done by subclasses instead.
117 }
118 
nodeName() const119 DOMString NodeImpl::nodeName() const
120 {
121     return DOMString();
122 }
123 
nodeType() const124 unsigned short NodeImpl::nodeType() const
125 {
126     return 0;
127 }
128 
childNodes()129 WTF::PassRefPtr<DOM::NodeListImpl> NodeImpl::childNodes()
130 {
131     return new ChildNodeListImpl(this);
132 }
133 
firstChild() const134 NodeImpl *NodeImpl::firstChild() const
135 {
136     return nullptr;
137 }
138 
lastChild() const139 NodeImpl *NodeImpl::lastChild() const
140 {
141     return nullptr;
142 }
143 
insertBefore(NodeImpl *,NodeImpl *,int & exceptioncode)144 NodeImpl *NodeImpl::insertBefore(NodeImpl *, NodeImpl *, int &exceptioncode)
145 {
146     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
147     return nullptr;
148 }
149 
replaceChild(NodeImpl *,NodeImpl *,int & exceptioncode)150 void NodeImpl::replaceChild(NodeImpl *, NodeImpl *, int &exceptioncode)
151 {
152     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
153 }
154 
removeChild(NodeImpl *,int & exceptioncode)155 void NodeImpl::removeChild(NodeImpl *, int &exceptioncode)
156 {
157     exceptioncode = DOMException::NOT_FOUND_ERR;
158 }
159 
appendChild(NodeImpl *,int & exceptioncode)160 NodeImpl *NodeImpl::appendChild(NodeImpl *, int &exceptioncode)
161 {
162     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
163     return nullptr;
164 }
165 
remove(int & exceptioncode)166 void NodeImpl::remove(int &exceptioncode)
167 {
168     exceptioncode = 0;
169     if (!parentNode()) {
170         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
171         return;
172     }
173 
174     parentNode()->removeChild(this, exceptioncode);
175 }
176 
hasChildNodes() const177 bool NodeImpl::hasChildNodes() const
178 {
179     return false;
180 }
181 
normalize()182 void NodeImpl::normalize()
183 {
184     // ### normalize attributes? (when we store attributes using child nodes)
185     int exceptioncode = 0;
186     NodeImpl *child = firstChild();
187 
188     // Recursively go through the subtree beneath us, normalizing all nodes. In the case
189     // where there are two adjacent text nodes, they are merged together
190     while (child) {
191         NodeImpl *nextChild = child->nextSibling();
192 
193         if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
194             // Current child and the next one are both text nodes... merge them
195             TextImpl *currentText = static_cast<TextImpl *>(child);
196             TextImpl *nextText = static_cast<TextImpl *>(nextChild);
197 
198             currentText->appendData(nextText->data(), exceptioncode);
199             if (exceptioncode) {
200                 return;
201             }
202 
203             removeChild(nextChild, exceptioncode);
204             if (exceptioncode) {
205                 return;
206             }
207         } else {
208             child->normalize();
209             child = nextChild;
210         }
211     }
212 }
213 
prefix() const214 DOMString NodeImpl::prefix() const
215 {
216     // For nodes other than elements and attributes, the prefix is always null
217     return DOMString();
218 }
219 
namespaceURI() const220 DOMString NodeImpl::namespaceURI() const
221 {
222     return DOMString();
223 }
224 
setPrefix(const DOMString &,int & exceptioncode)225 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode)
226 {
227     // The spec says that for nodes other than elements and attributes, prefix is always null.
228     // It does not say what to do when the user tries to set the prefix on another type of
229     // node, however mozilla throws a NAMESPACE_ERR exception
230     exceptioncode = DOMException::NAMESPACE_ERR;
231 }
232 
textContent() const233 DOMString NodeImpl::textContent() const
234 {
235     switch (nodeType()) {
236     case Node::TEXT_NODE:
237     case Node::CDATA_SECTION_NODE:
238     case Node::COMMENT_NODE:
239     case Node::PROCESSING_INSTRUCTION_NODE:
240         return nodeValue();
241 
242     case Node::ELEMENT_NODE:
243     case Node::ATTRIBUTE_NODE:
244     case Node::ENTITY_NODE:
245     case Node::ENTITY_REFERENCE_NODE:
246     case Node::DOCUMENT_FRAGMENT_NODE: {
247         DOMString s = "";
248 
249         for (NodeImpl *child = firstChild(); child; child = child->nextSibling()) {
250             if (child->nodeType() == Node::COMMENT_NODE ||
251                     child->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
252                 continue;
253             }
254 
255             s += child->textContent();
256         }
257 
258         return s;
259     }
260 
261     case Node::DOCUMENT_NODE:
262     case Node::DOCUMENT_TYPE_NODE:
263     case Node::NOTATION_NODE:
264     default:
265         return DOMString();
266     }
267 }
268 
setTextContent(const DOMString & text,int & ec)269 void NodeImpl::setTextContent(const DOMString &text, int &ec)
270 {
271     if (isReadOnly()) {
272         ec = DOMException::NO_MODIFICATION_ALLOWED_ERR;
273         return;
274     }
275 
276     switch (nodeType()) {
277     case Node::TEXT_NODE:
278     case Node::CDATA_SECTION_NODE:
279     case Node::COMMENT_NODE:
280     case Node::PROCESSING_INSTRUCTION_NODE:
281         setNodeValue(text, ec);
282         break;
283     case Node::ELEMENT_NODE:
284     case Node::ATTRIBUTE_NODE:
285     case Node::ENTITY_NODE:
286     case Node::ENTITY_REFERENCE_NODE:
287     case Node::DOCUMENT_FRAGMENT_NODE: {
288         NodeBaseImpl *container = static_cast<NodeBaseImpl *>(this);
289 
290         container->removeChildren();
291 
292         if (!text.isEmpty()) {
293             appendChild(document()->createTextNode(text.implementation()), ec);
294         }
295         break;
296     }
297     case Node::DOCUMENT_NODE:
298     case Node::DOCUMENT_TYPE_NODE:
299     case Node::NOTATION_NODE:
300     default:
301         // Do nothing
302         break;
303     }
304 }
305 
localName() const306 DOMString NodeImpl::localName() const
307 {
308     return DOMString();
309 }
310 
setFirstChild(NodeImpl *)311 void NodeImpl::setFirstChild(NodeImpl *)
312 {
313 }
314 
setLastChild(NodeImpl *)315 void NodeImpl::setLastChild(NodeImpl *)
316 {
317 }
318 
addChild(NodeImpl *)319 NodeImpl *NodeImpl::addChild(NodeImpl *)
320 {
321     return nullptr;
322 }
323 
getCaret(int,bool override,int & _x,int & _y,int & width,int & height)324 void NodeImpl::getCaret(int /*offset*/, bool override, int &_x, int &_y, int &width, int &height)
325 {
326     if (m_render) {
327         RenderObject *r = nullptr;
328         long r_ofs = 0;
329         bool outside, outsideEnd;
330 #if 0
331 // qCDebug(KHTML_LOG) << "getCaret: node " << this << " " << nodeName().string() << " offset: " << offset;
332 #endif
333 //         mapDOMPosToRenderPos(this, offset, r, r_ofs, outside, outsideEnd);
334         outside = false;
335         outsideEnd = false;
336 #if 0
337 // qCDebug(KHTML_LOG) << "getCaret: r " << r << " " << (r?r->renderName():QString()) << " r_ofs: " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd;
338 #endif
339         if (r) {
340             r->caretPos(r_ofs, override * RenderObject::CFOverride
341                         + outside * RenderObject::CFOutside
342                         + outsideEnd * RenderObject::CFOutsideEnd, _x, _y, width, height);
343         } else {
344             _x = _y = height = -1, width = 1;
345         }
346     } else {
347         _x = _y = height = -1, width = 1;
348     }
349 }
350 
isContentEditable() const351 bool NodeImpl::isContentEditable() const
352 {
353     return parentNode() ? parentNode()->isContentEditable() : false;
354 }
355 
getRect() const356 QRect NodeImpl::getRect() const
357 {
358     int _x, _y;
359     if (m_render && m_render->absolutePosition(_x, _y))
360         return QRect(_x + m_render->inlineXPos(), _y + m_render->inlineYPos(),
361                      m_render->width(), m_render->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra());
362 
363     return QRect();
364 }
365 
setChanged(bool b)366 void NodeImpl::setChanged(bool b)
367 {
368     if (b && !attached()) { // changed compared to what?
369         return;
370     }
371 
372     m_changed = b;
373     if (b) {
374         NodeImpl *p = parentNode();
375         while (p) {
376             p->setHasChangedChild(true);
377             p = p->parentNode();
378         }
379         document()->setDocumentChanged();
380     }
381 }
382 
isInline() const383 bool NodeImpl::isInline() const
384 {
385     if (m_render) {
386         return m_render->style()->display() == khtml::INLINE;
387     }
388     return !isElementNode();
389 }
390 
nodeIndex() const391 unsigned long NodeImpl::nodeIndex() const
392 {
393     NodeImpl *_tempNode = previousSibling();
394     unsigned long count = 0;
395     for (count = 0; _tempNode; count++) {
396         _tempNode = _tempNode->previousSibling();
397     }
398     return count;
399 }
400 
eventTargetDocument()401 DocumentImpl *NodeImpl::eventTargetDocument()
402 {
403     return document();
404 }
405 
dispatchEvent(EventImpl * evt,int & exceptioncode,bool tempEvent)406 void NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
407 {
408     evt->setTarget(this);
409 
410     dispatchGenericEvent(evt, exceptioncode);
411 
412     KHTMLPart *part = document()->part();
413     // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
414     // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
415     // So there is no need for the interpreter to keep the event in its cache
416     if (tempEvent && part && part->jScript()) {
417         part->jScript()->finishedWithEvent(evt);
418     }
419 }
420 
dispatchGenericEvent(EventImpl * evt,int &)421 void NodeImpl::dispatchGenericEvent(EventImpl *evt, int &/*exceptioncode */)
422 {
423     // ### check that type specified
424 
425     ref();
426 
427     // work out what nodes to send event to
428     QList<EventTargetImpl *> nodeChain;
429 
430     if (evt->target()->eventTargetType() != DOM_NODE) {
431         // The target is the only thing that goes into the chain.
432         nodeChain.prepend(evt->target());
433         evt->target()->ref();
434 
435         // ... except, well, load events lie and say their target is the document,
436         // so we patch that up now (since we want it as Window before we got here
437         if (evt->id() == EventImpl::LOAD_EVENT && evt->target()->eventTargetType() == WINDOW) {
438             evt->setTarget(document());
439         }
440     } else if (inDocument()) {
441         for (NodeImpl *n = this; n; n = n->parentNode()) {
442             n->ref();
443             nodeChain.prepend(n);
444         }
445 
446         // If the event isn't a load event, we propagate it up to window as well.
447         // The exclusion is so that things like image load events don't make it
448         // all the way upto window.onload. Meanwhile, the main load event
449         // is dispatched specially, via dispatchWindowEvent, with the case
450         // above doing the necessary fiddling for it.
451         if (evt->id() != EventImpl::LOAD_EVENT) {
452             EventTargetImpl *t = document()->windowEventTarget();
453             t->ref();
454             nodeChain.prepend(t);
455         }
456     } else {
457         // if node is not in the document just send event to itself
458         ref();
459         nodeChain.prepend(this);
460     }
461 
462     // trigger any capturing event handlers on our way down
463     evt->setEventPhase(Event::CAPTURING_PHASE);
464     QListIterator<EventTargetImpl *> it(nodeChain);
465     while (it.hasNext()) {
466         EventTargetImpl *cur = it.next();
467         if (cur == this || evt->propagationStopped()) {
468             break;
469         }
470         evt->setCurrentTarget(cur);
471         cur->handleLocalEvents(evt, true);
472     }
473 
474     // dispatch to the actual target node
475     it.toBack();
476     EventTargetImpl *curn = it.hasPrevious() ? it.previous() : nullptr;
477     EventTargetImpl *propagationSentinel = nullptr;
478     if (curn && !evt->propagationStopped()) {
479         evt->setEventPhase(Event::AT_TARGET);
480         evt->setCurrentTarget(curn);
481         curn->handleLocalEvents(evt, true);
482         if (!evt->propagationStopped()) {
483             curn->handleLocalEvents(evt, false);
484         } else {
485             propagationSentinel = curn;
486         }
487     }
488 
489     curn = it.hasPrevious() ? it.previous() : nullptr;
490 
491     if (evt->bubbles()) {
492         evt->setEventPhase(Event::BUBBLING_PHASE);
493         while (curn && !evt->propagationStopped()) {
494             if (evt->propagationStopped()) {
495                 propagationSentinel = curn;
496             }
497             evt->setCurrentTarget(curn);
498             curn->handleLocalEvents(evt, false);
499             curn = it.hasPrevious() ? it.previous() : nullptr;
500         }
501 
502         // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
503         evt->setCurrentTarget(nullptr);
504         evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
505 
506         it.toBack();
507         while (it.hasPrevious()) {
508             curn = it.previous();
509             if (curn == propagationSentinel || evt->defaultPrevented() || evt->defaultHandled()) {
510                 break;
511             }
512             curn->defaultEventHandler(evt);
513         }
514 
515         if (evt->id() == EventImpl::CLICK_EVENT && !evt->defaultPrevented() &&
516                 static_cast<MouseEventImpl *>(evt)->button() == 0) { // LMB click
517             dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, static_cast<UIEventImpl *>(evt)->detail());
518         }
519     }
520 
521     // deref all nodes in chain
522     it.toFront();
523     while (it.hasNext()) {
524         it.next()->deref();    // this may delete us
525     }
526 
527     DocumentImpl::updateDocumentsRendering();
528 
529     deref();
530 }
531 
dispatchHTMLEvent(int _id,bool canBubbleArg,bool cancelableArg)532 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
533 {
534     int exceptioncode = 0;
535     EventImpl *const evt = new EventImpl(static_cast<EventImpl::EventId>(_id), canBubbleArg, cancelableArg);
536     evt->ref();
537     dispatchEvent(evt, exceptioncode, true);
538     bool ret = !evt->defaultPrevented();
539     evt->deref();
540     return ret;
541 }
542 
dispatchWindowEvent(int _id,bool canBubbleArg,bool cancelableArg)543 void NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
544 {
545     EventImpl *const evt = new EventImpl(static_cast<EventImpl::EventId>(_id), canBubbleArg, cancelableArg);
546     dispatchWindowEvent(evt);
547 }
548 
dispatchWindowEvent(EventImpl * evt)549 void NodeImpl::dispatchWindowEvent(EventImpl *evt)
550 {
551     evt->setTarget(document()->windowEventTarget());
552     evt->ref();
553 
554     int exceptioncode = 0;
555     dispatchGenericEvent(evt, exceptioncode);
556 
557     if (evt->id() == EventImpl::LOAD_EVENT) {
558         // Trigger Load Event on the enclosing frame if there is one
559         DOM::HTMLPartContainerElementImpl *elt = document()->ownerElement();
560         if (elt) {
561             elt->slotEmitLoadEvent();
562         }
563     }
564 
565     evt->deref();
566 }
567 
dispatchMouseEvent(QMouseEvent * _mouse,int overrideId,int overrideDetail)568 void NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
569 {
570     bool cancelable = true;
571     int detail = overrideDetail; // defaults to 0
572     EventImpl::EventId evtId;
573     if (overrideId) {
574         evtId = static_cast<EventImpl::EventId>(overrideId);
575     } else {
576         switch (_mouse->type()) {
577         case QEvent::MouseButtonPress:
578             evtId = EventImpl::MOUSEDOWN_EVENT;
579             break;
580         case QEvent::MouseButtonRelease:
581             evtId = EventImpl::MOUSEUP_EVENT;
582             break;
583         case QEvent::MouseButtonDblClick:
584             evtId = EventImpl::CLICK_EVENT;
585             detail = 1; // ### support for multiple double clicks
586             break;
587         case QEvent::MouseMove:
588             evtId = EventImpl::MOUSEMOVE_EVENT;
589             cancelable = false;
590             break;
591         default:
592             return;
593         }
594     }
595 
596     int exceptioncode = 0;
597     int pageX = _mouse->x();
598     int pageY = _mouse->y();
599     if (document()->view()) {
600         document()->view()->revertTransforms(pageX, pageY);
601     }
602     int clientX = pageX;
603     int clientY = pageY;
604     if (document()->view()) {
605         document()->view()->contentsToViewport(pageX, pageY, pageX, pageY);
606     }
607 
608     int screenX = _mouse->globalX();
609     int screenY = _mouse->globalY();
610 
611     int button = -1;
612     switch (_mouse->button()) {
613     case Qt::LeftButton:
614         button = 0;
615         break;
616     case Qt::MidButton:
617         button = 1;
618         break;
619     case Qt::RightButton:
620         button = 2;
621         break;
622     default:
623         break;
624     }
625     bool ctrlKey = (_mouse->modifiers() & Qt::ControlModifier);
626     bool altKey = (_mouse->modifiers() & Qt::AltModifier);
627     bool shiftKey = (_mouse->modifiers() & Qt::ShiftModifier);
628     bool metaKey = (_mouse->modifiers() & Qt::MetaModifier);
629 
630     EventImpl *const evt = new MouseEventImpl(evtId, true, cancelable, document()->defaultView(),
631             detail, screenX, screenY, clientX, clientY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey,
632             button, nullptr);
633     evt->ref();
634     dispatchEvent(evt, exceptioncode, true);
635     evt->deref();
636 }
637 
dispatchUIEvent(int _id,int detail)638 void NodeImpl::dispatchUIEvent(int _id, int detail)
639 {
640     assert(!((_id != EventImpl::DOMFOCUSIN_EVENT &&
641               _id != EventImpl::DOMFOCUSOUT_EVENT &&
642               _id != EventImpl::DOMACTIVATE_EVENT)));
643 
644     bool cancelable = false;
645     if (_id == EventImpl::DOMACTIVATE_EVENT) {
646         cancelable = true;
647     }
648 
649     int exceptioncode = 0;
650     UIEventImpl *const evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id), true,
651             cancelable, document()->defaultView(), detail);
652     evt->ref();
653     dispatchEvent(evt, exceptioncode, true);
654     evt->deref();
655 }
656 
dispatchSubtreeModifiedEvent()657 void NodeImpl::dispatchSubtreeModifiedEvent()
658 {
659     childrenChanged();
660     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
661     if (!document()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER)) {
662         return;
663     }
664     int exceptioncode = 0;
665     ref();
666     MutationEventImpl *const evt = new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT, true,
667             false, nullptr, DOMString(), DOMString(), DOMString(), 0);
668     evt->ref();
669     dispatchEvent(evt, exceptioncode, true);
670     evt->deref();
671     derefOnly();
672 }
673 
dispatchKeyEvent(QKeyEvent * key,bool keypress)674 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key, bool keypress)
675 {
676     int exceptioncode = 0;
677     //qCDebug(KHTML_LOG) << "DOM::NodeImpl: dispatching keyboard event";
678     EventImpl *keyEventImpl;
679     if (keypress) {
680         keyEventImpl = new TextEventImpl(key, document()->defaultView());
681     } else {
682         keyEventImpl = new KeyboardEventImpl(key, document()->defaultView());
683     }
684     keyEventImpl->ref();
685     dispatchEvent(keyEventImpl, exceptioncode, true);
686     bool r = keyEventImpl->defaultHandled() || keyEventImpl->defaultPrevented();
687     keyEventImpl->deref();
688     return r;
689 }
690 
childNodeCount()691 unsigned long NodeImpl::childNodeCount()
692 {
693     return 0;
694 }
695 
childNode(unsigned long)696 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
697 {
698     return nullptr;
699 }
700 
traverseNextNode(NodeImpl * stayWithin) const701 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
702 {
703     if (firstChild() || stayWithin == this) {
704         return firstChild();
705     } else if (nextSibling()) {
706         return nextSibling();
707     } else {
708         const NodeImpl *n = this;
709         while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin)) {
710             n = n->parentNode();
711         }
712         if (n) {
713             return n->nextSibling();
714         }
715     }
716     return nullptr;
717 }
718 
traversePreviousNode() const719 NodeImpl *NodeImpl::traversePreviousNode() const
720 {
721     if (previousSibling()) {
722         NodeImpl *n = previousSibling();
723         while (n->lastChild()) {
724             n = n->lastChild();
725         }
726         return n;
727     } else if (parentNode()) {
728         return parentNode();
729     } else {
730         return nullptr;
731     }
732 }
733 
checkSetPrefix(const DOMString & _prefix,int & exceptioncode)734 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
735 {
736     // Perform error checking as required by spec for setting Node.prefix. Used by
737     // ElementImpl::setPrefix() and AttrImpl::setPrefix()
738 
739     // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
740     if (!Element::khtmlValidPrefix(_prefix)) {
741         exceptioncode = DOMException::INVALID_CHARACTER_ERR;
742         return;
743     }
744 
745     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
746     if (isReadOnly()) {
747         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
748         return;
749     }
750 
751     // NAMESPACE_ERR: - Raised if the specified prefix is malformed
752     // - if the namespaceURI of this node is null,
753     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
754     //   "http://www.w3.org/XML/1998/namespace",
755     // - if this node is an attribute and the specified prefix is "xmlns" and
756     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
757     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
758     if (Element::khtmlMalformedPrefix(_prefix) || /*FIXME: use IDString somehow here (namespacePart(id()) == defaultNamespace && id() > ID_LAST_TAG) ||*/
759             (_prefix == "xml" && namespaceURI() != "http://www.w3.org/XML/1998/namespace")) {
760         exceptioncode = DOMException::NAMESPACE_ERR;
761         return;
762     }
763 }
764 
checkAddChild(NodeImpl * newChild,int & exceptioncode)765 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
766 {
767     // Perform error checking as required by spec for adding a new child. Used by
768     // appendChild(), replaceChild() and insertBefore()
769 
770     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
771     if (!newChild) {
772         exceptioncode = DOMException::NOT_FOUND_ERR;
773         return;
774     }
775 
776     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
777     if (isReadOnly()) {
778         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
779         return;
780     }
781 
782     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
783     // created this node.
784     // We assume that if newChild is a DocumentFragment, all children are created from the same document
785     // as the fragment itself (otherwise they could not have been added as children)
786     if (newChild->document() != document()) {
787         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
788         return;
789     }
790 
791     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
792     // newChild node, or if the node to append is one of this node's ancestors.
793 
794     // check for ancestor/same node
795     if (isAncestor(newChild)) {
796         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
797         return;
798     }
799 
800     // check node allowed
801     if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
802         // newChild is a DocumentFragment... check all its children instead of newChild itself
803         NodeImpl *child;
804         for (child = newChild->firstChild(); child; child = child->nextSibling()) {
805             if (!childTypeAllowed(child->nodeType())) {
806                 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
807                 return;
808             }
809         }
810     } else {
811         // newChild is not a DocumentFragment... check if it's allowed directly
812         if (!childTypeAllowed(newChild->nodeType())) {
813             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
814             return;
815         }
816     }
817 }
818 
isAncestor(NodeImpl * other) const819 bool NodeImpl::isAncestor(NodeImpl *other) const
820 {
821     // Return true if other is the same as this node or an ancestor of it, otherwise false
822     const NodeImpl *n;
823     for (n = this; n; n = n->parentNode()) {
824         if (n == other) {
825             return true;
826         }
827     }
828     return false;
829 }
830 
childAllowed(NodeImpl * newChild)831 bool NodeImpl::childAllowed(NodeImpl *newChild)
832 {
833     return childTypeAllowed(newChild->nodeType());
834 }
835 
diff(khtml::RenderStyle * s1,khtml::RenderStyle * s2)836 NodeImpl::StyleChange NodeImpl::diff(khtml::RenderStyle *s1, khtml::RenderStyle *s2)
837 {
838     // This method won't work when a style contains noninherited properties with "inherit" value.
839     StyleChange ch = NoInherit;
840 
841     EDisplay display1 = s1 ? s1->display() : NONE;
842     EDisplay display2 = s2 ? s2->display() : NONE;
843     EPosition position1 = s1 ? s1->position() : PSTATIC;
844     EPosition position2 = s2 ? s2->position() : PSTATIC;
845 
846     if (display1 != display2 || position1 != position2) {
847         ch = Detach;
848     } else if (!s1 || !s2) {
849         ch = Inherit;
850     } else if (*s1 == *s2) {
851         ch = NoChange;
852     } else if (s1->useNormalContent() != s2->useNormalContent()) {
853         ch = Detach;    // when we add generated content all children must be detached
854     } else if (s1->inheritedNotEqual(s2)) {
855         ch = Inherit;
856     }
857 
858     // Because the first-letter implementation is so f..ked up, the easiest way
859     // to update first-letter is to remove the entire node and readd it.
860     if (ch < Detach && pseudoDiff(s1, s2, khtml::RenderStyle::FIRST_LETTER)) {
861         ch = Detach;
862     }
863     // If the other pseudoStyles have changed, we want to return NoInherit
864     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::BEFORE)) {
865         ch = NoInherit;
866     }
867     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::AFTER)) {
868         ch = NoInherit;
869     }
870     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::MARKER)) {
871         ch = NoInherit;
872     }
873     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::SELECTION)) {
874         ch = NoInherit;
875     }
876     if (ch == NoChange && pseudoDiff(s1, s2, khtml::RenderStyle::FIRST_LINE)) {
877         ch = NoInherit;
878     }
879 
880     return ch;
881 }
882 
pseudoDiff(khtml::RenderStyle * s1,khtml::RenderStyle * s2,unsigned int pid)883 bool NodeImpl::pseudoDiff(khtml::RenderStyle *s1, khtml::RenderStyle *s2, unsigned int pid)
884 {
885     khtml::RenderStyle *ps1 = s1 ? s1->getPseudoStyle((khtml::RenderStyle::PseudoId)pid) : nullptr;
886     khtml::RenderStyle *ps2 = s2 ? s2->getPseudoStyle((khtml::RenderStyle::PseudoId)pid) : nullptr;
887 
888     if (ps1 == ps2) {
889         return false;
890     } else if (ps1 && ps2) {
891         if (*ps1 == *ps2) {
892             return false;
893         } else {
894             return true;
895         }
896     } else {
897         return true;
898     }
899 }
900 
affectedByNoInherit() const901 bool NodeImpl::affectedByNoInherit() const
902 {
903     if (m_render && m_render->style()) {
904         return m_render->style()->inheritedNoninherited();
905     } else {
906         return false;
907     }
908 }
909 
close()910 void NodeImpl::close()
911 {
912     if (m_render) {
913         m_render->close();
914     }
915     m_closed = true;
916 }
917 
attach()918 void NodeImpl::attach()
919 {
920     assert(!attached());
921     assert(!m_render || (m_render->style() && m_render->parent()));
922     if (m_render) { // set states to match node
923         if (closed()) {
924             m_render->close();
925         }
926         if (hovered()) {
927             m_render->setMouseInside();
928         }
929     }
930     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
931     m_attached = true;
932 }
933 
detach()934 void NodeImpl::detach()
935 {
936 //    assert(m_attached);
937 
938     if (m_render) {
939         m_render->detach();
940     }
941 
942     m_render = nullptr;
943     document()->incDOMTreeVersion(DocumentImpl::TV_Structural);
944     m_attached = false;
945 }
946 
maintainsState()947 bool NodeImpl::maintainsState()
948 {
949     return false;
950 }
951 
state()952 QString NodeImpl::state()
953 {
954     return QString();
955 }
956 
restoreState(const QString &)957 void NodeImpl::restoreState(const QString &/*state*/)
958 {
959 }
960 
insertedIntoDocument()961 void NodeImpl::insertedIntoDocument()
962 {
963     setInDocument(true);
964 }
965 
removedFromDocument()966 void NodeImpl::removedFromDocument()
967 {
968     setInDocument(false);
969 }
970 
childrenChanged()971 void NodeImpl::childrenChanged()
972 {
973     if (parentNode()) {
974         parentNode()->childrenChanged();
975     }
976 }
977 
isReadOnly()978 bool NodeImpl::isReadOnly()
979 {
980     // Entity & Entity Reference nodes and their descendants are read-only
981     NodeImpl *n = this;
982     while (n) {
983         if (n->nodeType() == Node::ENTITY_NODE ||
984                 n->nodeType() == Node::ENTITY_REFERENCE_NODE) {
985             return true;
986         }
987         n = n->parentNode();
988     }
989     return false;
990 }
991 
previousEditable() const992 NodeImpl *NodeImpl::previousEditable() const
993 {
994     NodeImpl *node = previousLeafNode();
995     while (node) {
996         if (node->document()->part()->isCaretMode() || node->isContentEditable()) {
997             return node;
998         }
999         node = node->previousLeafNode();
1000     }
1001     return nullptr;
1002 }
1003 
nextEditable() const1004 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 
previousRenderer()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 
nextRenderer()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 
createRendererIfNeeded()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 
styleForRenderer(RenderObject * parent)1062 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1063 {
1064     return parent->style();
1065 }
1066 
rendererIsNeeded(RenderStyle * style)1067 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1068 {
1069     return (document()->documentElement() == this) || (style->display() != NONE);
1070 }
1071 
createRenderer(RenderArena *,RenderStyle *)1072 RenderObject *NodeImpl::createRenderer(RenderArena * /*arena*/, RenderStyle * /*style*/)
1073 {
1074     assert(false);
1075     return nullptr;
1076 }
1077 
computedStyle()1078 RenderStyle *NodeImpl::computedStyle()
1079 {
1080     return parentNode() ? parentNode()->computedStyle() : nullptr;
1081 }
1082 
previousLeafNode() const1083 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 
nextLeafNode() const1095 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 
maxOffset() const1107 long NodeImpl::maxOffset() const
1108 {
1109     return 1;
1110 }
1111 
caretMinOffset() const1112 long NodeImpl::caretMinOffset() const
1113 {
1114     return renderer() ? renderer()->caretMinOffset() : 0;
1115 }
1116 
caretMaxOffset() const1117 long NodeImpl::caretMaxOffset() const
1118 {
1119     return renderer() ? renderer()->caretMaxOffset() : 1;
1120 }
1121 
caretMaxRenderedOffset() const1122 unsigned long NodeImpl::caretMaxRenderedOffset() const
1123 {
1124     return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1125 }
1126 
isBlockFlow() const1127 bool NodeImpl::isBlockFlow() const
1128 {
1129     return renderer() && renderer()->isBlockFlow();
1130 }
1131 
isEditableBlock() const1132 bool NodeImpl::isEditableBlock() const
1133 {
1134     return isBlockFlow() && isContentEditable();
1135 }
1136 
enclosingBlockFlowElement() const1137 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 
rootEditableElement() const1156 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 
inSameRootEditableElement(NodeImpl * n)1180 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1181 {
1182     return n ? rootEditableElement() == n->rootEditableElement() : false;
1183 }
1184 
inSameContainingBlockFlowElement(NodeImpl * n)1185 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1186 {
1187     return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1188 }
1189 
positionForCoordinates(int x,int y) const1190 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 
isPointInsideSelection(int x,int y,const Selection & sel) const1199 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 
getElementsByTagName(const DOMString & tagName)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 
getElementsByTagNameNS(const DOMString & namespaceURI,const DOMString & localName)1242 NodeListImpl *NodeImpl::getElementsByTagNameNS(const DOMString &namespaceURI, const DOMString &localName)
1243 {
1244     return new TagNodeListImpl(this, namespaceURI, localName);
1245 }
1246 
getElementsByClassName(const DOMString & name)1247 NodeListImpl *NodeImpl::getElementsByClassName(const DOMString &name)
1248 {
1249     return new ClassNodeListImpl(this, name);
1250 }
1251 
hasAttributes() const1252 bool NodeImpl::hasAttributes() const
1253 {
1254     return false;
1255 }
1256 
isSupported(const DOMString & feature,const DOMString & version)1257 bool NodeImpl::isSupported(const DOMString &feature, const DOMString &version)
1258 {
1259     return DOMImplementationImpl::hasFeature(feature, version);
1260 }
1261 
ownerDocument() const1262 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.
logicalParentNode(const DOM::NodeImpl * node)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 
compareDocumentPosition(const DOM::NodeImpl * other)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 
rootForSelectorQuery(DOM::NodeImpl * arg)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 
querySelector(const DOM::DOMString & query,int & ec)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 
querySelectorAll(const DOM::DOMString & query,int & ec)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 
setDocument(DocumentImpl * doc)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 
lookupNamespaceURI(const DOM::DOMString & prefix)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 
findNextElementAncestor(NodeImpl * node)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 
~NodeBaseImpl()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 
firstChild() const1559 NodeImpl *NodeBaseImpl::firstChild() const
1560 {
1561     return _first;
1562 }
1563 
lastChild() const1564 NodeImpl *NodeBaseImpl::lastChild() const
1565 {
1566     return _last;
1567 }
1568 
insertBefore(NodeImpl * newChild,NodeImpl * refChild,int & exceptioncode)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 
replaceChild(NodeImpl * newChild,NodeImpl * oldChild,int & exceptioncode)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 
removeChild(NodeImpl * oldChild,int & exceptioncode)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 
removeChildren()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 
appendChild(NodeImpl * newChild,int & exceptioncode)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 
hasChildNodes() const1917 bool NodeBaseImpl::hasChildNodes() const
1918 {
1919     return _first != nullptr;
1920 }
1921 
1922 // not part of the DOM
setFirstChild(NodeImpl * child)1923 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1924 {
1925     _first = child;
1926 }
1927 
setLastChild(NodeImpl * child)1928 void NodeBaseImpl::setLastChild(NodeImpl *child)
1929 {
1930     _last = child;
1931 }
1932 
1933 // check for same source document:
checkSameDocument(NodeImpl * newChild,int & exceptioncode)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:
checkIsChild(NodeImpl * oldChild,int & exceptioncode)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 
addChild(NodeImpl * newChild)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 
attach()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 
detach()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 
cloneChildNodes(NodeImpl * clone)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
getUpperLeftCorner(int & xPos,int & yPos) const2021 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 
getLowerRightCorner(int & xPos,int & yPos) const2065 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 
setFocus(bool received)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 
setActive(bool down)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 
setHovered(bool hover)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 
childNodeCount()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 
childNode(unsigned long index)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 
dispatchChildInsertedEvents(NodeImpl * child,int & exceptioncode)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 
dispatchChildRemovalEvents(NodeImpl * child,int & exceptioncode)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 
NamedNodeMapImpl()2257 NamedNodeMapImpl::NamedNodeMapImpl()
2258 {
2259 }
2260 
~NamedNodeMapImpl()2261 NamedNodeMapImpl::~NamedNodeMapImpl()
2262 {
2263 }
2264 
getNamedItem(const DOMString & name)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 
setNamedItem(const Node & arg,int & exceptioncode)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 
removeNamedItem(const DOMString & name,int & exceptioncode)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 
getNamedItemNS(const DOMString & namespaceURI,const DOMString & localName)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 
setNamedItemNS(const Node & arg,int & exceptioncode)2302 Node NamedNodeMapImpl::setNamedItemNS(const Node &arg, int &exceptioncode)
2303 {
2304     return setNamedItem(arg.handle(), emptyPrefixName, true, exceptioncode);
2305 }
2306 
removeNamedItemNS(const DOMString & namespaceURI,const DOMString & localName,int & exceptioncode)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 
GenericRONamedNodeMapImpl(DocumentImpl * doc)2316 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentImpl *doc)
2317     : NamedNodeMapImpl()
2318 {
2319     m_doc = doc;
2320     m_contents = new QList<NodeImpl *>;
2321 }
2322 
~GenericRONamedNodeMapImpl()2323 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2324 {
2325     while (!m_contents->isEmpty()) {
2326         m_contents->takeLast()->deref();
2327     }
2328 
2329     delete m_contents;
2330 }
2331 
getNamedItem(NodeImpl::Id id,const PrefixName &,bool)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 
setNamedItem(NodeImpl *,const PrefixName &,bool,int & exceptioncode)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 
removeNamedItem(NodeImpl::Id,const PrefixName &,bool,int & exceptioncode)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 
item(unsigned index)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 
length() const2368 unsigned GenericRONamedNodeMapImpl::length() const
2369 {
2370     return m_contents->count();
2371 }
2372 
addNode(NodeImpl * n)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 
2384