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)
81 m_hasChangedChild( false ),
82 m_inDocument( false ),
87 m_styleElement( false ),
94 void NodeImpl::setDocument(DocumentPtr *doc)
108 NodeImpl::~NodeImpl()
112 delete m_regdListeners;
117 m_previous->setNextSibling(0);
119 m_next->setPreviousSibling(0);
122 DOMString NodeImpl::nodeValue() const
127 void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode )
129 // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
131 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
135 // be default nodeValue is null, so setting it has no effect
138 DOMString NodeImpl::nodeName() const
143 unsigned short NodeImpl::nodeType() const
148 NodeListImpl *NodeImpl::childNodes()
150 return new ChildNodeListImpl(this);
153 NodeImpl *NodeImpl::firstChild() const
158 NodeImpl *NodeImpl::lastChild() const
163 NodeImpl *NodeImpl::insertBefore( NodeImpl *newChild, NodeImpl *, int &exceptioncode )
167 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
171 NodeImpl *NodeImpl::replaceChild( NodeImpl *newChild, NodeImpl *, int &exceptioncode )
175 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
179 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
181 exceptioncode = DOMException::NOT_FOUND_ERR;
185 NodeImpl *NodeImpl::appendChild( NodeImpl *newChild, int &exceptioncode )
189 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
193 void NodeImpl::remove(int &exceptioncode)
197 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
201 parentNode()->removeChild(this, exceptioncode);
204 bool NodeImpl::hasChildNodes( ) const
209 void NodeImpl::normalize ()
211 // ### normalize attributes? (when we store attributes using child nodes)
212 int exceptioncode = 0;
213 NodeImpl *child = firstChild();
215 // Recursively go through the subtree beneath us, normalizing all nodes. In the case
216 // where there are two adjacent text nodes, they are merged together
218 NodeImpl *nextChild = child->nextSibling();
220 if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
221 // Current child and the next one are both text nodes... merge them
222 TextImpl *currentText = static_cast<TextImpl*>(child);
223 TextImpl *nextText = static_cast<TextImpl*>(nextChild);
225 currentText->appendData(nextText->data(),exceptioncode);
229 removeChild(nextChild,exceptioncode);
240 DOMString NodeImpl::prefix() const
242 // For nodes other than elements and attributes, the prefix is always null
246 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
248 // The spec says that for nodes other than elements and attributes, prefix is always null.
249 // It does not say what to do when the user tries to set the prefix on another type of
250 // node, however mozilla throws a NAMESPACE_ERR exception
251 exceptioncode = DOMException::NAMESPACE_ERR;
254 DOMString NodeImpl::localName() const
259 void NodeImpl::setFirstChild(NodeImpl *)
263 void NodeImpl::setLastChild(NodeImpl *)
267 NodeImpl *NodeImpl::addChild(NodeImpl *)
272 QString NodeImpl::toHTML() const
274 return recursive_toHTML(true);
277 static QString escapeHTML( const QString& in )
280 for ( unsigned int i = 0; i < in.length(); ++i ) {
281 switch( in[i].latin1() ) {
299 QString NodeImpl::startMarkup(const RangeImpl *range) const
301 unsigned short type = nodeType();
302 if (type == Node::TEXT_NODE) {
303 DOMString str = nodeValue().copy();
306 if (this == range->endContainer(exceptionCode)) {
307 str.truncate(range->endOffset(exceptionCode));
309 if (this == range->startContainer(exceptionCode)) {
310 str.remove(0, range->startOffset(exceptionCode));
313 Id parentID = parentNode()->id();
314 bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
315 return dontEscape ? str.string() : escapeHTML(str.string());
316 } else if (type != Node::DOCUMENT_NODE) {
317 QString markup = QChar('<') + nodeName().string();
318 if (type == Node::ELEMENT_NODE) {
319 const ElementImpl *el = static_cast<const ElementImpl *>(this);
320 NamedAttrMapImpl *attrs = el->attributes();
321 unsigned long length = attrs->length();
322 for (unsigned int i=0; i<length; i++) {
323 AttributeImpl *attr = attrs->attributeItem(i);
324 markup += " " + getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
327 markup += isHTMLElement() ? ">" : "/>";
333 QString NodeImpl::endMarkup(void) const
335 if ((!isHTMLElement() || endTag[id()] != FORBIDDEN) && nodeType() != Node::TEXT_NODE && nodeType() != Node::DOCUMENT_NODE) {
336 return "</" + nodeName().string() + ">";
341 QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, QPtrList<NodeImpl> *nodes)
343 // Doesn't make sense to only include children and include siblings.
344 assert(!(onlyIncludeChildren && includeSiblings));
346 for (const NodeImpl *current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
347 if (!onlyIncludeChildren) {
349 nodes->append(current);
351 me += current->startMarkup(0);
353 if (!current->isHTMLElement() || endTag[current->id()] != FORBIDDEN) {
355 if (NodeImpl *n = current->firstChild()) {
356 me += recursive_toString(n, false, true, nodes);
358 // Print my ending tag
359 if (!onlyIncludeChildren) {
360 me += current->endMarkup();
367 QString NodeImpl::recursive_toHTML(bool onlyIncludeChildren, QPtrList<NodeImpl> *nodes) const
369 return NodeImpl::recursive_toString(this, onlyIncludeChildren, false, nodes);
372 void NodeImpl::recursive_completeURLs(QString baseURL)
374 if (nodeType() == Node::ELEMENT_NODE) {
375 ElementImpl *el = static_cast<ElementImpl *>(this);
376 NamedAttrMapImpl *attrs = el->attributes();
377 unsigned long length = attrs->length();
378 for (unsigned int i=0; i<length; i++) {
379 AttributeImpl *attr = attrs->attributeItem(i);
380 if (el->isURLAttribute(attr)) {
381 el->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url());
387 if ((n = firstChild())) {
388 n->recursive_completeURLs(baseURL);
390 if ((n = nextSibling())) {
391 n->recursive_completeURLs(baseURL);
395 bool NodeImpl::isContentEditable() const
397 return m_parent ? m_parent->isContentEditable() : false;
400 QRect NodeImpl::getRect() const
403 if(m_render && m_render->absolutePosition(_x, _y))
404 return QRect( _x, _y, m_render->width(), m_render->height() );
409 void NodeImpl::setChanged(bool b)
411 if (b && !attached()) // changed compared to what?
416 NodeImpl *p = parentNode();
418 p->setHasChangedChild( true );
421 getDocument()->setDocumentChanged(true);
425 bool NodeImpl::isInline() const
427 if (m_render) return m_render->style()->display() == khtml::INLINE;
428 return !isElementNode();
431 bool NodeImpl::isFocusable() const
436 bool NodeImpl::isKeyboardFocusable() const
438 return isFocusable();
441 bool NodeImpl::isMouseFocusable() const
443 return isFocusable();
446 unsigned long NodeImpl::nodeIndex() const
448 NodeImpl *_tempNode = previousSibling();
449 unsigned long count=0;
450 for( count=0; _tempNode; count++ )
451 _tempNode = _tempNode->previousSibling();
455 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
458 case EventImpl::DOMSUBTREEMODIFIED_EVENT:
459 getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
461 case EventImpl::DOMNODEINSERTED_EVENT:
462 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
464 case EventImpl::DOMNODEREMOVED_EVENT:
465 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
467 case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
468 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
470 case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
471 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
473 case EventImpl::DOMATTRMODIFIED_EVENT:
474 getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
476 case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
477 getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
483 RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
484 if (!m_regdListeners) {
485 m_regdListeners = new QPtrList<RegisteredEventListener>;
486 m_regdListeners->setAutoDelete(true);
491 // remove existing identical listener set with identical arguments - the DOM2
492 // spec says that "duplicate instances are discarded" in this case.
493 removeEventListener(id,listener,useCapture);
495 m_regdListeners->append(rl);
499 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
501 if (!m_regdListeners) // nothing to remove
504 RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
506 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
507 for (; it.current(); ++it)
508 if (*(it.current()) == rl) {
509 m_regdListeners->removeRef(it.current());
514 void NodeImpl::removeHTMLEventListener(int id)
516 if (!m_regdListeners) // nothing to remove
519 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
520 for (; it.current(); ++it)
521 if (it.current()->id == id &&
522 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
523 m_regdListeners->removeRef(it.current());
528 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
530 // in case we already have it, we don't want removeHTMLEventListener to destroy it
533 removeHTMLEventListener(id);
536 addEventListener(id,listener,false);
541 EventListener *NodeImpl::getHTMLEventListener(int id)
543 if (!m_regdListeners)
546 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
547 for (; it.current(); ++it)
548 if (it.current()->id == id &&
549 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
550 return it.current()->listener;
556 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
560 evt->setTarget(this);
562 // We've had at least one report of a crash on a page where document is nil here.
563 // Unfortunately that page no longer exists, but we'll make this code robust against
565 // FIXME: Much code in this class assumes document is non-nil; it would be better to
566 // ensure that document can never be nil.
567 KHTMLPart *part = nil;
568 KHTMLView *view = nil;
570 if (document && document->document()) {
571 part = document->document()->part();
572 view = document->document()->view();
573 // Since event handling code could cause this object to be deleted, grab a reference to the view now
578 bool ret = dispatchGenericEvent( evt, exceptioncode );
580 // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
581 // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
582 // So there is no need for the interpreter to keep the event in it's cache
583 if (tempEvent && part && part->jScript())
584 part->jScript()->finishedWithEvent(evt);
594 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
598 // ### check that type specified
600 // work out what nodes to send event to
601 QPtrList<NodeImpl> nodeChain;
603 for (n = this; n; n = n->parentNode()) {
605 nodeChain.prepend(n);
608 // trigger any capturing event handlers on our way down
609 evt->setEventPhase(Event::CAPTURING_PHASE);
610 QPtrListIterator<NodeImpl> it(nodeChain);
611 for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
612 evt->setCurrentTarget(it.current());
613 it.current()->handleLocalEvents(evt,true);
616 // dispatch to the actual target node
618 if (!evt->propagationStopped()) {
619 evt->setEventPhase(Event::AT_TARGET);
620 evt->setCurrentTarget(it.current());
622 // Capturing first. -dwh
623 it.current()->handleLocalEvents(evt,true);
625 // Bubbling second. -dwh
626 if (!evt->propagationStopped())
627 it.current()->handleLocalEvents(evt,false);
631 // ok, now bubble up again (only non-capturing event handlers will be called)
632 // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
633 // no. the DOM specs says:
634 // The chain of EventTargets from the event target to the top of the tree
635 // is determined before the initial dispatch of the event.
636 // If modifications occur to the tree during event processing,
637 // event flow will proceed based on the initial state of the tree.
639 // since the initial dispatch is before the capturing phase,
640 // there's no need to recalculate the node chain.
643 if (evt->bubbles()) {
644 evt->setEventPhase(Event::BUBBLING_PHASE);
645 for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
646 evt->setCurrentTarget(it.current());
647 it.current()->handleLocalEvents(evt,false);
651 evt->setCurrentTarget(0);
652 evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
653 // anything about the default event handler phase.
656 if (evt->bubbles()) {
657 // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
660 for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
661 it.current()->defaultEventHandler(evt);
664 // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions
665 // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or
666 // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code.
667 if (!evt->defaultPrevented() && !disabled())
668 if (evt->id() == EventImpl::KHTML_CLICK_EVENT)
669 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1);
670 else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT)
671 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2);
673 // deref all nodes in chain
675 for (; it.current(); ++it)
676 it.current()->deref(); // this may delete us
678 DocumentImpl::updateDocumentsRendering();
680 bool defaultPrevented = evt->defaultPrevented();
684 return !defaultPrevented; // ### what if defaultPrevented was called before dispatchEvent?
687 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
689 int exceptioncode = 0;
690 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
691 return dispatchEvent(evt,exceptioncode,true);
694 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
696 int exceptioncode = 0;
697 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
700 DocumentPtr *doc = document;
702 bool r = dispatchGenericEvent( evt, exceptioncode );
703 if (!evt->defaultPrevented() && doc->document())
704 doc->document()->defaultEventHandler(evt);
706 if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
707 // For onload events, send them to the enclosing frame only.
708 // This is a DOM extension and is independent of bubbling/capturing rules of
709 // the DOM. You send the event only to the enclosing frame. It does not
710 // bubble through the parent document.
711 ElementImpl* elt = doc->document()->ownerElement();
712 if (elt && (elt->getDocument()->domain().isNull() ||
713 elt->getDocument()->domain() == doc->document()->domain())) {
714 // We also do a security check, since we don't want to allow the enclosing
715 // iframe to see loads of child documents in other domains.
716 evt->setCurrentTarget(elt);
719 elt->handleLocalEvents(evt,true);
722 if (!evt->propagationStopped())
723 elt->handleLocalEvents(evt,false);
724 r = !evt->defaultPrevented();
734 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
736 bool cancelable = true;
737 int detail = overrideDetail; // defaults to 0
738 EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
740 evtId = static_cast<EventImpl::EventId>(overrideId);
743 switch (_mouse->type()) {
744 case QEvent::MouseButtonPress:
745 evtId = EventImpl::MOUSEDOWN_EVENT;
747 case QEvent::MouseButtonRelease:
748 evtId = EventImpl::MOUSEUP_EVENT;
750 case QEvent::MouseButtonDblClick:
751 evtId = EventImpl::CLICK_EVENT;
752 detail = 1; // ### support for multiple double clicks
754 case QEvent::MouseMove:
755 evtId = EventImpl::MOUSEMOVE_EVENT;
762 if (evtId == EventImpl::UNKNOWN_EVENT)
763 return false; // shouldn't happen
766 int exceptioncode = 0;
769 // Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
770 // our khtmlview's coord system. This works for QMouseEvents coming from Cocoa because those events
771 // hold the location from the NSEvent. The QMouseEvent param here was made by other khtml code, so it
772 // will be a "proper" QT event with coords in terms of this widget. So in WebCore it would never be
773 // right to pass coords from _mouse to viewportToContents().
775 // int clientX, clientY;
776 // viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
777 int clientX = _mouse->x(); // ### adjust to be relative to view
778 int clientY = _mouse->y(); // ### adjust to be relative to view
783 KHTMLView *view = document->document()->view();
785 // This gets us as far as NSWindow coords
786 QPoint windowLoc = view->contentsToViewport(_mouse->pos());
787 // Then from NSWindow coords to screen coords
788 QPoint screenLoc = view->viewportToGlobal(windowLoc);
789 screenX = screenLoc.x();
790 screenY = screenLoc.y();
792 screenX = _mouse->x();
793 screenY = _mouse->y();
796 int screenX = _mouse->globalX();
797 int screenY = _mouse->globalY();
801 switch (_mouse->button()) {
808 case Qt::RightButton:
814 bool ctrlKey = (_mouse->state() & Qt::ControlButton);
815 bool altKey = (_mouse->state() & Qt::AltButton);
816 bool shiftKey = (_mouse->state() & Qt::ShiftButton);
817 bool metaKey = false; // ### qt support?
819 EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
820 detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
822 return dispatchEvent(evt,exceptioncode,true);
826 bool NodeImpl::dispatchUIEvent(int _id, int detail)
828 assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
829 _id != EventImpl::DOMFOCUSOUT_EVENT &&
830 _id != EventImpl::DOMACTIVATE_EVENT)));
832 bool cancelable = false;
833 if (_id == EventImpl::DOMACTIVATE_EVENT)
836 int exceptioncode = 0;
837 UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
838 cancelable,getDocument()->defaultView(),detail);
839 return dispatchEvent(evt,exceptioncode,true);
842 void NodeImpl::registerNodeList(NodeListImpl *list)
845 m_nodeLists = new QPtrDict<NodeListImpl>;
848 m_nodeLists->insert(list, list);
851 void NodeImpl::unregisterNodeList(NodeListImpl *list)
856 m_nodeLists->remove(list);
859 void NodeImpl::notifyLocalNodeListsSubtreeModified()
864 QPtrDictIterator<NodeListImpl> i(*m_nodeLists);
866 while (NodeListImpl *list = i.current()) {
867 list->rootNodeSubtreeModified();
872 void NodeImpl::notifyNodeListsSubtreeModified()
874 for (NodeImpl *n = this; n; n = n->parentNode()) {
875 n->notifyLocalNodeListsSubtreeModified();
879 bool NodeImpl::dispatchSubtreeModifiedEvent(bool sendChildrenChanged)
881 notifyNodeListsSubtreeModified();
882 if (sendChildrenChanged)
884 if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
886 int exceptioncode = 0;
887 return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
888 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
891 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
893 int exceptioncode = 0;
894 //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
895 KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
896 keyboardEventImpl->ref();
897 bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
900 // we want to return false if default is prevented (already taken care of)
901 // or if the element is default-handled by the DOM. Otherwise we let it just
902 // let it get handled by AppKit
903 if (keyboardEventImpl->defaultHandled())
905 // the default event handler should accept() the internal QKeyEvent
906 // to prevent the view from further evaluating it.
907 if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
911 keyboardEventImpl->deref();
915 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
917 if (!m_regdListeners)
920 if (disabled() && evt->isMouseEvent())
923 QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
924 QPtrListIterator<RegisteredEventListener> it(listenersCopy);
926 for (; it.current(); ++it) {
927 if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
928 it.current()->listener->handleEvent(ev, false);
933 void NodeImpl::defaultEventHandler(EventImpl *evt)
937 unsigned long NodeImpl::childNodeCount() const
942 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
947 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
950 assert(!stayWithin || firstChild()->isAncestor(stayWithin));
953 if (this == stayWithin)
956 assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
957 return nextSibling();
959 const NodeImpl *n = this;
960 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
963 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
964 return n->nextSibling();
969 NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const
971 if (this == stayWithin)
974 assert(!stayWithin || nextSibling()->isAncestor(stayWithin));
975 return nextSibling();
977 const NodeImpl *n = this;
978 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
981 assert(!stayWithin || !n->nextSibling() || n->nextSibling()->isAncestor(stayWithin));
982 return n->nextSibling();
987 NodeImpl *NodeImpl::traversePreviousNode() const
989 if (previousSibling()) {
990 NodeImpl *n = previousSibling();
991 while (n->lastChild())
995 else if (parentNode()) {
1003 NodeImpl *NodeImpl::traversePreviousNodePostOrder(NodeImpl *stayWithin) const
1006 assert(!stayWithin || lastChild()->isAncestor(stayWithin));
1009 if (this == stayWithin)
1011 if (previousSibling()) {
1012 assert(!stayWithin || previousSibling()->isAncestor(stayWithin));
1013 return previousSibling();
1015 const NodeImpl *n = this;
1016 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
1017 n = n->parentNode();
1019 assert(!stayWithin || !n->previousSibling() || n->previousSibling()->isAncestor(stayWithin));
1020 return n->previousSibling();
1025 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
1027 // Perform error checking as required by spec for setting Node.prefix. Used by
1028 // ElementImpl::setPrefix() and AttrImpl::setPrefix()
1030 // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
1031 if (!Element::khtmlValidPrefix(_prefix)) {
1032 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
1036 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1038 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1042 // NAMESPACE_ERR: - Raised if the specified prefix is malformed
1043 // - if the namespaceURI of this node is null,
1044 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
1045 // "http://www.w3.org/XML/1998/namespace",
1046 // - if this node is an attribute and the specified prefix is "xmlns" and
1047 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
1048 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
1049 if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
1050 (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
1051 exceptioncode = DOMException::NAMESPACE_ERR;
1056 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
1058 // Perform error checking as required by spec for adding a new child. Used by
1059 // appendChild(), replaceChild() and insertBefore()
1061 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
1063 exceptioncode = DOMException::NOT_FOUND_ERR;
1067 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
1069 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1073 bool shouldAdoptChild = false;
1075 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
1076 // created this node.
1077 // We assume that if newChild is a DocumentFragment, all children are created from the same document
1078 // as the fragment itself (otherwise they could not have been added as children)
1079 if (newChild->getDocument() != getDocument()) {
1080 // but if the child is not in a document yet then loosen the
1081 // restriction, so that e.g. creating an element with the Option()
1082 // constructor and then adding it to a different document works,
1083 // as it does in Mozilla and Mac IE.
1084 if (!newChild->inDocument()) {
1085 shouldAdoptChild = true;
1087 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1092 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1093 // newChild node, or if the node to append is one of this node's ancestors.
1095 // check for ancestor/same node
1096 if (newChild == this || isAncestor(newChild)) {
1097 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1101 // only do this once we know there won't be an exception
1102 if (shouldAdoptChild) {
1103 KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
1104 newChild->setDocument(getDocument()->docPtr());
1108 bool NodeImpl::isAncestor(const NodeImpl *other) const
1110 // Return true if other is an ancestor of this, otherwise false
1111 for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1118 bool NodeImpl::childAllowed( NodeImpl *newChild )
1120 return childTypeAllowed(newChild->nodeType());
1123 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1125 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
1126 // explicit inheritance of non-inherited properties and so you end up not re-resolving
1127 // style in cases where you need to.
1128 StyleChange ch = NoInherit;
1129 EDisplay display1 = s1 ? s1->display() : NONE;
1130 bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1131 EDisplay display2 = s2 ? s2->display() : NONE;
1132 bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1133 if (display1 != display2 || fl1 != fl2)
1135 else if ( !s1 || !s2 )
1137 else if ( *s1 == *s2 )
1139 else if ( s1->inheritedNotEqual( s2 ) )
1145 void NodeImpl::dump(QTextStream *stream, QString ind) const
1147 // ### implement dump() for all appropriate subclasses
1149 if (m_hasId) { *stream << " hasId"; }
1150 if (m_hasClass) { *stream << " hasClass"; }
1151 if (m_hasStyle) { *stream << " hasStyle"; }
1152 if (m_specified) { *stream << " specified"; }
1153 if (m_focused) { *stream << " focused"; }
1154 if (m_active) { *stream << " active"; }
1155 if (m_styleElement) { *stream << " styleElement"; }
1156 if (m_implicit) { *stream << " implicit"; }
1158 *stream << " tabIndex=" << m_tabIndex;
1159 if (m_regdListeners)
1160 *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1163 NodeImpl *child = firstChild();
1166 *stream << ind << child->nodeName().string().ascii() << ": ";
1167 child->dump(stream,ind+" ");
1168 child = child->nextSibling();
1173 void NodeImpl::attach()
1175 assert(!attached());
1176 assert(!m_render || (m_render->style() && m_render->parent()));
1177 getDocument()->incDOMTreeVersion();
1181 void NodeImpl::detach()
1183 // assert(m_attached);
1189 getDocument()->incDOMTreeVersion();
1193 bool NodeImpl::maintainsState()
1198 QString NodeImpl::state()
1200 return QString::null;
1203 void NodeImpl::restoreState(QStringList &/*states*/)
1207 void NodeImpl::insertedIntoDocument()
1209 setInDocument(true);
1212 void NodeImpl::removedFromDocument()
1214 setInDocument(false);
1217 void NodeImpl::childrenChanged()
1221 bool NodeImpl::disabled() const
1226 bool NodeImpl::isReadOnly()
1228 // Entity & Entity Reference nodes and their descendants are read-only
1231 if (n->nodeType() == Node::ENTITY_NODE ||
1232 n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1234 n = n->parentNode();
1239 NodeImpl *NodeImpl::previousEditable() const
1241 NodeImpl *node = previousLeafNode();
1243 if (node->isContentEditable())
1245 node = node->previousLeafNode();
1250 NodeImpl *NodeImpl::nextEditable() const
1252 NodeImpl *node = nextLeafNode();
1254 if (node->isContentEditable())
1256 node = node->nextLeafNode();
1261 RenderObject * NodeImpl::previousRenderer()
1263 for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1265 return n->renderer();
1270 RenderObject * NodeImpl::nextRenderer()
1272 for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1274 return n->renderer();
1279 bool NodeImpl::isAtomicNode() const
1281 return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1284 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1286 if (previousSibling()) {
1287 NodeImpl *n = previousSibling();
1288 while (!n->isAtomicNode() && n->lastChild())
1292 else if (parentNode()) {
1293 return parentNode();
1300 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1302 if (!isAtomicNode() && firstChild())
1303 return firstChild();
1305 return nextSibling();
1306 const NodeImpl *n = this;
1307 while (n && !n->nextSibling())
1308 n = n->parentNode();
1310 return n->nextSibling();
1314 NodeImpl *NodeImpl::previousLeafNode() const
1316 NodeImpl *node = previousNodeConsideringAtomicNodes();
1318 if (node->isAtomicNode())
1320 node = node->previousNodeConsideringAtomicNodes();
1325 NodeImpl *NodeImpl::nextLeafNode() const
1327 NodeImpl *node = nextNodeConsideringAtomicNodes();
1329 if (node->isAtomicNode())
1331 node = node->nextNodeConsideringAtomicNodes();
1336 void NodeImpl::createRendererIfNeeded()
1340 if (!getDocument()->shouldCreateRenderers())
1344 assert(!attached());
1347 NodeImpl *parent = parentNode();
1350 RenderObject *parentRenderer = parent->renderer();
1351 if (parentRenderer && parentRenderer->canHaveChildren()) {
1352 RenderStyle *style = styleForRenderer(parentRenderer);
1354 #ifndef KHTML_NO_XBL
1355 bool resolveStyle = false;
1356 if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
1357 rendererIsNeeded(style)) {
1360 style = styleForRenderer(parentRenderer);
1363 if (rendererIsNeeded(style)) {
1365 m_render = createRenderer(getDocument()->renderArena(), style);
1366 m_render->setStyle(style);
1367 parentRenderer->addChild(m_render, nextRenderer());
1368 #ifndef KHTML_NO_XBL
1369 } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1373 style->deref(getDocument()->renderArena());
1377 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1379 return parent->style();
1382 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1384 return (getDocument()->documentElement() == this) || (style->display() != NONE);
1387 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1393 long NodeImpl::maxOffset() const
1398 long NodeImpl::caretMinOffset() const
1400 return renderer() ? renderer()->caretMinOffset() : 0;
1403 long NodeImpl::caretMaxOffset() const
1405 return renderer() ? renderer()->caretMaxOffset() : 1;
1408 unsigned long NodeImpl::caretMaxRenderedOffset() const
1410 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1413 bool NodeImpl::isBlockFlow() const
1415 return renderer() && renderer()->isBlockFlow();
1418 bool NodeImpl::isEditableBlock() const
1420 return isContentEditable() && isBlockFlow();
1423 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1425 NodeImpl *n = const_cast<NodeImpl *>(this);
1427 return static_cast<ElementImpl *>(n);
1430 n = n->parentNode();
1433 if (n->isBlockFlow() || n->id() == ID_BODY)
1434 return static_cast<ElementImpl *>(n);
1439 ElementImpl *NodeImpl::enclosingInlineElement() const
1441 NodeImpl *n = const_cast<NodeImpl *>(this);
1445 p = n->parentNode();
1446 if (!p || p->isBlockFlow() || p->id() == ID_BODY)
1447 return static_cast<ElementImpl *>(n);
1450 ASSERT_NOT_REACHED();
1454 ElementImpl *NodeImpl::rootEditableElement() const
1456 if (!isContentEditable())
1459 NodeImpl *n = const_cast<NodeImpl *>(this);
1460 if (n->id() == ID_BODY)
1461 return static_cast<ElementImpl *>(n);
1463 NodeImpl *result = n->isEditableBlock() ? n : 0;
1465 n = n->parentNode();
1466 if (!n || !n->isContentEditable())
1468 if (n->id() == ID_BODY) {
1472 if (n->isBlockFlow())
1475 return static_cast<ElementImpl *>(result);
1478 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1480 return n ? rootEditableElement() == n->rootEditableElement() : false;
1483 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1485 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1489 NodeImpl::Id NodeImpl::identifier() const
1496 void NodeImpl::displayNode(const char *prefix)
1501 fprintf(stderr, "%s%s\t%p %s\n", prefix, getTagName(id()).string().latin1(), this, nodeValue().ascii());
1503 fprintf(stderr, "%s%s\t%p\n", prefix, getTagName(id()).string().latin1(), this);
1506 void NodeImpl::displayTree()
1508 NodeImpl *rootNode = rootEditableElement();
1511 for (node = rootNode; node; node = node->traverseNextNode()) {
1514 fprintf(stderr, "*");
1515 for (tmpNode = node; tmpNode != rootNode; tmpNode = tmpNode->parentNode())
1516 fprintf(stderr, "\t");
1517 node->displayNode(0);
1521 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1527 if (s.length() == 0)
1532 strncpy(buffer, result.string().latin1(), length - 1);
1536 //-------------------------------------------------------------------------
1538 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1545 NodeBaseImpl::~NodeBaseImpl()
1547 //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1549 // Avoid deep recursion when destroying the node tree.
1550 static bool alreadyInsideDestructor;
1551 bool topLevel = !alreadyInsideDestructor;
1553 alreadyInsideDestructor = true;
1555 // List of nodes to be deleted.
1556 static NodeImpl *head;
1557 static NodeImpl *tail;
1559 // We have to tell all children that their parent has died.
1563 for( n = _first; n != 0; n = next ) {
1564 next = n->nextSibling();
1565 n->setPreviousSibling(0);
1566 n->setNextSibling(0);
1569 if ( !n->refCount() ) {
1570 // Add the node to the list of nodes to be deleted.
1571 // Reuse the nextSibling pointer for this purpose.
1573 tail->setNextSibling(n);
1580 // Only for the top level call, do the actual deleting.
1582 while ((n = head) != 0) {
1583 next = n->nextSibling();
1584 n->setNextSibling(0);
1593 alreadyInsideDestructor = false;
1598 NodeImpl *NodeBaseImpl::firstChild() const
1603 NodeImpl *NodeBaseImpl::lastChild() const
1608 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1612 // insertBefore(...,null) is equivalent to appendChild()
1614 return appendChild(newChild, exceptioncode);
1616 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1618 // Make sure adding the new child is ok
1619 checkAddChild(newChild, exceptioncode);
1623 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1624 if (refChild->parentNode() != this) {
1625 exceptioncode = DOMException::NOT_FOUND_ERR;
1629 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1631 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1632 // Just return the document fragment
1633 if (isFragment && !newChild->firstChild())
1634 return (newChild->hasOneRef() && !newChild->parent()) ? 0 : newChild;
1636 // Now actually add the child(ren)
1637 NodeImpl *nextChild;
1638 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1640 NodeImpl *prev = refChild->previousSibling();
1641 if ( prev == newChild || refChild == newChild ) // nothing to do
1645 nextChild = isFragment ? child->nextSibling() : 0;
1647 // If child is already present in the tree, first remove it
1648 NodeImpl *newParent = child->parentNode();
1650 newParent->removeChild( child, exceptioncode );
1651 if ( exceptioncode )
1654 // Add child in the correct position
1656 prev->setNextSibling(child);
1659 refChild->setPreviousSibling(child);
1660 child->setParent(this);
1661 child->setPreviousSibling(prev);
1662 child->setNextSibling(refChild);
1664 // Add child to the rendering tree
1665 // ### should we detach() it first if it's already attached?
1666 if (attached() && !child->attached())
1669 // Dispatch the mutation events
1670 dispatchChildInsertedEvents(child,exceptioncode);
1676 getDocument()->setDocumentChanged(true);
1677 dispatchSubtreeModifiedEvent();
1681 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1685 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1687 if ( oldChild == newChild ) // nothing to do
1690 // Make sure adding the new child is ok
1691 checkAddChild(newChild, exceptioncode);
1695 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1696 if (!oldChild || oldChild->parentNode() != this) {
1697 exceptioncode = DOMException::NOT_FOUND_ERR;
1701 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1702 NodeImpl *nextChild;
1703 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1705 // Remove the old child
1706 NodeImpl *prev = oldChild->previousSibling();
1707 NodeImpl *next = oldChild->nextSibling();
1709 removeChild(oldChild, exceptioncode);
1713 // Add the new child(ren)
1715 nextChild = isFragment ? child->nextSibling() : 0;
1717 // If child is already present in the tree, first remove it
1718 NodeImpl *newParent = child->parentNode();
1720 newParent->removeChild( child, exceptioncode );
1724 // Add child in the correct position
1725 if (prev) prev->setNextSibling(child);
1726 if (next) next->setPreviousSibling(child);
1727 if(!prev) _first = child;
1728 if(!next) _last = child;
1729 child->setParent(this);
1730 child->setPreviousSibling(prev);
1731 child->setNextSibling(next);
1733 // Add child to the rendering tree
1734 // ### should we detach() it first if it's already attached?
1735 if (attached() && !child->attached())
1738 // Dispatch the mutation events
1739 dispatchChildInsertedEvents(child,exceptioncode);
1745 // ### set style in case it's attached
1746 getDocument()->setDocumentChanged(true);
1747 dispatchSubtreeModifiedEvent();
1751 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1755 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1757 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1761 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1762 if (!oldChild || oldChild->parentNode() != this) {
1763 exceptioncode = DOMException::NOT_FOUND_ERR;
1767 // Dispatch pre-removal mutation events
1768 getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1769 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1770 oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1771 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1776 dispatchChildRemovalEvents(oldChild,exceptioncode);
1780 // Remove from rendering tree
1781 if (oldChild->attached())
1785 NodeImpl *prev, *next;
1786 prev = oldChild->previousSibling();
1787 next = oldChild->nextSibling();
1789 if(next) next->setPreviousSibling(prev);
1790 if(prev) prev->setNextSibling(next);
1791 if(_first == oldChild) _first = next;
1792 if(_last == oldChild) _last = prev;
1794 oldChild->setPreviousSibling(0);
1795 oldChild->setNextSibling(0);
1796 oldChild->setParent(0);
1798 getDocument()->setDocumentChanged(true);
1800 // Dispatch post-removal mutation events
1801 dispatchSubtreeModifiedEvent();
1803 if (oldChild->inDocument())
1804 oldChild->removedFromDocument();
1809 void NodeBaseImpl::removeChildren()
1812 while (NodeImpl *n = _first) {
1813 NodeImpl *next = n->nextSibling();
1817 // Fire removed from document mutation events.
1818 dispatchChildRemovalEvents(n, exceptionCode);
1822 n->setPreviousSibling(0);
1823 n->setNextSibling(0);
1826 if (n->inDocument())
1827 n->removedFromDocument();
1835 // Dispatch a single post-removal mutation event denoting a modified subtree.
1836 dispatchSubtreeModifiedEvent();
1840 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1844 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1846 // Make sure adding the new child is ok
1847 checkAddChild(newChild, exceptioncode);
1851 if ( newChild == _last ) // nothing to do
1854 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1856 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1857 // Just return the document fragment
1858 if (isFragment && !newChild->firstChild())
1861 // Now actually add the child(ren)
1862 NodeImpl *nextChild;
1863 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1866 nextChild = isFragment ? child->nextSibling() : 0;
1868 // If child is already present in the tree, first remove it
1869 NodeImpl *oldParent = child->parentNode();
1871 oldParent->removeChild( child, exceptioncode );
1876 // Append child to the end of the list
1877 child->setParent(this);
1881 child->setPreviousSibling(_last);
1882 _last->setNextSibling(child);
1887 _first = _last = child;
1890 // Add child to the rendering tree
1891 // ### should we detach() it first if it's already attached?
1892 if (attached() && !child->attached())
1895 // Dispatch the mutation events
1896 dispatchChildInsertedEvents(child,exceptioncode);
1901 getDocument()->setDocumentChanged(true);
1902 // ### set style in case it's attached
1903 dispatchSubtreeModifiedEvent();
1907 bool NodeBaseImpl::hasChildNodes ( ) const
1912 // not part of the DOM
1913 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1918 void NodeBaseImpl::setLastChild(NodeImpl *child)
1923 // check for same source document:
1924 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1927 DocumentImpl *ownerDocThis = getDocument();
1928 DocumentImpl *ownerDocNew = getDocument();
1929 if(ownerDocThis != ownerDocNew) {
1930 kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1931 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1937 // check for being (grand-..)father:
1938 // ### remove in favor or isAncestor()
1939 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1941 //check if newChild is parent of this...
1943 for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1945 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1951 // check for being child:
1952 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1954 if(!oldChild || oldChild->parentNode() != this) {
1955 exceptioncode = DOMException::NOT_FOUND_ERR;
1961 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1963 // do not add applyChanges here! This function is only used during parsing
1965 Node protectNewChild(newChild); // make sure the new child is ref'd and deref'd so we don't leak it
1967 // short check for consistency with DTD
1968 if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1970 //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1975 newChild->setParent(this);
1979 newChild->setPreviousSibling(_last);
1980 _last->setNextSibling(newChild);
1985 _first = _last = newChild;
1988 newChild->insertedIntoDocument();
1991 if(newChild->nodeType() == Node::ELEMENT_NODE)
1996 void NodeBaseImpl::attach()
1998 NodeImpl *child = _first;
2002 child = child->nextSibling();
2007 void NodeBaseImpl::detach()
2009 NodeImpl *child = _first;
2012 NodeImpl* prev = child;
2013 child = child->nextSibling();
2019 void NodeBaseImpl::insertedIntoDocument()
2021 NodeImpl::insertedIntoDocument();
2022 for (NodeImpl *child = _first; child; child = child->nextSibling())
2023 child->insertedIntoDocument();
2026 void NodeBaseImpl::removedFromDocument()
2028 NodeImpl::removedFromDocument();
2029 for (NodeImpl *child = _first; child; child = child->nextSibling())
2030 child->removedFromDocument();
2033 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
2035 int exceptioncode = 0;
2037 for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
2039 clone->appendChild(n->cloneNode(true),exceptioncode);
2043 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
2044 DOMStringImpl* localName )
2046 if (!localName) return 0;
2048 NodeImpl::Id idMask = namespaceMask | localNameMask;
2049 if (localName->l && localName->s[0] == '*')
2050 idMask &= ~localNameMask;
2051 if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
2052 idMask &= ~namespaceMask;
2054 Id id = 0; // 0 means "all items"
2055 if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
2057 id = getDocument()->tagId( namespaceURI, localName, true);
2058 if ( !id ) // not found -> we want to return an empty list, not "all items"
2059 id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
2062 return new TagNodeListImpl( this, id, idMask );
2065 // I don't like this way of implementing the method, but I didn't find any
2067 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
2071 RenderObject *o = m_render;
2073 if ( !o->isInline() || o->isReplaced() ) {
2074 o->absolutePosition( xPos, yPos );
2078 // find the next text/image child, to get a position
2081 o = o->firstChild();
2082 else if(o->nextSibling())
2083 o = o->nextSibling();
2085 RenderObject *next = 0;
2088 if(!o) return false;
2089 next = o->nextSibling();
2093 if((o->isText() && !o->isBR()) || o->isReplaced()) {
2094 o->container()->absolutePosition( xPos, yPos );
2096 xPos += static_cast<RenderText *>(o)->minXPos();
2106 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2111 RenderObject *o = m_render;
2113 if (!o->isInline() || o->isReplaced())
2115 o->absolutePosition( xPos, yPos );
2117 yPos += o->height();
2120 // find the last text/image child, to get a position
2124 else if(o->previousSibling())
2125 o = o->previousSibling();
2127 RenderObject *prev = 0;
2130 if(!o) return false;
2131 prev = o->previousSibling();
2135 if(o->isText() || o->isReplaced()) {
2136 o->container()->absolutePosition(xPos, yPos);
2138 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2140 xPos += o->xPos()+o->width();
2141 yPos += o->yPos()+o->height();
2148 QRect NodeBaseImpl::getRect() const
2151 if (!getUpperLeftCorner(xPos,yPos))
2157 if (!getLowerRightCorner(xEnd,yEnd))
2171 if ( xEnd <= xPos || yEnd <= yPos )
2172 return QRect( QPoint( xPos, yPos ), QSize() );
2174 return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2177 void NodeBaseImpl::setFocus(bool received)
2179 if (m_focused == received) return;
2181 NodeImpl::setFocus(received);
2183 if (received && isEditableBlock() && !hasChildNodes()) {
2184 getDocument()->part()->setSelection(Position(this, 0));
2187 // note that we need to recalc the style
2191 void NodeBaseImpl::setActive(bool down)
2193 if (down == active()) return;
2195 NodeImpl::setActive(down);
2197 // note that we need to recalc the style
2198 if (m_render && m_render->style()->affectedByActiveRules())
2202 unsigned long NodeBaseImpl::childNodeCount() const
2204 unsigned long count = 0;
2206 for (n = firstChild(); n; n = n->nextSibling())
2211 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2214 NodeImpl *n = firstChild();
2215 for (i = 0; i < index; i++)
2216 n = n->nextSibling();
2220 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2222 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2223 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2224 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2229 // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2230 bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2232 while (p->parentNode())
2233 p = p->parentNode();
2234 if (p->nodeType() == Node::DOCUMENT_NODE) {
2235 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2236 c->insertedIntoDocument();
2238 if (hasInsertedListeners) {
2239 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2240 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2248 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2250 // Dispatch pre-removal mutation events
2251 getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2252 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2253 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2254 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2259 bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2261 // dispatch the DOMNodeRemovedFromDocument event to all descendants
2263 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2264 if (hasRemovalListeners) {
2265 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2266 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2274 // ---------------------------------------------------------------------------
2277 NodeListImpl::NodeListImpl(NodeImpl *_rootNode)
2278 : rootNode(_rootNode),
2279 isLengthCacheValid(false),
2280 isItemCacheValid(false)
2283 rootNode->registerNodeList(this);
2286 NodeListImpl::~NodeListImpl()
2288 rootNode->unregisterNodeList(this);
2292 unsigned long NodeListImpl::recursiveLength( NodeImpl *start ) const
2297 if (isLengthCacheValid && start == rootNode) {
2298 return cachedLength;
2301 unsigned long len = 0;
2303 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2304 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2307 len+= recursiveLength(n);
2311 if (start == rootNode) {
2313 isLengthCacheValid = true;
2319 NodeImpl *NodeListImpl::recursiveItem ( unsigned long offset, NodeImpl *start) const
2321 int remainingOffset = offset;
2323 start = rootNode->firstChild();
2324 if (isItemCacheValid) {
2325 if (offset == lastItemOffset) {
2327 } else if (offset > lastItemOffset) {
2329 remainingOffset -= lastItemOffset;
2334 NodeImpl *n = start;
2337 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2338 if (nodeMatches(n)) {
2339 if (!remainingOffset) {
2341 lastItemOffset = offset;
2342 isItemCacheValid = 1;
2349 n = n->traverseNextNode(rootNode);
2352 return 0; // no matching node in this subtree
2355 NodeImpl *NodeListImpl::itemById (const DOMString& elementId) const
2357 if (rootNode->isDocumentNode() || rootNode->inDocument()) {
2358 NodeImpl *node = rootNode->getDocument()->getElementById(elementId);
2360 if (node == NULL || !nodeMatches(node))
2363 for (NodeImpl *p = node->parentNode(); p; p = p->parentNode()) {
2371 unsigned long l = length();
2373 for ( unsigned long i = 0; i < l; i++ ) {
2374 NodeImpl *node = item(i);
2376 if ( static_cast<ElementImpl *>(node)->getIDAttribute() == elementId ) {
2385 void NodeListImpl::rootNodeSubtreeModified()
2387 isLengthCacheValid = false;
2388 isItemCacheValid = false;
2392 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2397 unsigned long ChildNodeListImpl::length() const
2399 unsigned long len = 0;
2401 for(n = rootNode->firstChild(); n != 0; n = n->nextSibling())
2407 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2409 unsigned int pos = 0;
2410 NodeImpl *n = rootNode->firstChild();
2412 while( n != 0 && pos < index )
2414 n = n->nextSibling();
2421 bool ChildNodeListImpl::nodeMatches(NodeImpl *testNode) const
2423 return testNode->parentNode() == rootNode;
2426 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2428 m_id(_id & _idMask),
2433 unsigned long TagNodeListImpl::length() const
2435 return recursiveLength();
2438 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2440 return recursiveItem( index );
2443 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2445 return ( testNode->isElementNode() &&
2446 (testNode->id() & m_idMask) == m_id);
2449 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2450 : NodeListImpl(n), nodeName(t)
2454 unsigned long NameNodeListImpl::length() const
2456 return recursiveLength();
2459 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2461 return recursiveItem( index );
2464 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2466 return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2469 // ---------------------------------------------------------------------------
2471 NamedNodeMapImpl::NamedNodeMapImpl()
2475 NamedNodeMapImpl::~NamedNodeMapImpl()
2479 // ----------------------------------------------------------------------------
2483 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2484 : NamedNodeMapImpl()
2486 m_doc = doc->document();
2487 m_contents = new QPtrList<NodeImpl>;
2490 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2492 while (m_contents->count() > 0)
2493 m_contents->take(0)->deref();
2498 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2500 QPtrListIterator<NodeImpl> it(*m_contents);
2501 for (; it.current(); ++it)
2502 if (it.current()->nodeName() == name)
2503 return it.current();
2507 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2509 // can't modify this list through standard DOM functions
2510 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2511 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2515 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2517 // can't modify this list through standard DOM functions
2518 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2519 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2523 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2525 // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2526 // (also for other similar methods)
2527 if (index >= m_contents->count())
2530 return m_contents->at(index);
2533 unsigned long GenericRONamedNodeMapImpl::length( ) const
2535 return m_contents->count();
2538 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2539 const DOMString &localName,
2540 int &/*exceptioncode*/ ) const
2542 NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2543 localName.implementation(), true);
2545 QPtrListIterator<NodeImpl> it(*m_contents);
2546 for (; it.current(); ++it)
2547 if (it.current()->id() == searchId)
2548 return it.current();
2553 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2555 // can't modify this list through standard DOM functions
2556 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2557 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2561 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2562 const DOMString &/*localName*/,
2563 int &exceptioncode )
2565 // can't modify this list through standard DOM functions
2566 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2570 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2572 // The spec says that in the case of duplicates we only keep the first one
2573 int exceptioncode = 0;
2574 if (getNamedItem(n->nodeName(),exceptioncode))
2578 m_contents->append(n);