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/html_interchange.h"
39 #include "editing/selection.h"
44 #include "rendering/render_object.h"
45 #include "rendering/render_text.h"
47 #include "ecma/kjs_binding.h"
48 #include "ecma/kjs_proxy.h"
49 #include "khtmlview.h"
50 #include "khtml_part.h"
55 #include "xbl/xbl_binding_manager.h"
59 #include "KWQAssertions.h"
60 #include "KWQLogging.h"
62 #define ASSERT(assertion) assert(assertion)
63 #define LOG(channel, formatAndArgs...) ((void)0)
67 using namespace khtml;
69 NodeImpl::NodeImpl(DocumentPtr *doc)
82 m_hasChangedChild( false ),
83 m_inDocument( false ),
88 m_styleElement( false ),
95 void NodeImpl::setDocument(DocumentPtr *doc)
109 NodeImpl::~NodeImpl()
113 delete m_regdListeners;
118 m_previous->setNextSibling(0);
120 m_next->setPreviousSibling(0);
123 DOMString NodeImpl::nodeValue() const
128 void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode )
130 // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
132 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
136 // be default nodeValue is null, so setting it has no effect
139 DOMString NodeImpl::nodeName() const
144 unsigned short NodeImpl::nodeType() const
149 NodeListImpl *NodeImpl::childNodes()
151 return new ChildNodeListImpl(this);
154 NodeImpl *NodeImpl::firstChild() const
159 NodeImpl *NodeImpl::lastChild() const
164 NodeImpl *NodeImpl::lastDescendent() const
166 NodeImpl *n = const_cast<NodeImpl *>(this);
167 while (n && n->lastChild())
172 NodeImpl *NodeImpl::insertBefore( NodeImpl *newChild, NodeImpl *, int &exceptioncode )
176 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
180 NodeImpl *NodeImpl::replaceChild( NodeImpl *newChild, NodeImpl *, int &exceptioncode )
184 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
188 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
190 exceptioncode = DOMException::NOT_FOUND_ERR;
194 NodeImpl *NodeImpl::appendChild( NodeImpl *newChild, int &exceptioncode )
198 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
202 void NodeImpl::remove(int &exceptioncode)
206 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
210 parentNode()->removeChild(this, exceptioncode);
213 bool NodeImpl::hasChildNodes( ) const
218 void NodeImpl::normalize ()
220 // ### normalize attributes? (when we store attributes using child nodes)
221 int exceptioncode = 0;
222 NodeImpl *child = firstChild();
224 // Recursively go through the subtree beneath us, normalizing all nodes. In the case
225 // where there are two adjacent text nodes, they are merged together
227 NodeImpl *nextChild = child->nextSibling();
229 if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
230 // Current child and the next one are both text nodes... merge them
231 TextImpl *currentText = static_cast<TextImpl*>(child);
232 TextImpl *nextText = static_cast<TextImpl*>(nextChild);
234 currentText->appendData(nextText->data(),exceptioncode);
238 removeChild(nextChild,exceptioncode);
249 DOMString NodeImpl::prefix() const
251 // For nodes other than elements and attributes, the prefix is always null
255 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
257 // The spec says that for nodes other than elements and attributes, prefix is always null.
258 // It does not say what to do when the user tries to set the prefix on another type of
259 // node, however mozilla throws a NAMESPACE_ERR exception
260 exceptioncode = DOMException::NAMESPACE_ERR;
263 DOMString NodeImpl::localName() const
268 void NodeImpl::setFirstChild(NodeImpl *)
272 void NodeImpl::setLastChild(NodeImpl *)
276 NodeImpl *NodeImpl::addChild(NodeImpl *)
281 bool NodeImpl::isContentEditable() const
283 return m_parent ? m_parent->isContentEditable() : false;
286 QRect NodeImpl::getRect() const
289 if(m_render && m_render->absolutePosition(_x, _y))
290 return QRect( _x, _y, m_render->width(), m_render->height() );
295 void NodeImpl::setChanged(bool b)
297 if (b && !attached()) // changed compared to what?
302 NodeImpl *p = parentNode();
304 p->setHasChangedChild( true );
307 getDocument()->setDocumentChanged(true);
311 bool NodeImpl::isInline() const
313 if (m_render) return m_render->style()->display() == khtml::INLINE;
314 return !isElementNode();
317 bool NodeImpl::isFocusable() const
322 bool NodeImpl::isKeyboardFocusable() const
324 return isFocusable();
327 bool NodeImpl::isMouseFocusable() const
329 return isFocusable();
332 unsigned long NodeImpl::nodeIndex() const
334 NodeImpl *_tempNode = previousSibling();
335 unsigned long count=0;
336 for( count=0; _tempNode; count++ )
337 _tempNode = _tempNode->previousSibling();
341 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
344 case EventImpl::DOMSUBTREEMODIFIED_EVENT:
345 getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
347 case EventImpl::DOMNODEINSERTED_EVENT:
348 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
350 case EventImpl::DOMNODEREMOVED_EVENT:
351 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
353 case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
354 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
356 case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
357 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
359 case EventImpl::DOMATTRMODIFIED_EVENT:
360 getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
362 case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
363 getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
369 RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
370 if (!m_regdListeners) {
371 m_regdListeners = new QPtrList<RegisteredEventListener>;
372 m_regdListeners->setAutoDelete(true);
377 // remove existing identical listener set with identical arguments - the DOM2
378 // spec says that "duplicate instances are discarded" in this case.
379 removeEventListener(id,listener,useCapture);
381 m_regdListeners->append(rl);
385 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
387 if (!m_regdListeners) // nothing to remove
390 RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
392 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
393 for (; it.current(); ++it)
394 if (*(it.current()) == rl) {
395 m_regdListeners->removeRef(it.current());
400 void NodeImpl::removeHTMLEventListener(int id)
402 if (!m_regdListeners) // nothing to remove
405 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
406 for (; it.current(); ++it)
407 if (it.current()->id == id &&
408 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
409 m_regdListeners->removeRef(it.current());
414 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
416 // in case we already have it, we don't want removeHTMLEventListener to destroy it
419 removeHTMLEventListener(id);
422 addEventListener(id,listener,false);
427 EventListener *NodeImpl::getHTMLEventListener(int id)
429 if (!m_regdListeners)
432 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
433 for (; it.current(); ++it)
434 if (it.current()->id == id &&
435 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
436 return it.current()->listener;
442 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
446 evt->setTarget(this);
448 // We've had at least one report of a crash on a page where document is nil here.
449 // Unfortunately that page no longer exists, but we'll make this code robust against
451 // FIXME: Much code in this class assumes document is non-nil; it would be better to
452 // ensure that document can never be nil.
453 KHTMLPart *part = nil;
454 KHTMLView *view = nil;
456 if (document && document->document()) {
457 part = document->document()->part();
458 view = document->document()->view();
459 // Since event handling code could cause this object to be deleted, grab a reference to the view now
464 bool ret = dispatchGenericEvent( evt, exceptioncode );
466 // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
467 // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
468 // So there is no need for the interpreter to keep the event in it's cache
469 if (tempEvent && part && part->jScript())
470 part->jScript()->finishedWithEvent(evt);
480 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
484 // ### check that type specified
486 // work out what nodes to send event to
487 QPtrList<NodeImpl> nodeChain;
489 for (n = this; n; n = n->parentNode()) {
491 nodeChain.prepend(n);
494 // trigger any capturing event handlers on our way down
495 evt->setEventPhase(Event::CAPTURING_PHASE);
496 QPtrListIterator<NodeImpl> it(nodeChain);
497 for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
498 evt->setCurrentTarget(it.current());
499 it.current()->handleLocalEvents(evt,true);
502 // dispatch to the actual target node
504 if (!evt->propagationStopped()) {
505 evt->setEventPhase(Event::AT_TARGET);
506 evt->setCurrentTarget(it.current());
508 // Capturing first. -dwh
509 it.current()->handleLocalEvents(evt,true);
511 // Bubbling second. -dwh
512 if (!evt->propagationStopped())
513 it.current()->handleLocalEvents(evt,false);
517 // ok, now bubble up again (only non-capturing event handlers will be called)
518 // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
519 // no. the DOM specs says:
520 // The chain of EventTargets from the event target to the top of the tree
521 // is determined before the initial dispatch of the event.
522 // If modifications occur to the tree during event processing,
523 // event flow will proceed based on the initial state of the tree.
525 // since the initial dispatch is before the capturing phase,
526 // there's no need to recalculate the node chain.
529 if (evt->bubbles()) {
530 evt->setEventPhase(Event::BUBBLING_PHASE);
531 for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
532 evt->setCurrentTarget(it.current());
533 it.current()->handleLocalEvents(evt,false);
537 evt->setCurrentTarget(0);
538 evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
539 // anything about the default event handler phase.
542 if (evt->bubbles()) {
543 // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
546 for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
547 it.current()->defaultEventHandler(evt);
550 // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions
551 // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or
552 // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code.
553 if (!evt->defaultPrevented() && !disabled())
554 if (evt->id() == EventImpl::KHTML_CLICK_EVENT)
555 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1);
556 else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT)
557 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2);
559 // deref all nodes in chain
561 for (; it.current(); ++it)
562 it.current()->deref(); // this may delete us
564 DocumentImpl::updateDocumentsRendering();
566 bool defaultPrevented = evt->defaultPrevented();
570 return !defaultPrevented; // ### what if defaultPrevented was called before dispatchEvent?
573 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
575 int exceptioncode = 0;
576 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
577 return dispatchEvent(evt,exceptioncode,true);
580 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
582 int exceptioncode = 0;
583 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
586 DocumentPtr *doc = document;
588 bool r = dispatchGenericEvent( evt, exceptioncode );
589 if (!evt->defaultPrevented() && doc->document())
590 doc->document()->defaultEventHandler(evt);
592 if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
593 // For onload events, send them to the enclosing frame only.
594 // This is a DOM extension and is independent of bubbling/capturing rules of
595 // the DOM. You send the event only to the enclosing frame. It does not
596 // bubble through the parent document.
597 ElementImpl* elt = doc->document()->ownerElement();
598 if (elt && (elt->getDocument()->domain().isNull() ||
599 elt->getDocument()->domain() == doc->document()->domain())) {
600 // We also do a security check, since we don't want to allow the enclosing
601 // iframe to see loads of child documents in other domains.
602 evt->setCurrentTarget(elt);
605 elt->handleLocalEvents(evt,true);
608 if (!evt->propagationStopped())
609 elt->handleLocalEvents(evt,false);
610 r = !evt->defaultPrevented();
620 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
622 bool cancelable = true;
623 int detail = overrideDetail; // defaults to 0
624 EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
626 evtId = static_cast<EventImpl::EventId>(overrideId);
629 switch (_mouse->type()) {
630 case QEvent::MouseButtonPress:
631 evtId = EventImpl::MOUSEDOWN_EVENT;
633 case QEvent::MouseButtonRelease:
634 evtId = EventImpl::MOUSEUP_EVENT;
636 case QEvent::MouseButtonDblClick:
637 evtId = EventImpl::CLICK_EVENT;
638 detail = 1; // ### support for multiple double clicks
640 case QEvent::MouseMove:
641 evtId = EventImpl::MOUSEMOVE_EVENT;
648 if (evtId == EventImpl::UNKNOWN_EVENT)
649 return false; // shouldn't happen
652 int exceptioncode = 0;
655 // Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
656 // our khtmlview's coord system. This works for QMouseEvents coming from Cocoa because those events
657 // hold the location from the NSEvent. The QMouseEvent param here was made by other khtml code, so it
658 // will be a "proper" QT event with coords in terms of this widget. So in WebCore it would never be
659 // right to pass coords from _mouse to viewportToContents().
661 // int clientX, clientY;
662 // viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
663 int clientX = _mouse->x(); // ### adjust to be relative to view
664 int clientY = _mouse->y(); // ### adjust to be relative to view
669 KHTMLView *view = document->document()->view();
671 // This gets us as far as NSWindow coords
672 QPoint windowLoc = view->contentsToViewport(_mouse->pos());
673 // Then from NSWindow coords to screen coords
674 QPoint screenLoc = view->viewportToGlobal(windowLoc);
675 screenX = screenLoc.x();
676 screenY = screenLoc.y();
678 screenX = _mouse->x();
679 screenY = _mouse->y();
682 int screenX = _mouse->globalX();
683 int screenY = _mouse->globalY();
687 switch (_mouse->button()) {
694 case Qt::RightButton:
700 bool ctrlKey = (_mouse->state() & Qt::ControlButton);
701 bool altKey = (_mouse->state() & Qt::AltButton);
702 bool shiftKey = (_mouse->state() & Qt::ShiftButton);
703 bool metaKey = false; // ### qt support?
705 EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
706 detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
708 return dispatchEvent(evt,exceptioncode,true);
712 bool NodeImpl::dispatchUIEvent(int _id, int detail)
714 assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
715 _id != EventImpl::DOMFOCUSOUT_EVENT &&
716 _id != EventImpl::DOMACTIVATE_EVENT)));
718 bool cancelable = false;
719 if (_id == EventImpl::DOMACTIVATE_EVENT)
722 int exceptioncode = 0;
723 UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
724 cancelable,getDocument()->defaultView(),detail);
725 return dispatchEvent(evt,exceptioncode,true);
728 void NodeImpl::registerNodeList(NodeListImpl *list)
731 m_nodeLists = new QPtrDict<NodeListImpl>;
734 m_nodeLists->insert(list, list);
737 void NodeImpl::unregisterNodeList(NodeListImpl *list)
742 m_nodeLists->remove(list);
745 void NodeImpl::notifyLocalNodeListsSubtreeModified()
750 QPtrDictIterator<NodeListImpl> i(*m_nodeLists);
752 while (NodeListImpl *list = i.current()) {
753 list->rootNodeSubtreeModified();
758 void NodeImpl::notifyNodeListsSubtreeModified()
760 for (NodeImpl *n = this; n; n = n->parentNode()) {
761 n->notifyLocalNodeListsSubtreeModified();
765 bool NodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged)
767 notifyNodeListsSubtreeModified();
768 if (sendChildrenChanged)
770 if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
772 int exceptioncode = 0;
773 return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
774 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
777 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
779 int exceptioncode = 0;
780 //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
781 KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
782 keyboardEventImpl->ref();
783 bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
786 // we want to return false if default is prevented (already taken care of)
787 // or if the element is default-handled by the DOM. Otherwise we let it just
788 // let it get handled by AppKit
789 if (keyboardEventImpl->defaultHandled())
791 // the default event handler should accept() the internal QKeyEvent
792 // to prevent the view from further evaluating it.
793 if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
797 keyboardEventImpl->deref();
801 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
803 if (!m_regdListeners)
806 if (disabled() && evt->isMouseEvent())
809 QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
810 QPtrListIterator<RegisteredEventListener> it(listenersCopy);
812 for (; it.current(); ++it) {
813 if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
814 it.current()->listener->handleEvent(ev, false);
819 void NodeImpl::defaultEventHandler(EventImpl *evt)
823 unsigned long NodeImpl::childNodeCount() const
828 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
833 NodeImpl *NodeImpl::traverseNextNode(const NodeImpl *stayWithin) const
836 assert(!stayWithin || firstChild()->isAncestor(stayWithin));
839 if (this == stayWithin)
842 assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
843 return nextSibling();
845 const NodeImpl *n = this;
846 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
849 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
850 return n->nextSibling();
855 NodeImpl *NodeImpl::traverseNextSibling(const NodeImpl *stayWithin) const
857 if (this == stayWithin)
860 assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
861 return nextSibling();
863 const NodeImpl *n = this;
864 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
867 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
868 return n->nextSibling();
873 NodeImpl *NodeImpl::traversePreviousNode() const
875 if (previousSibling()) {
876 NodeImpl *n = previousSibling();
877 while (n->lastChild())
881 else if (parentNode()) {
889 NodeImpl *NodeImpl::traversePreviousNodePostOrder(const NodeImpl *stayWithin) const
892 assert(!stayWithin || lastChild()->isAncestor(stayWithin));
895 if (this == stayWithin)
897 if (previousSibling()) {
898 assert(!stayWithin || previousSibling()->isAncestor(stayWithin));
899 return previousSibling();
901 const NodeImpl *n = this;
902 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
905 assert(!stayWithin || !n->previousSibling() || n->previousSibling()->isAncestor(stayWithin));
906 return n->previousSibling();
911 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
913 // Perform error checking as required by spec for setting Node.prefix. Used by
914 // ElementImpl::setPrefix() and AttrImpl::setPrefix()
916 // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
917 if (!Element::khtmlValidPrefix(_prefix)) {
918 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
922 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
924 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
928 // NAMESPACE_ERR: - Raised if the specified prefix is malformed
929 // - if the namespaceURI of this node is null,
930 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
931 // "http://www.w3.org/XML/1998/namespace",
932 // - if this node is an attribute and the specified prefix is "xmlns" and
933 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
934 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
935 if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
936 (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
937 exceptioncode = DOMException::NAMESPACE_ERR;
942 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
944 // Perform error checking as required by spec for adding a new child. Used by
945 // appendChild(), replaceChild() and insertBefore()
947 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
949 exceptioncode = DOMException::NOT_FOUND_ERR;
953 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
955 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
959 bool shouldAdoptChild = false;
961 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
962 // created this node.
963 // We assume that if newChild is a DocumentFragment, all children are created from the same document
964 // as the fragment itself (otherwise they could not have been added as children)
965 if (newChild->getDocument() != getDocument()) {
966 // but if the child is not in a document yet then loosen the
967 // restriction, so that e.g. creating an element with the Option()
968 // constructor and then adding it to a different document works,
969 // as it does in Mozilla and Mac IE.
970 if (!newChild->inDocument()) {
971 shouldAdoptChild = true;
973 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
978 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
979 // newChild node, or if the node to append is one of this node's ancestors.
981 // check for ancestor/same node
982 if (newChild == this || isAncestor(newChild)) {
983 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
987 // only do this once we know there won't be an exception
988 if (shouldAdoptChild) {
989 KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
990 newChild->setDocument(getDocument()->docPtr());
994 bool NodeImpl::isAncestor(const NodeImpl *other) const
996 // Return true if other is an ancestor of this, otherwise false
997 for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1004 bool NodeImpl::childAllowed( NodeImpl *newChild )
1006 return childTypeAllowed(newChild->nodeType());
1009 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1011 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
1012 // explicit inheritance of non-inherited properties and so you end up not re-resolving
1013 // style in cases where you need to.
1014 StyleChange ch = NoInherit;
1015 EDisplay display1 = s1 ? s1->display() : NONE;
1016 bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1017 EDisplay display2 = s2 ? s2->display() : NONE;
1018 bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1019 if (display1 != display2 || fl1 != fl2)
1021 else if ( !s1 || !s2 )
1023 else if ( *s1 == *s2 )
1025 else if ( s1->inheritedNotEqual( s2 ) )
1031 void NodeImpl::dump(QTextStream *stream, QString ind) const
1033 // ### implement dump() for all appropriate subclasses
1035 if (m_hasId) { *stream << " hasId"; }
1036 if (m_hasClass) { *stream << " hasClass"; }
1037 if (m_hasStyle) { *stream << " hasStyle"; }
1038 if (m_specified) { *stream << " specified"; }
1039 if (m_focused) { *stream << " focused"; }
1040 if (m_active) { *stream << " active"; }
1041 if (m_styleElement) { *stream << " styleElement"; }
1042 if (m_implicit) { *stream << " implicit"; }
1044 *stream << " tabIndex=" << m_tabIndex;
1045 if (m_regdListeners)
1046 *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1049 NodeImpl *child = firstChild();
1052 *stream << ind << child->nodeName().string().ascii() << ": ";
1053 child->dump(stream,ind+" ");
1054 child = child->nextSibling();
1059 void NodeImpl::attach()
1061 assert(!attached());
1062 assert(!m_render || (m_render->style() && m_render->parent()));
1063 getDocument()->incDOMTreeVersion();
1067 void NodeImpl::detach()
1069 // assert(m_attached);
1075 DocumentImpl *doc = getDocument();
1077 doc->incDOMTreeVersion();
1081 bool NodeImpl::maintainsState()
1086 QString NodeImpl::state()
1088 return QString::null;
1091 void NodeImpl::restoreState(QStringList &/*states*/)
1095 void NodeImpl::insertedIntoDocument()
1097 setInDocument(true);
1100 void NodeImpl::removedFromDocument()
1102 setInDocument(false);
1105 void NodeImpl::childrenChanged()
1109 bool NodeImpl::disabled() const
1114 bool NodeImpl::isReadOnly()
1116 // Entity & Entity Reference nodes and their descendants are read-only
1119 if (n->nodeType() == Node::ENTITY_NODE ||
1120 n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1122 n = n->parentNode();
1127 NodeImpl *NodeImpl::previousEditable() const
1129 NodeImpl *node = previousLeafNode();
1131 if (node->isContentEditable())
1133 node = node->previousLeafNode();
1138 NodeImpl *NodeImpl::nextEditable() const
1140 NodeImpl *node = nextLeafNode();
1142 if (node->isContentEditable())
1144 node = node->nextLeafNode();
1149 RenderObject * NodeImpl::previousRenderer()
1151 for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1153 return n->renderer();
1158 RenderObject * NodeImpl::nextRenderer()
1160 for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1162 return n->renderer();
1167 bool NodeImpl::isAtomicNode() const
1169 return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1172 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1174 if (previousSibling()) {
1175 NodeImpl *n = previousSibling();
1176 while (!n->isAtomicNode() && n->lastChild())
1180 else if (parentNode()) {
1181 return parentNode();
1188 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1190 if (!isAtomicNode() && firstChild())
1191 return firstChild();
1193 return nextSibling();
1194 const NodeImpl *n = this;
1195 while (n && !n->nextSibling())
1196 n = n->parentNode();
1198 return n->nextSibling();
1202 NodeImpl *NodeImpl::previousLeafNode() const
1204 NodeImpl *node = previousNodeConsideringAtomicNodes();
1206 if (node->isAtomicNode())
1208 node = node->previousNodeConsideringAtomicNodes();
1213 NodeImpl *NodeImpl::nextLeafNode() const
1215 NodeImpl *node = nextNodeConsideringAtomicNodes();
1217 if (node->isAtomicNode())
1219 node = node->nextNodeConsideringAtomicNodes();
1224 void NodeImpl::createRendererIfNeeded()
1228 if (!getDocument()->shouldCreateRenderers())
1232 assert(!attached());
1235 NodeImpl *parent = parentNode();
1238 RenderObject *parentRenderer = parent->renderer();
1239 if (parentRenderer && parentRenderer->canHaveChildren()) {
1240 RenderStyle *style = styleForRenderer(parentRenderer);
1242 #ifndef KHTML_NO_XBL
1243 bool resolveStyle = false;
1244 if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
1245 rendererIsNeeded(style)) {
1248 style = styleForRenderer(parentRenderer);
1251 if (rendererIsNeeded(style)) {
1253 m_render = createRenderer(getDocument()->renderArena(), style);
1254 m_render->setStyle(style);
1255 parentRenderer->addChild(m_render, nextRenderer());
1256 #ifndef KHTML_NO_XBL
1257 } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1261 style->deref(getDocument()->renderArena());
1265 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1267 return parent->style();
1270 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1272 return (getDocument()->documentElement() == this) || (style->display() != NONE);
1275 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1281 long NodeImpl::maxOffset() const
1286 long NodeImpl::caretMinOffset() const
1288 return renderer() ? renderer()->caretMinOffset() : 0;
1291 long NodeImpl::caretMaxOffset() const
1293 return renderer() ? renderer()->caretMaxOffset() : 1;
1296 unsigned long NodeImpl::caretMaxRenderedOffset() const
1298 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1301 long NodeImpl::previousOffset (long current) const
1303 return renderer() ? renderer()->previousOffset(current) : current - 1;
1306 long NodeImpl::nextOffset (long current) const
1308 return renderer() ? renderer()->nextOffset(current) : current + 1;
1311 bool NodeImpl::isBlockFlow() const
1313 return renderer() && renderer()->isBlockFlow();
1316 bool NodeImpl::isEditableBlock() const
1318 return isContentEditable() && isBlockFlow();
1321 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1323 NodeImpl *n = const_cast<NodeImpl *>(this);
1325 return static_cast<ElementImpl *>(n);
1328 n = n->parentNode();
1331 if (n->isBlockFlow() || n->id() == ID_BODY)
1332 return static_cast<ElementImpl *>(n);
1337 ElementImpl *NodeImpl::enclosingInlineElement() const
1339 NodeImpl *n = const_cast<NodeImpl *>(this);
1343 p = n->parentNode();
1344 if (!p || p->isBlockFlow() || p->id() == ID_BODY)
1345 return static_cast<ElementImpl *>(n);
1346 // Also stop if any previous sibling is a block
1347 for (NodeImpl *sibling = n->previousSibling(); sibling; sibling = sibling->previousSibling()) {
1348 if (sibling->isBlockFlow())
1349 return static_cast<ElementImpl *>(n);
1353 ASSERT_NOT_REACHED();
1357 ElementImpl *NodeImpl::rootEditableElement() const
1359 if (!isContentEditable())
1362 NodeImpl *n = const_cast<NodeImpl *>(this);
1363 if (n->id() == ID_BODY)
1364 return static_cast<ElementImpl *>(n);
1366 NodeImpl *result = n->isEditableBlock() ? n : 0;
1368 n = n->parentNode();
1369 if (!n || !n->isContentEditable())
1371 if (n->id() == ID_BODY) {
1375 if (n->isBlockFlow())
1378 return static_cast<ElementImpl *>(result);
1381 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1383 return n ? rootEditableElement() == n->rootEditableElement() : false;
1386 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1388 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1392 NodeImpl::Id NodeImpl::identifier() const
1399 void NodeImpl::displayNode(const char *prefix)
1404 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().string().latin1(), this, nodeValue().string().latin1());
1406 fprintf(stderr, "%s%s\t%p\n", prefix, nodeName().string().latin1(), this);
1409 void NodeImpl::displayTree()
1411 NodeImpl *rootNode = rootEditableElement() ? : this;
1414 for (node = rootNode; node; node = node->traverseNextNode()) {
1417 fprintf(stderr, "*");
1418 for (tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
1419 fprintf(stderr, "\t");
1420 node->displayNode(0);
1424 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1430 if (s.length() == 0)
1435 strncpy(buffer, result.string().latin1(), length - 1);
1439 //-------------------------------------------------------------------------
1441 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1448 NodeBaseImpl::~NodeBaseImpl()
1450 //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1452 // Avoid deep recursion when destroying the node tree.
1453 static bool alreadyInsideDestructor;
1454 bool topLevel = !alreadyInsideDestructor;
1456 alreadyInsideDestructor = true;
1458 // List of nodes to be deleted.
1459 static NodeImpl *head;
1460 static NodeImpl *tail;
1462 // We have to tell all children that their parent has died.
1466 for( n = _first; n != 0; n = next ) {
1467 next = n->nextSibling();
1468 n->setPreviousSibling(0);
1469 n->setNextSibling(0);
1472 if ( !n->refCount() ) {
1473 // Add the node to the list of nodes to be deleted.
1474 // Reuse the nextSibling pointer for this purpose.
1476 tail->setNextSibling(n);
1483 // Only for the top level call, do the actual deleting.
1485 while ((n = head) != 0) {
1486 next = n->nextSibling();
1487 n->setNextSibling(0);
1496 alreadyInsideDestructor = false;
1501 NodeImpl *NodeBaseImpl::firstChild() const
1506 NodeImpl *NodeBaseImpl::lastChild() const
1511 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1515 // insertBefore(...,null) is equivalent to appendChild()
1517 return appendChild(newChild, exceptioncode);
1519 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1521 // Make sure adding the new child is ok
1522 checkAddChild(newChild, exceptioncode);
1526 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1527 if (refChild->parentNode() != this) {
1528 exceptioncode = DOMException::NOT_FOUND_ERR;
1532 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1534 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1535 // Just return the document fragment
1536 if (isFragment && !newChild->firstChild())
1537 return (newChild->hasOneRef() && !newChild->parent()) ? 0 : newChild;
1539 // Now actually add the child(ren)
1540 NodeImpl *nextChild;
1541 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1543 NodeImpl *prev = refChild->previousSibling();
1544 if ( prev == newChild || refChild == newChild ) // nothing to do
1548 nextChild = isFragment ? child->nextSibling() : 0;
1550 // If child is already present in the tree, first remove it
1551 NodeImpl *newParent = child->parentNode();
1553 newParent->removeChild( child, exceptioncode );
1554 if ( exceptioncode )
1557 // Add child in the correct position
1559 prev->setNextSibling(child);
1562 refChild->setPreviousSibling(child);
1563 child->setParent(this);
1564 child->setPreviousSibling(prev);
1565 child->setNextSibling(refChild);
1567 // Add child to the rendering tree
1568 // ### should we detach() it first if it's already attached?
1569 if (attached() && !child->attached())
1572 // Dispatch the mutation events
1573 dispatchChildInsertedEvents(child,exceptioncode);
1579 getDocument()->setDocumentChanged(true);
1580 dispatchSubtreeModifiedEvent();
1584 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1588 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1590 if ( oldChild == newChild ) // nothing to do
1593 // Make sure adding the new child is ok
1594 checkAddChild(newChild, exceptioncode);
1598 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1599 if (!oldChild || oldChild->parentNode() != this) {
1600 exceptioncode = DOMException::NOT_FOUND_ERR;
1604 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1605 NodeImpl *nextChild;
1606 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1608 // Remove the old child
1609 NodeImpl *prev = oldChild->previousSibling();
1610 NodeImpl *next = oldChild->nextSibling();
1612 removeChild(oldChild, exceptioncode);
1616 // Add the new child(ren)
1618 nextChild = isFragment ? child->nextSibling() : 0;
1620 // If child is already present in the tree, first remove it
1621 NodeImpl *newParent = child->parentNode();
1623 newParent->removeChild( child, exceptioncode );
1627 // Add child in the correct position
1628 if (prev) prev->setNextSibling(child);
1629 if (next) next->setPreviousSibling(child);
1630 if(!prev) _first = child;
1631 if(!next) _last = child;
1632 child->setParent(this);
1633 child->setPreviousSibling(prev);
1634 child->setNextSibling(next);
1636 // Add child to the rendering tree
1637 // ### should we detach() it first if it's already attached?
1638 if (attached() && !child->attached())
1641 // Dispatch the mutation events
1642 dispatchChildInsertedEvents(child,exceptioncode);
1648 // ### set style in case it's attached
1649 getDocument()->setDocumentChanged(true);
1650 dispatchSubtreeModifiedEvent();
1654 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1658 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1660 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1664 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1665 if (!oldChild || oldChild->parentNode() != this) {
1666 exceptioncode = DOMException::NOT_FOUND_ERR;
1670 // Dispatch pre-removal mutation events
1671 getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1672 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1673 oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1674 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1679 dispatchChildRemovalEvents(oldChild,exceptioncode);
1683 // Remove from rendering tree
1684 if (oldChild->attached())
1688 NodeImpl *prev, *next;
1689 prev = oldChild->previousSibling();
1690 next = oldChild->nextSibling();
1692 if(next) next->setPreviousSibling(prev);
1693 if(prev) prev->setNextSibling(next);
1694 if(_first == oldChild) _first = next;
1695 if(_last == oldChild) _last = prev;
1697 oldChild->setPreviousSibling(0);
1698 oldChild->setNextSibling(0);
1699 oldChild->setParent(0);
1701 getDocument()->setDocumentChanged(true);
1703 // Dispatch post-removal mutation events
1704 dispatchSubtreeModifiedEvent();
1706 if (oldChild->inDocument())
1707 oldChild->removedFromDocument();
1712 void NodeBaseImpl::removeChildren()
1715 while (NodeImpl *n = _first) {
1716 NodeImpl *next = n->nextSibling();
1720 // Fire removed from document mutation events.
1721 dispatchChildRemovalEvents(n, exceptionCode);
1725 n->setPreviousSibling(0);
1726 n->setNextSibling(0);
1729 if (n->inDocument())
1730 n->removedFromDocument();
1738 // Dispatch a single post-removal mutation event denoting a modified subtree.
1739 dispatchSubtreeModifiedEvent();
1743 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1747 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1749 // Make sure adding the new child is ok
1750 checkAddChild(newChild, exceptioncode);
1754 if ( newChild == _last ) // nothing to do
1757 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1759 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1760 // Just return the document fragment
1761 if (isFragment && !newChild->firstChild())
1764 // Now actually add the child(ren)
1765 NodeImpl *nextChild;
1766 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1769 nextChild = isFragment ? child->nextSibling() : 0;
1771 // If child is already present in the tree, first remove it
1772 NodeImpl *oldParent = child->parentNode();
1774 oldParent->removeChild( child, exceptioncode );
1779 // Append child to the end of the list
1780 child->setParent(this);
1784 child->setPreviousSibling(_last);
1785 _last->setNextSibling(child);
1790 _first = _last = child;
1793 // Add child to the rendering tree
1794 // ### should we detach() it first if it's already attached?
1795 if (attached() && !child->attached())
1798 // Dispatch the mutation events
1799 dispatchChildInsertedEvents(child,exceptioncode);
1804 getDocument()->setDocumentChanged(true);
1805 // ### set style in case it's attached
1806 dispatchSubtreeModifiedEvent();
1810 bool NodeBaseImpl::hasChildNodes ( ) const
1815 // not part of the DOM
1816 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1821 void NodeBaseImpl::setLastChild(NodeImpl *child)
1826 // check for same source document:
1827 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1830 DocumentImpl *ownerDocThis = getDocument();
1831 DocumentImpl *ownerDocNew = getDocument();
1832 if(ownerDocThis != ownerDocNew) {
1833 kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1834 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1840 // check for being (grand-..)father:
1841 // ### remove in favor or isAncestor()
1842 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1844 //check if newChild is parent of this...
1846 for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1848 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1854 // check for being child:
1855 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1857 if(!oldChild || oldChild->parentNode() != this) {
1858 exceptioncode = DOMException::NOT_FOUND_ERR;
1864 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1866 // do not add applyChanges here! This function is only used during parsing
1868 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1870 // short check for consistency with DTD
1871 if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1873 //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1878 newChild->setParent(this);
1882 newChild->setPreviousSibling(_last);
1883 _last->setNextSibling(newChild);
1888 _first = _last = newChild;
1891 newChild->insertedIntoDocument();
1894 if(newChild->nodeType() == Node::ELEMENT_NODE)
1899 void NodeBaseImpl::attach()
1901 NodeImpl *child = _first;
1905 child = child->nextSibling();
1910 void NodeBaseImpl::detach()
1912 NodeImpl *child = _first;
1915 NodeImpl* prev = child;
1916 child = child->nextSibling();
1922 void NodeBaseImpl::insertedIntoDocument()
1924 NodeImpl::insertedIntoDocument();
1925 for (NodeImpl *child = _first; child; child = child->nextSibling())
1926 child->insertedIntoDocument();
1929 void NodeBaseImpl::removedFromDocument()
1931 NodeImpl::removedFromDocument();
1932 for (NodeImpl *child = _first; child; child = child->nextSibling())
1933 child->removedFromDocument();
1936 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
1938 int exceptioncode = 0;
1940 for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
1942 clone->appendChild(n->cloneNode(true),exceptioncode);
1946 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
1947 DOMStringImpl* localName )
1949 if (!localName) return 0;
1951 NodeImpl::Id idMask = namespaceMask | localNameMask;
1952 if (localName->l && localName->s[0] == '*')
1953 idMask &= ~localNameMask;
1954 if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
1955 idMask &= ~namespaceMask;
1957 Id id = 0; // 0 means "all items"
1958 if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
1960 id = getDocument()->tagId( namespaceURI, localName, true);
1961 if ( !id ) // not found -> we want to return an empty list, not "all items"
1962 id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
1965 return new TagNodeListImpl( this, id, idMask );
1968 // I don't like this way of implementing the method, but I didn't find any
1970 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
1974 RenderObject *o = m_render;
1976 if ( !o->isInline() || o->isReplaced() ) {
1977 o->absolutePosition( xPos, yPos );
1981 // find the next text/image child, to get a position
1984 o = o->firstChild();
1985 else if(o->nextSibling())
1986 o = o->nextSibling();
1988 RenderObject *next = 0;
1991 if(!o) return false;
1992 next = o->nextSibling();
1996 if((o->isText() && !o->isBR()) || o->isReplaced()) {
1997 o->container()->absolutePosition( xPos, yPos );
1999 xPos += static_cast<RenderText *>(o)->minXPos();
2009 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2014 RenderObject *o = m_render;
2016 if (!o->isInline() || o->isReplaced())
2018 o->absolutePosition( xPos, yPos );
2020 yPos += o->height();
2023 // find the last text/image child, to get a position
2027 else if(o->previousSibling())
2028 o = o->previousSibling();
2030 RenderObject *prev = 0;
2033 if(!o) return false;
2034 prev = o->previousSibling();
2038 if(o->isText() || o->isReplaced()) {
2039 o->container()->absolutePosition(xPos, yPos);
2041 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2043 xPos += o->xPos()+o->width();
2044 yPos += o->yPos()+o->height();
2051 QRect NodeBaseImpl::getRect() const
2054 if (!getUpperLeftCorner(xPos,yPos))
2060 if (!getLowerRightCorner(xEnd,yEnd))
2074 if ( xEnd <= xPos || yEnd <= yPos )
2075 return QRect( QPoint( xPos, yPos ), QSize() );
2077 return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2080 void NodeBaseImpl::setFocus(bool received)
2082 if (m_focused == received) return;
2084 NodeImpl::setFocus(received);
2086 if (received && isEditableBlock() && !hasChildNodes()) {
2087 getDocument()->part()->setSelection(Selection(Position(this, 0), DOWNSTREAM));
2090 // note that we need to recalc the style
2094 void NodeBaseImpl::setActive(bool down)
2096 if (down == active()) return;
2098 NodeImpl::setActive(down);
2100 // note that we need to recalc the style
2101 if (m_render && m_render->style()->affectedByActiveRules())
2105 unsigned long NodeBaseImpl::childNodeCount() const
2107 unsigned long count = 0;
2109 for (n = firstChild(); n; n = n->nextSibling())
2114 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2117 NodeImpl *n = firstChild();
2118 for (i = 0; n != 0 && i < index; i++)
2119 n = n->nextSibling();
2123 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2125 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2126 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2127 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2132 // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2133 bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2135 while (p->parentNode())
2136 p = p->parentNode();
2137 if (p->nodeType() == Node::DOCUMENT_NODE) {
2138 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2139 c->insertedIntoDocument();
2141 if (hasInsertedListeners) {
2142 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2143 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2151 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2153 // Dispatch pre-removal mutation events
2154 getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2155 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2156 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2157 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2162 bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2164 // dispatch the DOMNodeRemovedFromDocument event to all descendants
2166 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2167 if (hasRemovalListeners) {
2168 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2169 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2177 // ---------------------------------------------------------------------------
2180 NodeListImpl::NodeListImpl(NodeImpl *_rootNode)
2181 : rootNode(_rootNode),
2182 isLengthCacheValid(false),
2183 isItemCacheValid(false)
2186 rootNode->registerNodeList(this);
2189 NodeListImpl::~NodeListImpl()
2191 rootNode->unregisterNodeList(this);
2195 unsigned long NodeListImpl::recursiveLength( NodeImpl *start ) const
2200 if (isLengthCacheValid && start == rootNode) {
2201 return cachedLength;
2204 unsigned long len = 0;
2206 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2207 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2210 len+= recursiveLength(n);
2214 if (start == rootNode) {
2216 isLengthCacheValid = true;
2222 NodeImpl *NodeListImpl::recursiveItem ( unsigned long offset, NodeImpl *start) const
2224 int remainingOffset = offset;
2226 start = rootNode->firstChild();
2227 if (isItemCacheValid) {
2228 if (offset == lastItemOffset) {
2230 } else if (offset > lastItemOffset) {
2232 remainingOffset -= lastItemOffset;
2237 NodeImpl *n = start;
2240 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2241 if (nodeMatches(n)) {
2242 if (!remainingOffset) {
2244 lastItemOffset = offset;
2245 isItemCacheValid = 1;
2252 n = n->traverseNextNode(rootNode);
2255 return 0; // no matching node in this subtree
2258 NodeImpl *NodeListImpl::itemById (const DOMString& elementId) const
2260 if (rootNode->isDocumentNode() || rootNode->inDocument()) {
2261 NodeImpl *node = rootNode->getDocument()->getElementById(elementId);
2263 if (node == NULL || !nodeMatches(node))
2266 for (NodeImpl *p = node->parentNode(); p; p = p->parentNode()) {
2274 unsigned long l = length();
2276 for ( unsigned long i = 0; i < l; i++ ) {
2277 NodeImpl *node = item(i);
2279 if ( static_cast<ElementImpl *>(node)->getIDAttribute() == elementId ) {
2288 void NodeListImpl::rootNodeSubtreeModified()
2290 isLengthCacheValid = false;
2291 isItemCacheValid = false;
2295 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2300 unsigned long ChildNodeListImpl::length() const
2302 unsigned long len = 0;
2304 for(n = rootNode->firstChild(); n != 0; n = n->nextSibling())
2310 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2312 unsigned int pos = 0;
2313 NodeImpl *n = rootNode->firstChild();
2315 while( n != 0 && pos < index )
2317 n = n->nextSibling();
2324 bool ChildNodeListImpl::nodeMatches(NodeImpl *testNode) const
2326 return testNode->parentNode() == rootNode;
2329 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2331 m_id(_id & _idMask),
2336 unsigned long TagNodeListImpl::length() const
2338 return recursiveLength();
2341 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2343 return recursiveItem( index );
2346 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2348 return ( testNode->isElementNode() &&
2349 (testNode->id() & m_idMask) == m_id);
2352 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2353 : NodeListImpl(n), nodeName(t)
2357 unsigned long NameNodeListImpl::length() const
2359 return recursiveLength();
2362 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2364 return recursiveItem( index );
2367 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2369 return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2372 // ---------------------------------------------------------------------------
2374 NamedNodeMapImpl::NamedNodeMapImpl()
2378 NamedNodeMapImpl::~NamedNodeMapImpl()
2382 // ----------------------------------------------------------------------------
2386 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2387 : NamedNodeMapImpl()
2389 m_doc = doc->document();
2390 m_contents = new QPtrList<NodeImpl>;
2393 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2395 while (m_contents->count() > 0)
2396 m_contents->take(0)->deref();
2401 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2403 QPtrListIterator<NodeImpl> it(*m_contents);
2404 for (; it.current(); ++it)
2405 if (it.current()->nodeName() == name)
2406 return it.current();
2410 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2412 // can't modify this list through standard DOM functions
2413 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2414 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2418 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2420 // can't modify this list through standard DOM functions
2421 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2422 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2426 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2428 // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2429 // (also for other similar methods)
2430 if (index >= m_contents->count())
2433 return m_contents->at(index);
2436 unsigned long GenericRONamedNodeMapImpl::length( ) const
2438 return m_contents->count();
2441 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2442 const DOMString &localName,
2443 int &/*exceptioncode*/ ) const
2445 NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2446 localName.implementation(), true);
2448 QPtrListIterator<NodeImpl> it(*m_contents);
2449 for (; it.current(); ++it)
2450 if (it.current()->id() == searchId)
2451 return it.current();
2456 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2458 // can't modify this list through standard DOM functions
2459 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2460 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2464 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2465 const DOMString &/*localName*/,
2466 int &exceptioncode )
2468 // can't modify this list through standard DOM functions
2469 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2473 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2475 // The spec says that in the case of duplicates we only keep the first one
2476 int exceptioncode = 0;
2477 if (getNamedItem(n->nodeName(),exceptioncode))
2481 m_contents->append(n);