2 * This file is part of the DOM implementation for KDE.
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 * Copyright (C) 2004 Apple Computer, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 #include "xml/dom_nodeimpl.h"
27 #include "dom/dom_exception.h"
28 #include "misc/htmlattrs.h"
29 #include "misc/htmltags.h"
30 #include "xml/dom_elementimpl.h"
31 #include "xml/dom_textimpl.h"
32 #include "xml/dom2_eventsimpl.h"
33 #include "xml/dom_docimpl.h"
34 #include "xml/dom_position.h"
35 #include "xml/dom2_rangeimpl.h"
36 #include "css/csshelper.h"
37 #include "css/cssstyleselector.h"
38 #include "editing/selection.h"
43 #include "rendering/render_object.h"
44 #include "rendering/render_text.h"
46 #include "ecma/kjs_binding.h"
47 #include "ecma/kjs_proxy.h"
48 #include "khtmlview.h"
49 #include "khtml_part.h"
54 #include "xbl/xbl_binding_manager.h"
58 #include "KWQAssertions.h"
59 #include "KWQLogging.h"
61 #define ASSERT(assertion) assert(assertion)
62 #define LOG(channel, formatAndArgs...) ((void)0)
66 using namespace khtml;
68 NodeImpl::NodeImpl(DocumentPtr *doc)
80 m_hasChangedChild( false ),
81 m_inDocument( false ),
86 m_styleElement( false ),
93 void NodeImpl::setDocument(DocumentPtr *doc)
107 NodeImpl::~NodeImpl()
111 delete m_regdListeners;
115 m_previous->setNextSibling(0);
117 m_next->setPreviousSibling(0);
120 DOMString NodeImpl::nodeValue() const
125 void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode )
127 // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
129 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
133 // be default nodeValue is null, so setting it has no effect
136 DOMString NodeImpl::nodeName() const
141 unsigned short NodeImpl::nodeType() const
146 NodeListImpl *NodeImpl::childNodes()
148 return new ChildNodeListImpl(this);
151 NodeImpl *NodeImpl::firstChild() const
156 NodeImpl *NodeImpl::lastChild() const
161 NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl *, int &exceptioncode )
163 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
167 NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode )
169 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
173 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
175 exceptioncode = DOMException::NOT_FOUND_ERR;
179 NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode )
181 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
185 void NodeImpl::remove(int &exceptioncode)
189 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
193 parentNode()->removeChild(this, exceptioncode);
196 bool NodeImpl::hasChildNodes( ) const
201 void NodeImpl::normalize ()
203 // ### normalize attributes? (when we store attributes using child nodes)
204 int exceptioncode = 0;
205 NodeImpl *child = firstChild();
207 // Recursively go through the subtree beneath us, normalizing all nodes. In the case
208 // where there are two adjacent text nodes, they are merged together
210 NodeImpl *nextChild = child->nextSibling();
212 if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
213 // Current child and the next one are both text nodes... merge them
214 TextImpl *currentText = static_cast<TextImpl*>(child);
215 TextImpl *nextText = static_cast<TextImpl*>(nextChild);
217 currentText->appendData(nextText->data(),exceptioncode);
221 removeChild(nextChild,exceptioncode);
232 DOMString NodeImpl::prefix() const
234 // For nodes other than elements and attributes, the prefix is always null
238 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
240 // The spec says that for nodes other than elements and attributes, prefix is always null.
241 // It does not say what to do when the user tries to set the prefix on another type of
242 // node, however mozilla throws a NAMESPACE_ERR exception
243 exceptioncode = DOMException::NAMESPACE_ERR;
246 DOMString NodeImpl::localName() const
251 void NodeImpl::setFirstChild(NodeImpl *)
255 void NodeImpl::setLastChild(NodeImpl *)
259 NodeImpl *NodeImpl::addChild(NodeImpl *)
264 QString NodeImpl::toHTML() const
266 return recursive_toHTML(true);
269 static QString escapeHTML( const QString& in )
272 for ( unsigned int i = 0; i < in.length(); ++i ) {
273 switch( in[i].latin1() ) {
291 QString NodeImpl::startMarkup(const DOM::RangeImpl *range) const
293 unsigned short type = nodeType();
294 if (type == Node::TEXT_NODE) {
295 DOMString str = nodeValue().copy();
298 if (this == range->endContainer(exceptionCode)) {
299 str.truncate(range->endOffset(exceptionCode));
301 if (this == range->startContainer(exceptionCode)) {
302 str.remove(0, range->startOffset(exceptionCode));
305 Id parentID = parentNode()->id();
306 bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
307 return dontEscape ? str.string() : escapeHTML(str.string());
308 } else if (type != Node::DOCUMENT_NODE) {
309 QString markup = QChar('<') + nodeName().string();
310 if (type == Node::ELEMENT_NODE) {
311 const ElementImpl *el = static_cast<const ElementImpl *>(this);
312 NamedAttrMapImpl *attrs = el->attributes();
313 unsigned long length = attrs->length();
314 for (unsigned int i=0; i<length; i++) {
315 AttributeImpl *attr = attrs->attributeItem(i);
316 markup += " " + getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
319 markup += isHTMLElement() ? ">" : "/>";
325 QString NodeImpl::endMarkup(void) const
327 if ((!isHTMLElement() || endTag[id()] != FORBIDDEN) && nodeType() != Node::TEXT_NODE && nodeType() != Node::DOCUMENT_NODE) {
328 return "</" + nodeName().string() + ">";
333 QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, QPtrList<NodeImpl> *nodes)
335 // Doesn't make sense to only include children and include siblings.
336 assert(!(onlyIncludeChildren && includeSiblings));
338 for (const NodeImpl *current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
339 if (!onlyIncludeChildren) {
341 nodes->append(current);
343 me += current->startMarkup(0);
345 if (!current->isHTMLElement() || endTag[current->id()] != FORBIDDEN) {
347 if (NodeImpl *n = current->firstChild()) {
348 me += recursive_toString(n, false, true, nodes);
350 // Print my ending tag
351 if (!onlyIncludeChildren) {
352 me += current->endMarkup();
359 QString NodeImpl::recursive_toHTML(bool onlyIncludeChildren, QPtrList<NodeImpl> *nodes) const
361 return NodeImpl::recursive_toString(this, onlyIncludeChildren, false, nodes);
364 void NodeImpl::recursive_completeURLs(QString baseURL)
366 if (nodeType() == Node::ELEMENT_NODE) {
367 ElementImpl *el = static_cast<ElementImpl *>(this);
368 NamedAttrMapImpl *attrs = el->attributes();
369 unsigned long length = attrs->length();
370 for (unsigned int i=0; i<length; i++) {
371 AttributeImpl *attr = attrs->attributeItem(i);
372 if (el->isURLAttribute(attr)) {
373 el->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url());
379 if ((n = firstChild())) {
380 n->recursive_completeURLs(baseURL);
382 if ((n = nextSibling())) {
383 n->recursive_completeURLs(baseURL);
387 bool NodeImpl::isContentEditable() const
389 return m_parent ? m_parent->isContentEditable() : false;
392 QRect NodeImpl::getRect() const
395 if(m_render && m_render->absolutePosition(_x, _y))
396 return QRect( _x, _y, m_render->width(), m_render->height() );
401 void NodeImpl::setChanged(bool b)
403 if (b && !attached()) // changed compared to what?
408 NodeImpl *p = parentNode();
410 p->setHasChangedChild( true );
413 getDocument()->setDocumentChanged(true);
417 bool NodeImpl::isInline() const
419 if (m_render) return m_render->style()->display() == khtml::INLINE;
420 return !isElementNode();
423 bool NodeImpl::isFocusable() const
428 bool NodeImpl::isKeyboardFocusable() const
430 return isFocusable();
433 bool NodeImpl::isMouseFocusable() const
435 return isFocusable();
438 unsigned long NodeImpl::nodeIndex() const
440 NodeImpl *_tempNode = previousSibling();
441 unsigned long count=0;
442 for( count=0; _tempNode; count++ )
443 _tempNode = _tempNode->previousSibling();
447 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
450 case EventImpl::DOMSUBTREEMODIFIED_EVENT:
451 getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
453 case EventImpl::DOMNODEINSERTED_EVENT:
454 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
456 case EventImpl::DOMNODEREMOVED_EVENT:
457 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
459 case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
460 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
462 case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
463 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
465 case EventImpl::DOMATTRMODIFIED_EVENT:
466 getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
468 case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
469 getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
475 RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
476 if (!m_regdListeners) {
477 m_regdListeners = new QPtrList<RegisteredEventListener>;
478 m_regdListeners->setAutoDelete(true);
483 // remove existing identical listener set with identical arguments - the DOM2
484 // spec says that "duplicate instances are discarded" in this case.
485 removeEventListener(id,listener,useCapture);
487 m_regdListeners->append(rl);
491 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
493 if (!m_regdListeners) // nothing to remove
496 RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
498 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
499 for (; it.current(); ++it)
500 if (*(it.current()) == rl) {
501 m_regdListeners->removeRef(it.current());
506 void NodeImpl::removeHTMLEventListener(int id)
508 if (!m_regdListeners) // nothing to remove
511 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
512 for (; it.current(); ++it)
513 if (it.current()->id == id &&
514 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
515 m_regdListeners->removeRef(it.current());
520 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
522 // in case we already have it, we don't want removeHTMLEventListener to destroy it
525 removeHTMLEventListener(id);
528 addEventListener(id,listener,false);
533 EventListener *NodeImpl::getHTMLEventListener(int id)
535 if (!m_regdListeners)
538 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
539 for (; it.current(); ++it)
540 if (it.current()->id == id &&
541 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
542 return it.current()->listener;
548 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
552 evt->setTarget(this);
554 // We've had at least one report of a crash on a page where document is nil here.
555 // Unfortunately that page no longer exists, but we'll make this code robust against
557 // FIXME: Much code in this class assumes document is non-nil; it would be better to
558 // ensure that document can never be nil.
559 KHTMLPart *part = nil;
560 KHTMLView *view = nil;
562 if (document && document->document()) {
563 part = document->document()->part();
564 view = document->document()->view();
565 // Since event handling code could cause this object to be deleted, grab a reference to the view now
570 bool ret = dispatchGenericEvent( evt, exceptioncode );
572 // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
573 // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
574 // So there is no need for the interpreter to keep the event in it's cache
575 if (tempEvent && part && part->jScript())
576 part->jScript()->finishedWithEvent(evt);
586 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
590 // ### check that type specified
592 // work out what nodes to send event to
593 QPtrList<NodeImpl> nodeChain;
595 for (n = this; n; n = n->parentNode()) {
597 nodeChain.prepend(n);
600 // trigger any capturing event handlers on our way down
601 evt->setEventPhase(Event::CAPTURING_PHASE);
602 QPtrListIterator<NodeImpl> it(nodeChain);
603 for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
604 evt->setCurrentTarget(it.current());
605 it.current()->handleLocalEvents(evt,true);
608 // dispatch to the actual target node
610 if (!evt->propagationStopped()) {
611 evt->setEventPhase(Event::AT_TARGET);
612 evt->setCurrentTarget(it.current());
614 // Capturing first. -dwh
615 it.current()->handleLocalEvents(evt,true);
617 // Bubbling second. -dwh
618 if (!evt->propagationStopped())
619 it.current()->handleLocalEvents(evt,false);
623 // ok, now bubble up again (only non-capturing event handlers will be called)
624 // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
625 // no. the DOM specs says:
626 // The chain of EventTargets from the event target to the top of the tree
627 // is determined before the initial dispatch of the event.
628 // If modifications occur to the tree during event processing,
629 // event flow will proceed based on the initial state of the tree.
631 // since the initial dispatch is before the capturing phase,
632 // there's no need to recalculate the node chain.
635 if (evt->bubbles()) {
636 evt->setEventPhase(Event::BUBBLING_PHASE);
637 for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
638 evt->setCurrentTarget(it.current());
639 it.current()->handleLocalEvents(evt,false);
643 evt->setCurrentTarget(0);
644 evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
645 // anything about the default event handler phase.
648 if (evt->bubbles()) {
649 // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
652 for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
653 it.current()->defaultEventHandler(evt);
656 // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions
657 // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or
658 // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code.
659 if (!evt->defaultPrevented() && !disabled())
660 if (evt->id() == EventImpl::KHTML_CLICK_EVENT)
661 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1);
662 else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT)
663 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2);
665 // deref all nodes in chain
667 for (; it.current(); ++it)
668 it.current()->deref(); // this may delete us
670 DocumentImpl::updateDocumentsRendering();
672 bool defaultPrevented = evt->defaultPrevented();
676 return !defaultPrevented; // ### what if defaultPrevented was called before dispatchEvent?
679 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
681 int exceptioncode = 0;
682 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
683 return dispatchEvent(evt,exceptioncode,true);
686 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
688 int exceptioncode = 0;
689 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
692 DocumentPtr *doc = document;
694 bool r = dispatchGenericEvent( evt, exceptioncode );
695 if (!evt->defaultPrevented() && doc->document())
696 doc->document()->defaultEventHandler(evt);
698 if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
699 // For onload events, send them to the enclosing frame only.
700 // This is a DOM extension and is independent of bubbling/capturing rules of
701 // the DOM. You send the event only to the enclosing frame. It does not
702 // bubble through the parent document.
703 DOM::ElementImpl* elt = doc->document()->ownerElement();
704 if (elt && (elt->getDocument()->domain().isNull() ||
705 elt->getDocument()->domain() == doc->document()->domain())) {
706 // We also do a security check, since we don't want to allow the enclosing
707 // iframe to see loads of child documents in other domains.
708 evt->setCurrentTarget(elt);
711 elt->handleLocalEvents(evt,true);
714 if (!evt->propagationStopped())
715 elt->handleLocalEvents(evt,false);
716 r = !evt->defaultPrevented();
726 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
728 bool cancelable = true;
729 int detail = overrideDetail; // defaults to 0
730 EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
732 evtId = static_cast<EventImpl::EventId>(overrideId);
735 switch (_mouse->type()) {
736 case QEvent::MouseButtonPress:
737 evtId = EventImpl::MOUSEDOWN_EVENT;
739 case QEvent::MouseButtonRelease:
740 evtId = EventImpl::MOUSEUP_EVENT;
742 case QEvent::MouseButtonDblClick:
743 evtId = EventImpl::CLICK_EVENT;
744 detail = 1; // ### support for multiple double clicks
746 case QEvent::MouseMove:
747 evtId = EventImpl::MOUSEMOVE_EVENT;
754 if (evtId == EventImpl::UNKNOWN_EVENT)
755 return false; // shouldn't happen
758 int exceptioncode = 0;
761 // Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
762 // our khtmlview's coord system. This works for QMouseEvents coming from Cocoa because those events
763 // hold the location from the NSEvent. The QMouseEvent param here was made by other khtml code, so it
764 // will be a "proper" QT event with coords in terms of this widget. So in WebCore it would never be
765 // right to pass coords from _mouse to viewportToContents().
767 // int clientX, clientY;
768 // viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
769 int clientX = _mouse->x(); // ### adjust to be relative to view
770 int clientY = _mouse->y(); // ### adjust to be relative to view
775 KHTMLView *view = document->document()->view();
777 // This gets us as far as NSWindow coords
778 QPoint windowLoc = view->contentsToViewport(_mouse->pos());
779 // Then from NSWindow coords to screen coords
780 QPoint screenLoc = view->viewportToGlobal(windowLoc);
781 screenX = screenLoc.x();
782 screenY = screenLoc.y();
784 screenX = _mouse->x();
785 screenY = _mouse->y();
788 int screenX = _mouse->globalX();
789 int screenY = _mouse->globalY();
793 switch (_mouse->button()) {
800 case Qt::RightButton:
806 bool ctrlKey = (_mouse->state() & Qt::ControlButton);
807 bool altKey = (_mouse->state() & Qt::AltButton);
808 bool shiftKey = (_mouse->state() & Qt::ShiftButton);
809 bool metaKey = false; // ### qt support?
811 EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
812 detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
814 return dispatchEvent(evt,exceptioncode,true);
818 bool NodeImpl::dispatchUIEvent(int _id, int detail)
820 assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
821 _id != EventImpl::DOMFOCUSOUT_EVENT &&
822 _id != EventImpl::DOMACTIVATE_EVENT)));
824 bool cancelable = false;
825 if (_id == EventImpl::DOMACTIVATE_EVENT)
828 int exceptioncode = 0;
829 UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
830 cancelable,getDocument()->defaultView(),detail);
831 return dispatchEvent(evt,exceptioncode,true);
834 bool NodeImpl::dispatchSubtreeModifiedEvent()
837 if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
839 int exceptioncode = 0;
840 return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
841 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
844 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
846 int exceptioncode = 0;
847 //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
848 KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
849 keyboardEventImpl->ref();
850 bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
853 // we want to return false if default is prevented (already taken care of)
854 // or if the element is default-handled by the DOM. Otherwise we let it just
855 // let it get handled by AppKit
856 if (keyboardEventImpl->defaultHandled())
858 // the default event handler should accept() the internal QKeyEvent
859 // to prevent the view from further evaluating it.
860 if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
864 keyboardEventImpl->deref();
868 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
870 if (!m_regdListeners)
873 if (disabled() && evt->isMouseEvent())
876 QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
877 QPtrListIterator<RegisteredEventListener> it(listenersCopy);
879 for (; it.current(); ++it) {
880 if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
881 it.current()->listener->handleEvent(ev, false);
886 void NodeImpl::defaultEventHandler(EventImpl *evt)
890 unsigned long NodeImpl::childNodeCount() const
895 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
900 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
905 return nextSibling();
906 const NodeImpl *n = this;
907 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
910 return n->nextSibling();
914 NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const
917 return nextSibling();
918 const NodeImpl *n = this;
919 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
922 return n->nextSibling();
926 NodeImpl *NodeImpl::traversePreviousNode() const
928 if (previousSibling()) {
929 NodeImpl *n = previousSibling();
930 while (n->lastChild())
934 else if (parentNode()) {
942 NodeImpl *NodeImpl::traversePreviousNodePostOrder(NodeImpl *stayWithin) const
946 if (previousSibling())
947 return previousSibling();
948 const NodeImpl *n = this;
949 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
952 return n->previousSibling();
956 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
958 // Perform error checking as required by spec for setting Node.prefix. Used by
959 // ElementImpl::setPrefix() and AttrImpl::setPrefix()
961 // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
962 if (!Element::khtmlValidPrefix(_prefix)) {
963 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
967 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
969 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
973 // NAMESPACE_ERR: - Raised if the specified prefix is malformed
974 // - if the namespaceURI of this node is null,
975 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
976 // "http://www.w3.org/XML/1998/namespace",
977 // - if this node is an attribute and the specified prefix is "xmlns" and
978 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
979 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
980 if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
981 (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
982 exceptioncode = DOMException::NAMESPACE_ERR;
987 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
989 // Perform error checking as required by spec for adding a new child. Used by
990 // appendChild(), replaceChild() and insertBefore()
992 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
994 exceptioncode = DOMException::NOT_FOUND_ERR;
998 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
1000 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1004 bool shouldAdoptChild = false;
1006 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
1007 // created this node.
1008 // We assume that if newChild is a DocumentFragment, all children are created from the same document
1009 // as the fragment itself (otherwise they could not have been added as children)
1010 if (newChild->getDocument() != getDocument()) {
1011 // but if the child is not in a document yet then loosen the
1012 // restriction, so that e.g. creating an element with the Option()
1013 // constructor and then adding it to a different document works,
1014 // as it does in Mozilla and Mac IE.
1015 if (!newChild->inDocument()) {
1016 shouldAdoptChild = true;
1018 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1023 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1024 // newChild node, or if the node to append is one of this node's ancestors.
1026 // check for ancestor/same node
1027 if (newChild == this || isAncestor(newChild)) {
1028 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1032 // only do this once we know there won't be an exception
1033 if (shouldAdoptChild) {
1034 KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
1035 newChild->setDocument(getDocument()->docPtr());
1039 bool NodeImpl::isAncestor(const NodeImpl *other) const
1041 // Return true if other is an ancestor of this, otherwise false
1042 for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1049 bool NodeImpl::childAllowed( NodeImpl *newChild )
1051 return childTypeAllowed(newChild->nodeType());
1054 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1056 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
1057 // explicit inheritance of non-inherited properties and so you end up not re-resolving
1058 // style in cases where you need to.
1059 StyleChange ch = NoInherit;
1060 EDisplay display1 = s1 ? s1->display() : NONE;
1061 bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1062 EDisplay display2 = s2 ? s2->display() : NONE;
1063 bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1064 if (display1 != display2 || fl1 != fl2)
1066 else if ( !s1 || !s2 )
1068 else if ( *s1 == *s2 )
1070 else if ( s1->inheritedNotEqual( s2 ) )
1076 void NodeImpl::dump(QTextStream *stream, QString ind) const
1078 // ### implement dump() for all appropriate subclasses
1080 if (m_hasId) { *stream << " hasId"; }
1081 if (m_hasClass) { *stream << " hasClass"; }
1082 if (m_hasStyle) { *stream << " hasStyle"; }
1083 if (m_specified) { *stream << " specified"; }
1084 if (m_focused) { *stream << " focused"; }
1085 if (m_active) { *stream << " active"; }
1086 if (m_styleElement) { *stream << " styleElement"; }
1087 if (m_implicit) { *stream << " implicit"; }
1089 *stream << " tabIndex=" << m_tabIndex;
1090 if (m_regdListeners)
1091 *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1094 NodeImpl *child = firstChild();
1097 *stream << ind << child->nodeName().string().ascii() << ": ";
1098 child->dump(stream,ind+" ");
1099 child = child->nextSibling();
1104 void NodeImpl::attach()
1106 assert(!attached());
1107 assert(!m_render || (m_render->style() && m_render->parent()));
1111 void NodeImpl::detach()
1113 // assert(m_attached);
1122 bool NodeImpl::maintainsState()
1127 QString NodeImpl::state()
1129 return QString::null;
1132 void NodeImpl::restoreState(QStringList &/*states*/)
1136 void NodeImpl::insertedIntoDocument()
1138 setInDocument(true);
1141 void NodeImpl::removedFromDocument()
1143 setInDocument(false);
1146 void NodeImpl::childrenChanged()
1150 bool NodeImpl::disabled() const
1155 bool NodeImpl::isReadOnly()
1157 // Entity & Entity Reference nodes and their descendants are read-only
1160 if (n->nodeType() == Node::ENTITY_NODE ||
1161 n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1163 n = n->parentNode();
1168 NodeImpl *NodeImpl::previousEditable() const
1170 NodeImpl *node = previousLeafNode();
1172 if (node->isContentEditable())
1174 node = node->previousLeafNode();
1179 NodeImpl *NodeImpl::nextEditable() const
1181 NodeImpl *node = nextLeafNode();
1183 if (node->isContentEditable())
1185 node = node->nextLeafNode();
1190 RenderObject * NodeImpl::previousRenderer()
1192 for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1194 return n->renderer();
1199 RenderObject * NodeImpl::nextRenderer()
1201 for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1203 return n->renderer();
1208 bool NodeImpl::isAtomicNode() const
1210 return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1213 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1215 if (previousSibling()) {
1216 NodeImpl *n = previousSibling();
1217 while (!n->isAtomicNode() && n->lastChild())
1221 else if (parentNode()) {
1222 return parentNode();
1229 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1231 if (!isAtomicNode() && firstChild())
1232 return firstChild();
1234 return nextSibling();
1235 const NodeImpl *n = this;
1236 while (n && !n->nextSibling())
1237 n = n->parentNode();
1239 return n->nextSibling();
1243 NodeImpl *NodeImpl::previousLeafNode() const
1245 NodeImpl *node = previousNodeConsideringAtomicNodes();
1247 if (node->isAtomicNode())
1249 node = node->previousNodeConsideringAtomicNodes();
1254 NodeImpl *NodeImpl::nextLeafNode() const
1256 NodeImpl *node = nextNodeConsideringAtomicNodes();
1258 if (node->isAtomicNode())
1260 node = node->nextNodeConsideringAtomicNodes();
1265 void NodeImpl::createRendererIfNeeded()
1269 if (!getDocument()->shouldCreateRenderers())
1273 assert(!attached());
1276 NodeImpl *parent = parentNode();
1279 RenderObject *parentRenderer = parent->renderer();
1280 if (parentRenderer && parentRenderer->canHaveChildren()) {
1281 RenderStyle *style = styleForRenderer(parentRenderer);
1283 #ifndef KHTML_NO_XBL
1284 bool resolveStyle = false;
1285 if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
1286 rendererIsNeeded(style)) {
1289 style = styleForRenderer(parentRenderer);
1292 if (rendererIsNeeded(style)) {
1294 m_render = createRenderer(getDocument()->renderArena(), style);
1295 m_render->setStyle(style);
1296 parentRenderer->addChild(m_render, nextRenderer());
1297 #ifndef KHTML_NO_XBL
1298 } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1302 style->deref(getDocument()->renderArena());
1306 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1308 return parent->style();
1311 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1313 return (getDocument()->documentElement() == this) || (style->display() != NONE);
1316 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1322 long NodeImpl::maxOffset() const
1327 long NodeImpl::caretMinOffset() const
1329 return renderer() ? renderer()->caretMinOffset() : 0;
1332 long NodeImpl::caretMaxOffset() const
1334 return renderer() ? renderer()->caretMaxOffset() : 1;
1337 unsigned long NodeImpl::caretMaxRenderedOffset() const
1339 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1342 bool NodeImpl::isBlockFlow() const
1344 return renderer() && renderer()->isBlockFlow();
1347 bool NodeImpl::isEditableBlock() const
1349 return isContentEditable() && isBlockFlow();
1352 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1354 NodeImpl *n = const_cast<NodeImpl *>(this);
1356 return static_cast<ElementImpl *>(n);
1359 n = n->parentNode();
1362 if (n->isBlockFlow() || n->id() == ID_BODY)
1363 return static_cast<ElementImpl *>(n);
1368 ElementImpl *NodeImpl::enclosingInlineElement() const
1370 NodeImpl *n = const_cast<NodeImpl *>(this);
1374 p = n->parentNode();
1375 if (!p || p->isBlockFlow() || p->id() == ID_BODY)
1376 return static_cast<ElementImpl *>(n);
1379 ASSERT_NOT_REACHED();
1383 ElementImpl *NodeImpl::rootEditableElement() const
1385 if (!isContentEditable())
1388 NodeImpl *n = const_cast<NodeImpl *>(this);
1389 if (n->id() == ID_BODY)
1390 return static_cast<ElementImpl *>(n);
1392 NodeImpl *result = n->isEditableBlock() ? n : 0;
1394 n = n->parentNode();
1395 if (!n || !n->isContentEditable())
1397 if (n->id() == ID_BODY) {
1401 if (n->isBlockFlow())
1404 return static_cast<ElementImpl *>(result);
1407 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1409 return n ? rootEditableElement() == n->rootEditableElement() : false;
1412 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1414 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1418 NodeImpl::Id NodeImpl::identifier() const
1425 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1431 if (s.length() == 0)
1436 strncpy(buffer, result.string().latin1(), length - 1);
1440 //-------------------------------------------------------------------------
1442 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1449 NodeBaseImpl::~NodeBaseImpl()
1451 //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1453 // Avoid deep recursion when destroying the node tree.
1454 static bool alreadyInsideDestructor;
1455 bool topLevel = !alreadyInsideDestructor;
1457 alreadyInsideDestructor = true;
1459 // List of nodes to be deleted.
1460 static NodeImpl *head;
1461 static NodeImpl *tail;
1463 // We have to tell all children that their parent has died.
1467 for( n = _first; n != 0; n = next ) {
1468 next = n->nextSibling();
1469 n->setPreviousSibling(0);
1470 n->setNextSibling(0);
1473 if ( !n->refCount() ) {
1474 // Add the node to the list of nodes to be deleted.
1475 // Reuse the nextSibling pointer for this purpose.
1477 tail->setNextSibling(n);
1484 // Only for the top level call, do the actual deleting.
1486 while ((n = head) != 0) {
1487 next = n->nextSibling();
1488 n->setNextSibling(0);
1497 alreadyInsideDestructor = false;
1502 NodeImpl *NodeBaseImpl::firstChild() const
1507 NodeImpl *NodeBaseImpl::lastChild() const
1512 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1516 // insertBefore(...,null) is equivalent to appendChild()
1518 return appendChild(newChild, exceptioncode);
1520 // Make sure adding the new child is ok
1521 checkAddChild(newChild, exceptioncode);
1525 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1526 if (refChild->parentNode() != this) {
1527 exceptioncode = DOMException::NOT_FOUND_ERR;
1531 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1533 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1534 // Just return the document fragment
1535 if (isFragment && !newChild->firstChild())
1538 // Now actually add the child(ren)
1539 NodeImpl *nextChild;
1540 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1542 NodeImpl *prev = refChild->previousSibling();
1543 if ( prev == newChild || refChild == newChild ) // nothing to do
1547 nextChild = isFragment ? child->nextSibling() : 0;
1549 // If child is already present in the tree, first remove it
1550 NodeImpl *newParent = child->parentNode();
1552 newParent->removeChild( child, exceptioncode );
1553 if ( exceptioncode )
1556 // Add child in the correct position
1558 prev->setNextSibling(child);
1561 refChild->setPreviousSibling(child);
1562 child->setParent(this);
1563 child->setPreviousSibling(prev);
1564 child->setNextSibling(refChild);
1566 // Add child to the rendering tree
1567 // ### should we detach() it first if it's already attached?
1568 if (attached() && !child->attached())
1571 // Dispatch the mutation events
1572 dispatchChildInsertedEvents(child,exceptioncode);
1578 getDocument()->setDocumentChanged(true);
1579 dispatchSubtreeModifiedEvent();
1583 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1587 if ( oldChild == newChild ) // nothing to do
1590 // Make sure adding the new child is ok
1591 checkAddChild(newChild, exceptioncode);
1595 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1596 if (!oldChild || oldChild->parentNode() != this) {
1597 exceptioncode = DOMException::NOT_FOUND_ERR;
1601 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1602 NodeImpl *nextChild;
1603 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1606 // Remove the old child
1607 NodeImpl *prev = oldChild->previousSibling();
1608 NodeImpl *next = oldChild->nextSibling();
1610 removeChild(oldChild, exceptioncode);
1614 // Add the new child(ren)
1616 nextChild = isFragment ? child->nextSibling() : 0;
1618 // If child is already present in the tree, first remove it
1619 NodeImpl *newParent = child->parentNode();
1621 newParent->removeChild( child, exceptioncode );
1625 // Add child in the correct position
1626 if (prev) prev->setNextSibling(child);
1627 if (next) next->setPreviousSibling(child);
1628 if(!prev) _first = child;
1629 if(!next) _last = child;
1630 child->setParent(this);
1631 child->setPreviousSibling(prev);
1632 child->setNextSibling(next);
1634 // Add child to the rendering tree
1635 // ### should we detach() it first if it's already attached?
1636 if (attached() && !child->attached())
1639 // Dispatch the mutation events
1640 dispatchChildInsertedEvents(child,exceptioncode);
1646 // ### set style in case it's attached
1647 getDocument()->setDocumentChanged(true);
1648 dispatchSubtreeModifiedEvent();
1652 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1656 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1658 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1662 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1663 if (!oldChild || oldChild->parentNode() != this) {
1664 exceptioncode = DOMException::NOT_FOUND_ERR;
1668 // Dispatch pre-removal mutation events
1669 getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1670 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1671 oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1672 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1677 dispatchChildRemovalEvents(oldChild,exceptioncode);
1681 // Remove from rendering tree
1682 if (oldChild->attached())
1686 NodeImpl *prev, *next;
1687 prev = oldChild->previousSibling();
1688 next = oldChild->nextSibling();
1690 if(next) next->setPreviousSibling(prev);
1691 if(prev) prev->setNextSibling(next);
1692 if(_first == oldChild) _first = next;
1693 if(_last == oldChild) _last = prev;
1695 oldChild->setPreviousSibling(0);
1696 oldChild->setNextSibling(0);
1697 oldChild->setParent(0);
1699 getDocument()->setDocumentChanged(true);
1701 // Dispatch post-removal mutation events
1702 dispatchSubtreeModifiedEvent();
1704 if (oldChild->inDocument())
1705 oldChild->removedFromDocument();
1710 void NodeBaseImpl::removeChildren()
1713 while (NodeImpl *n = _first) {
1714 NodeImpl *next = n->nextSibling();
1718 // Fire removed from document mutation events.
1719 dispatchChildRemovalEvents(n, exceptionCode);
1723 n->setPreviousSibling(0);
1724 n->setNextSibling(0);
1727 if (n->inDocument())
1728 n->removedFromDocument();
1736 // Dispatch a single post-removal mutation event denoting a modified subtree.
1737 dispatchSubtreeModifiedEvent();
1741 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1745 // Make sure adding the new child is ok
1746 checkAddChild(newChild, exceptioncode);
1750 if ( newChild == _last ) // nothing to do
1753 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1755 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1756 // Just return the document fragment
1757 if (isFragment && !newChild->firstChild())
1760 // Now actually add the child(ren)
1761 NodeImpl *nextChild;
1762 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1765 nextChild = isFragment ? child->nextSibling() : 0;
1767 // If child is already present in the tree, first remove it
1768 NodeImpl *oldParent = child->parentNode();
1770 oldParent->removeChild( child, exceptioncode );
1775 // Append child to the end of the list
1776 child->setParent(this);
1780 child->setPreviousSibling(_last);
1781 _last->setNextSibling(child);
1786 _first = _last = child;
1789 // Add child to the rendering tree
1790 // ### should we detach() it first if it's already attached?
1791 if (attached() && !child->attached())
1794 // Dispatch the mutation events
1795 dispatchChildInsertedEvents(child,exceptioncode);
1800 getDocument()->setDocumentChanged(true);
1801 // ### set style in case it's attached
1802 dispatchSubtreeModifiedEvent();
1806 bool NodeBaseImpl::hasChildNodes ( ) const
1811 // not part of the DOM
1812 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1817 void NodeBaseImpl::setLastChild(NodeImpl *child)
1822 // check for same source document:
1823 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1826 DocumentImpl *ownerDocThis = getDocument();
1827 DocumentImpl *ownerDocNew = getDocument();
1828 if(ownerDocThis != ownerDocNew) {
1829 kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1830 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1836 // check for being (grand-..)father:
1837 // ### remove in favor or isAncestor()
1838 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1840 //check if newChild is parent of this...
1842 for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1844 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1850 // check for being child:
1851 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1853 if(!oldChild || oldChild->parentNode() != this) {
1854 exceptioncode = DOMException::NOT_FOUND_ERR;
1860 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1862 // do not add applyChanges here! This function is only used during parsing
1864 // short check for consistency with DTD
1865 if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1867 //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1872 newChild->setParent(this);
1876 newChild->setPreviousSibling(_last);
1877 _last->setNextSibling(newChild);
1882 _first = _last = newChild;
1885 newChild->insertedIntoDocument();
1888 if(newChild->nodeType() == Node::ELEMENT_NODE)
1893 void NodeBaseImpl::attach()
1895 NodeImpl *child = _first;
1899 child = child->nextSibling();
1904 void NodeBaseImpl::detach()
1906 NodeImpl *child = _first;
1909 NodeImpl* prev = child;
1910 child = child->nextSibling();
1916 void NodeBaseImpl::insertedIntoDocument()
1918 NodeImpl::insertedIntoDocument();
1919 for (NodeImpl *child = _first; child; child = child->nextSibling())
1920 child->insertedIntoDocument();
1923 void NodeBaseImpl::removedFromDocument()
1925 NodeImpl::removedFromDocument();
1926 for (NodeImpl *child = _first; child; child = child->nextSibling())
1927 child->removedFromDocument();
1930 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
1932 int exceptioncode = 0;
1934 for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
1936 clone->appendChild(n->cloneNode(true),exceptioncode);
1940 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
1941 DOMStringImpl* localName )
1943 if (!localName) return 0;
1945 NodeImpl::Id idMask = namespaceMask | localNameMask;
1946 if (localName->l && localName->s[0] == '*')
1947 idMask &= ~localNameMask;
1948 if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
1949 idMask &= ~namespaceMask;
1951 Id id = 0; // 0 means "all items"
1952 if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
1954 id = getDocument()->tagId( namespaceURI, localName, true);
1955 if ( !id ) // not found -> we want to return an empty list, not "all items"
1956 id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
1959 return new TagNodeListImpl( this, id, idMask );
1962 // I don't like this way of implementing the method, but I didn't find any
1964 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
1968 RenderObject *o = m_render;
1970 if ( !o->isInline() || o->isReplaced() ) {
1971 o->absolutePosition( xPos, yPos );
1975 // find the next text/image child, to get a position
1978 o = o->firstChild();
1979 else if(o->nextSibling())
1980 o = o->nextSibling();
1982 RenderObject *next = 0;
1985 if(!o) return false;
1986 next = o->nextSibling();
1990 if((o->isText() && !o->isBR()) || o->isReplaced()) {
1991 o->container()->absolutePosition( xPos, yPos );
1993 xPos += static_cast<RenderText *>(o)->minXPos();
2003 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2008 RenderObject *o = m_render;
2010 if (!o->isInline() || o->isReplaced())
2012 o->absolutePosition( xPos, yPos );
2014 yPos += o->height();
2017 // find the last text/image child, to get a position
2021 else if(o->previousSibling())
2022 o = o->previousSibling();
2024 RenderObject *prev = 0;
2027 if(!o) return false;
2028 prev = o->previousSibling();
2032 if(o->isText() || o->isReplaced()) {
2033 o->container()->absolutePosition(xPos, yPos);
2035 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2037 xPos += o->xPos()+o->width();
2038 yPos += o->yPos()+o->height();
2045 QRect NodeBaseImpl::getRect() const
2048 if (!getUpperLeftCorner(xPos,yPos))
2054 if (!getLowerRightCorner(xEnd,yEnd))
2068 if ( xEnd <= xPos || yEnd <= yPos )
2069 return QRect( QPoint( xPos, yPos ), QSize() );
2071 return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2074 void NodeBaseImpl::setFocus(bool received)
2076 if (m_focused == received) return;
2078 NodeImpl::setFocus(received);
2080 if (received && isEditableBlock() && !hasChildNodes()) {
2081 getDocument()->part()->setSelection(Position(this, 0));
2084 // note that we need to recalc the style
2088 void NodeBaseImpl::setActive(bool down)
2090 if (down == active()) return;
2092 NodeImpl::setActive(down);
2094 // note that we need to recalc the style
2095 if (m_render && m_render->style()->affectedByActiveRules())
2099 unsigned long NodeBaseImpl::childNodeCount() const
2101 unsigned long count = 0;
2103 for (n = firstChild(); n; n = n->nextSibling())
2108 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2111 NodeImpl *n = firstChild();
2112 for (i = 0; i < index; i++)
2113 n = n->nextSibling();
2117 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2119 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2120 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2121 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2126 // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2127 bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2129 while (p->parentNode())
2130 p = p->parentNode();
2131 if (p->nodeType() == Node::DOCUMENT_NODE) {
2132 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2133 c->insertedIntoDocument();
2135 if (hasInsertedListeners) {
2136 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2137 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2145 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2147 // Dispatch pre-removal mutation events
2148 getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2149 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2150 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2151 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2156 bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2158 // dispatch the DOMNOdeRemovedFromDocument event to all descendants
2160 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2161 if (hasRemovalListeners) {
2162 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2163 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2171 // ---------------------------------------------------------------------------
2173 NodeImpl *NodeListImpl::item( unsigned long /*index*/ ) const
2178 unsigned long NodeListImpl::length() const
2183 unsigned long NodeListImpl::recursiveLength(NodeImpl *start) const
2185 unsigned long len = 0;
2187 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2188 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2191 len+= recursiveLength(n);
2198 NodeImpl *NodeListImpl::recursiveItem ( NodeImpl *start, unsigned long &offset ) const
2200 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2201 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2206 NodeImpl *depthSearch= recursiveItem(n, offset);
2212 return 0; // no matching node in this subtree
2215 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2221 ChildNodeListImpl::~ChildNodeListImpl()
2226 unsigned long ChildNodeListImpl::length() const
2228 unsigned long len = 0;
2230 for(n = refNode->firstChild(); n != 0; n = n->nextSibling())
2236 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2238 unsigned int pos = 0;
2239 NodeImpl *n = refNode->firstChild();
2241 while( n != 0 && pos < index )
2243 n = n->nextSibling();
2250 bool ChildNodeListImpl::nodeMatches( NodeImpl */*testNode*/ ) const
2255 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2256 : refNode(n), m_id(_id & _idMask), m_idMask(_idMask)
2261 TagNodeListImpl::~TagNodeListImpl()
2266 unsigned long TagNodeListImpl::length() const
2268 return recursiveLength( refNode );
2271 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2273 return recursiveItem( refNode, index );
2276 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2278 return ( testNode->isElementNode() &&
2279 (testNode->id() & m_idMask) == m_id);
2282 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2289 NameNodeListImpl::~NameNodeListImpl()
2294 unsigned long NameNodeListImpl::length() const
2296 return recursiveLength( refNode );
2299 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2301 return recursiveItem( refNode, index );
2304 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2306 return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2309 // ---------------------------------------------------------------------------
2311 NamedNodeMapImpl::NamedNodeMapImpl()
2315 NamedNodeMapImpl::~NamedNodeMapImpl()
2319 // ----------------------------------------------------------------------------
2323 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2324 : NamedNodeMapImpl()
2326 m_doc = doc->document();
2327 m_contents = new QPtrList<NodeImpl>;
2330 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2332 while (m_contents->count() > 0)
2333 m_contents->take(0)->deref();
2338 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2340 QPtrListIterator<NodeImpl> it(*m_contents);
2341 for (; it.current(); ++it)
2342 if (it.current()->nodeName() == name)
2343 return it.current();
2347 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2349 // can't modify this list through standard DOM functions
2350 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2351 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2355 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2357 // can't modify this list through standard DOM functions
2358 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2359 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2363 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2365 // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2366 // (also for other similar methods)
2367 if (index >= m_contents->count())
2370 return m_contents->at(index);
2373 unsigned long GenericRONamedNodeMapImpl::length( ) const
2375 return m_contents->count();
2378 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2379 const DOMString &localName,
2380 int &/*exceptioncode*/ ) const
2382 NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2383 localName.implementation(), true);
2385 QPtrListIterator<NodeImpl> it(*m_contents);
2386 for (; it.current(); ++it)
2387 if (it.current()->id() == searchId)
2388 return it.current();
2393 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2395 // can't modify this list through standard DOM functions
2396 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2397 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2401 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2402 const DOMString &/*localName*/,
2403 int &exceptioncode )
2405 // can't modify this list through standard DOM functions
2406 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2410 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2412 // The spec says that in the case of duplicates we only keep the first one
2413 int exceptioncode = 0;
2414 if (getNamedItem(n->nodeName(),exceptioncode))
2418 m_contents->append(n);