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 *, NodeImpl *, int &exceptioncode )
165 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
169 NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode )
171 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
175 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
177 exceptioncode = DOMException::NOT_FOUND_ERR;
181 NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode )
183 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
187 void NodeImpl::remove(int &exceptioncode)
191 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
195 parentNode()->removeChild(this, exceptioncode);
198 bool NodeImpl::hasChildNodes( ) const
203 void NodeImpl::normalize ()
205 // ### normalize attributes? (when we store attributes using child nodes)
206 int exceptioncode = 0;
207 NodeImpl *child = firstChild();
209 // Recursively go through the subtree beneath us, normalizing all nodes. In the case
210 // where there are two adjacent text nodes, they are merged together
212 NodeImpl *nextChild = child->nextSibling();
214 if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
215 // Current child and the next one are both text nodes... merge them
216 TextImpl *currentText = static_cast<TextImpl*>(child);
217 TextImpl *nextText = static_cast<TextImpl*>(nextChild);
219 currentText->appendData(nextText->data(),exceptioncode);
223 removeChild(nextChild,exceptioncode);
234 DOMString NodeImpl::prefix() const
236 // For nodes other than elements and attributes, the prefix is always null
240 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
242 // The spec says that for nodes other than elements and attributes, prefix is always null.
243 // It does not say what to do when the user tries to set the prefix on another type of
244 // node, however mozilla throws a NAMESPACE_ERR exception
245 exceptioncode = DOMException::NAMESPACE_ERR;
248 DOMString NodeImpl::localName() const
253 void NodeImpl::setFirstChild(NodeImpl *)
257 void NodeImpl::setLastChild(NodeImpl *)
261 NodeImpl *NodeImpl::addChild(NodeImpl *)
266 QString NodeImpl::toHTML() const
268 return recursive_toHTML(true);
271 static QString escapeHTML( const QString& in )
274 for ( unsigned int i = 0; i < in.length(); ++i ) {
275 switch( in[i].latin1() ) {
293 QString NodeImpl::startMarkup(const DOM::RangeImpl *range) const
295 unsigned short type = nodeType();
296 if (type == Node::TEXT_NODE) {
297 DOMString str = nodeValue().copy();
300 if (this == range->endContainer(exceptionCode)) {
301 str.truncate(range->endOffset(exceptionCode));
303 if (this == range->startContainer(exceptionCode)) {
304 str.remove(0, range->startOffset(exceptionCode));
307 Id parentID = parentNode()->id();
308 bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
309 return dontEscape ? str.string() : escapeHTML(str.string());
310 } else if (type != Node::DOCUMENT_NODE) {
311 QString markup = QChar('<') + nodeName().string();
312 if (type == Node::ELEMENT_NODE) {
313 const ElementImpl *el = static_cast<const ElementImpl *>(this);
314 NamedAttrMapImpl *attrs = el->attributes();
315 unsigned long length = attrs->length();
316 for (unsigned int i=0; i<length; i++) {
317 AttributeImpl *attr = attrs->attributeItem(i);
318 markup += " " + getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
321 markup += isHTMLElement() ? ">" : "/>";
327 QString NodeImpl::endMarkup(void) const
329 if ((!isHTMLElement() || endTag[id()] != FORBIDDEN) && nodeType() != Node::TEXT_NODE && nodeType() != Node::DOCUMENT_NODE) {
330 return "</" + nodeName().string() + ">";
335 QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, QPtrList<NodeImpl> *nodes)
337 // Doesn't make sense to only include children and include siblings.
338 assert(!(onlyIncludeChildren && includeSiblings));
340 for (const NodeImpl *current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
341 if (!onlyIncludeChildren) {
343 nodes->append(current);
345 me += current->startMarkup(0);
347 if (!current->isHTMLElement() || endTag[current->id()] != FORBIDDEN) {
349 if (NodeImpl *n = current->firstChild()) {
350 me += recursive_toString(n, false, true, nodes);
352 // Print my ending tag
353 if (!onlyIncludeChildren) {
354 me += current->endMarkup();
361 QString NodeImpl::recursive_toHTML(bool onlyIncludeChildren, QPtrList<NodeImpl> *nodes) const
363 return NodeImpl::recursive_toString(this, onlyIncludeChildren, false, nodes);
366 void NodeImpl::recursive_completeURLs(QString baseURL)
368 if (nodeType() == Node::ELEMENT_NODE) {
369 ElementImpl *el = static_cast<ElementImpl *>(this);
370 NamedAttrMapImpl *attrs = el->attributes();
371 unsigned long length = attrs->length();
372 for (unsigned int i=0; i<length; i++) {
373 AttributeImpl *attr = attrs->attributeItem(i);
374 if (el->isURLAttribute(attr)) {
375 el->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url());
381 if ((n = firstChild())) {
382 n->recursive_completeURLs(baseURL);
384 if ((n = nextSibling())) {
385 n->recursive_completeURLs(baseURL);
389 bool NodeImpl::isContentEditable() const
391 return m_parent ? m_parent->isContentEditable() : false;
394 QRect NodeImpl::getRect() const
397 if(m_render && m_render->absolutePosition(_x, _y))
398 return QRect( _x, _y, m_render->width(), m_render->height() );
403 void NodeImpl::setChanged(bool b)
405 if (b && !attached()) // changed compared to what?
410 NodeImpl *p = parentNode();
412 p->setHasChangedChild( true );
415 getDocument()->setDocumentChanged(true);
419 bool NodeImpl::isInline() const
421 if (m_render) return m_render->style()->display() == khtml::INLINE;
422 return !isElementNode();
425 bool NodeImpl::isFocusable() const
430 bool NodeImpl::isKeyboardFocusable() const
432 return isFocusable();
435 bool NodeImpl::isMouseFocusable() const
437 return isFocusable();
440 unsigned long NodeImpl::nodeIndex() const
442 NodeImpl *_tempNode = previousSibling();
443 unsigned long count=0;
444 for( count=0; _tempNode; count++ )
445 _tempNode = _tempNode->previousSibling();
449 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
452 case EventImpl::DOMSUBTREEMODIFIED_EVENT:
453 getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
455 case EventImpl::DOMNODEINSERTED_EVENT:
456 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
458 case EventImpl::DOMNODEREMOVED_EVENT:
459 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
461 case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
462 getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
464 case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
465 getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
467 case EventImpl::DOMATTRMODIFIED_EVENT:
468 getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
470 case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
471 getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
477 RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
478 if (!m_regdListeners) {
479 m_regdListeners = new QPtrList<RegisteredEventListener>;
480 m_regdListeners->setAutoDelete(true);
485 // remove existing identical listener set with identical arguments - the DOM2
486 // spec says that "duplicate instances are discarded" in this case.
487 removeEventListener(id,listener,useCapture);
489 m_regdListeners->append(rl);
493 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
495 if (!m_regdListeners) // nothing to remove
498 RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
500 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
501 for (; it.current(); ++it)
502 if (*(it.current()) == rl) {
503 m_regdListeners->removeRef(it.current());
508 void NodeImpl::removeHTMLEventListener(int id)
510 if (!m_regdListeners) // nothing to remove
513 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
514 for (; it.current(); ++it)
515 if (it.current()->id == id &&
516 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
517 m_regdListeners->removeRef(it.current());
522 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
524 // in case we already have it, we don't want removeHTMLEventListener to destroy it
527 removeHTMLEventListener(id);
530 addEventListener(id,listener,false);
535 EventListener *NodeImpl::getHTMLEventListener(int id)
537 if (!m_regdListeners)
540 QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
541 for (; it.current(); ++it)
542 if (it.current()->id == id &&
543 it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
544 return it.current()->listener;
550 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
554 evt->setTarget(this);
556 // We've had at least one report of a crash on a page where document is nil here.
557 // Unfortunately that page no longer exists, but we'll make this code robust against
559 // FIXME: Much code in this class assumes document is non-nil; it would be better to
560 // ensure that document can never be nil.
561 KHTMLPart *part = nil;
562 KHTMLView *view = nil;
564 if (document && document->document()) {
565 part = document->document()->part();
566 view = document->document()->view();
567 // Since event handling code could cause this object to be deleted, grab a reference to the view now
572 bool ret = dispatchGenericEvent( evt, exceptioncode );
574 // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
575 // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
576 // So there is no need for the interpreter to keep the event in it's cache
577 if (tempEvent && part && part->jScript())
578 part->jScript()->finishedWithEvent(evt);
588 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
592 // ### check that type specified
594 // work out what nodes to send event to
595 QPtrList<NodeImpl> nodeChain;
597 for (n = this; n; n = n->parentNode()) {
599 nodeChain.prepend(n);
602 // trigger any capturing event handlers on our way down
603 evt->setEventPhase(Event::CAPTURING_PHASE);
604 QPtrListIterator<NodeImpl> it(nodeChain);
605 for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
606 evt->setCurrentTarget(it.current());
607 it.current()->handleLocalEvents(evt,true);
610 // dispatch to the actual target node
612 if (!evt->propagationStopped()) {
613 evt->setEventPhase(Event::AT_TARGET);
614 evt->setCurrentTarget(it.current());
616 // Capturing first. -dwh
617 it.current()->handleLocalEvents(evt,true);
619 // Bubbling second. -dwh
620 if (!evt->propagationStopped())
621 it.current()->handleLocalEvents(evt,false);
625 // ok, now bubble up again (only non-capturing event handlers will be called)
626 // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
627 // no. the DOM specs says:
628 // The chain of EventTargets from the event target to the top of the tree
629 // is determined before the initial dispatch of the event.
630 // If modifications occur to the tree during event processing,
631 // event flow will proceed based on the initial state of the tree.
633 // since the initial dispatch is before the capturing phase,
634 // there's no need to recalculate the node chain.
637 if (evt->bubbles()) {
638 evt->setEventPhase(Event::BUBBLING_PHASE);
639 for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
640 evt->setCurrentTarget(it.current());
641 it.current()->handleLocalEvents(evt,false);
645 evt->setCurrentTarget(0);
646 evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
647 // anything about the default event handler phase.
650 if (evt->bubbles()) {
651 // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
654 for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
655 it.current()->defaultEventHandler(evt);
658 // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions
659 // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or
660 // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code.
661 if (!evt->defaultPrevented() && !disabled())
662 if (evt->id() == EventImpl::KHTML_CLICK_EVENT)
663 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1);
664 else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT)
665 dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2);
667 // deref all nodes in chain
669 for (; it.current(); ++it)
670 it.current()->deref(); // this may delete us
672 DocumentImpl::updateDocumentsRendering();
674 bool defaultPrevented = evt->defaultPrevented();
678 return !defaultPrevented; // ### what if defaultPrevented was called before dispatchEvent?
681 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
683 int exceptioncode = 0;
684 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
685 return dispatchEvent(evt,exceptioncode,true);
688 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
690 int exceptioncode = 0;
691 EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
694 DocumentPtr *doc = document;
696 bool r = dispatchGenericEvent( evt, exceptioncode );
697 if (!evt->defaultPrevented() && doc->document())
698 doc->document()->defaultEventHandler(evt);
700 if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
701 // For onload events, send them to the enclosing frame only.
702 // This is a DOM extension and is independent of bubbling/capturing rules of
703 // the DOM. You send the event only to the enclosing frame. It does not
704 // bubble through the parent document.
705 DOM::ElementImpl* elt = doc->document()->ownerElement();
706 if (elt && (elt->getDocument()->domain().isNull() ||
707 elt->getDocument()->domain() == doc->document()->domain())) {
708 // We also do a security check, since we don't want to allow the enclosing
709 // iframe to see loads of child documents in other domains.
710 evt->setCurrentTarget(elt);
713 elt->handleLocalEvents(evt,true);
716 if (!evt->propagationStopped())
717 elt->handleLocalEvents(evt,false);
718 r = !evt->defaultPrevented();
728 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
730 bool cancelable = true;
731 int detail = overrideDetail; // defaults to 0
732 EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
734 evtId = static_cast<EventImpl::EventId>(overrideId);
737 switch (_mouse->type()) {
738 case QEvent::MouseButtonPress:
739 evtId = EventImpl::MOUSEDOWN_EVENT;
741 case QEvent::MouseButtonRelease:
742 evtId = EventImpl::MOUSEUP_EVENT;
744 case QEvent::MouseButtonDblClick:
745 evtId = EventImpl::CLICK_EVENT;
746 detail = 1; // ### support for multiple double clicks
748 case QEvent::MouseMove:
749 evtId = EventImpl::MOUSEMOVE_EVENT;
756 if (evtId == EventImpl::UNKNOWN_EVENT)
757 return false; // shouldn't happen
760 int exceptioncode = 0;
763 // Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
764 // our khtmlview's coord system. This works for QMouseEvents coming from Cocoa because those events
765 // hold the location from the NSEvent. The QMouseEvent param here was made by other khtml code, so it
766 // will be a "proper" QT event with coords in terms of this widget. So in WebCore it would never be
767 // right to pass coords from _mouse to viewportToContents().
769 // int clientX, clientY;
770 // viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
771 int clientX = _mouse->x(); // ### adjust to be relative to view
772 int clientY = _mouse->y(); // ### adjust to be relative to view
777 KHTMLView *view = document->document()->view();
779 // This gets us as far as NSWindow coords
780 QPoint windowLoc = view->contentsToViewport(_mouse->pos());
781 // Then from NSWindow coords to screen coords
782 QPoint screenLoc = view->viewportToGlobal(windowLoc);
783 screenX = screenLoc.x();
784 screenY = screenLoc.y();
786 screenX = _mouse->x();
787 screenY = _mouse->y();
790 int screenX = _mouse->globalX();
791 int screenY = _mouse->globalY();
795 switch (_mouse->button()) {
802 case Qt::RightButton:
808 bool ctrlKey = (_mouse->state() & Qt::ControlButton);
809 bool altKey = (_mouse->state() & Qt::AltButton);
810 bool shiftKey = (_mouse->state() & Qt::ShiftButton);
811 bool metaKey = false; // ### qt support?
813 EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
814 detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
816 return dispatchEvent(evt,exceptioncode,true);
820 bool NodeImpl::dispatchUIEvent(int _id, int detail)
822 assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
823 _id != EventImpl::DOMFOCUSOUT_EVENT &&
824 _id != EventImpl::DOMACTIVATE_EVENT)));
826 bool cancelable = false;
827 if (_id == EventImpl::DOMACTIVATE_EVENT)
830 int exceptioncode = 0;
831 UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
832 cancelable,getDocument()->defaultView(),detail);
833 return dispatchEvent(evt,exceptioncode,true);
836 void NodeImpl::registerNodeList(NodeListImpl *list)
839 m_nodeLists = new QPtrDict<NodeListImpl>;
842 m_nodeLists->insert(list, list);
845 void NodeImpl::unregisterNodeList(NodeListImpl *list)
850 m_nodeLists->remove(list);
853 void NodeImpl::notifyLocalNodeListsSubtreeModified()
858 QPtrDictIterator<NodeListImpl> i(*m_nodeLists);
860 while (NodeListImpl *list = i.current()) {
861 list->rootNodeSubtreeModified();
865 void NodeImpl::notifyNodeListsSubtreeModified()
867 for (NodeImpl *n = this; n; n = n->parentNode()) {
868 n->notifyLocalNodeListsSubtreeModified();
872 bool NodeImpl::dispatchSubtreeModifiedEvent()
874 notifyNodeListsSubtreeModified();
876 if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
878 int exceptioncode = 0;
879 return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
880 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
883 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
885 int exceptioncode = 0;
886 //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
887 KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
888 keyboardEventImpl->ref();
889 bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
892 // we want to return false if default is prevented (already taken care of)
893 // or if the element is default-handled by the DOM. Otherwise we let it just
894 // let it get handled by AppKit
895 if (keyboardEventImpl->defaultHandled())
897 // the default event handler should accept() the internal QKeyEvent
898 // to prevent the view from further evaluating it.
899 if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
903 keyboardEventImpl->deref();
907 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
909 if (!m_regdListeners)
912 if (disabled() && evt->isMouseEvent())
915 QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
916 QPtrListIterator<RegisteredEventListener> it(listenersCopy);
918 for (; it.current(); ++it) {
919 if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
920 it.current()->listener->handleEvent(ev, false);
925 void NodeImpl::defaultEventHandler(EventImpl *evt)
929 unsigned long NodeImpl::childNodeCount() const
934 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
939 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
944 return nextSibling();
945 const NodeImpl *n = this;
946 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
949 return n->nextSibling();
953 NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const
956 return nextSibling();
957 const NodeImpl *n = this;
958 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
961 return n->nextSibling();
965 NodeImpl *NodeImpl::traversePreviousNode() const
967 if (previousSibling()) {
968 NodeImpl *n = previousSibling();
969 while (n->lastChild())
973 else if (parentNode()) {
981 NodeImpl *NodeImpl::traversePreviousNodePostOrder(NodeImpl *stayWithin) const
985 if (previousSibling())
986 return previousSibling();
987 const NodeImpl *n = this;
988 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
991 return n->previousSibling();
995 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
997 // Perform error checking as required by spec for setting Node.prefix. Used by
998 // ElementImpl::setPrefix() and AttrImpl::setPrefix()
1000 // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
1001 if (!Element::khtmlValidPrefix(_prefix)) {
1002 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
1006 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1008 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1012 // NAMESPACE_ERR: - Raised if the specified prefix is malformed
1013 // - if the namespaceURI of this node is null,
1014 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
1015 // "http://www.w3.org/XML/1998/namespace",
1016 // - if this node is an attribute and the specified prefix is "xmlns" and
1017 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
1018 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
1019 if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
1020 (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
1021 exceptioncode = DOMException::NAMESPACE_ERR;
1026 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
1028 // Perform error checking as required by spec for adding a new child. Used by
1029 // appendChild(), replaceChild() and insertBefore()
1031 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
1033 exceptioncode = DOMException::NOT_FOUND_ERR;
1037 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
1039 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1043 bool shouldAdoptChild = false;
1045 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
1046 // created this node.
1047 // We assume that if newChild is a DocumentFragment, all children are created from the same document
1048 // as the fragment itself (otherwise they could not have been added as children)
1049 if (newChild->getDocument() != getDocument()) {
1050 // but if the child is not in a document yet then loosen the
1051 // restriction, so that e.g. creating an element with the Option()
1052 // constructor and then adding it to a different document works,
1053 // as it does in Mozilla and Mac IE.
1054 if (!newChild->inDocument()) {
1055 shouldAdoptChild = true;
1057 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1062 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1063 // newChild node, or if the node to append is one of this node's ancestors.
1065 // check for ancestor/same node
1066 if (newChild == this || isAncestor(newChild)) {
1067 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1071 // only do this once we know there won't be an exception
1072 if (shouldAdoptChild) {
1073 KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
1074 newChild->setDocument(getDocument()->docPtr());
1078 bool NodeImpl::isAncestor(const NodeImpl *other) const
1080 // Return true if other is an ancestor of this, otherwise false
1081 for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1088 bool NodeImpl::childAllowed( NodeImpl *newChild )
1090 return childTypeAllowed(newChild->nodeType());
1093 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1095 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
1096 // explicit inheritance of non-inherited properties and so you end up not re-resolving
1097 // style in cases where you need to.
1098 StyleChange ch = NoInherit;
1099 EDisplay display1 = s1 ? s1->display() : NONE;
1100 bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1101 EDisplay display2 = s2 ? s2->display() : NONE;
1102 bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1103 if (display1 != display2 || fl1 != fl2)
1105 else if ( !s1 || !s2 )
1107 else if ( *s1 == *s2 )
1109 else if ( s1->inheritedNotEqual( s2 ) )
1115 void NodeImpl::dump(QTextStream *stream, QString ind) const
1117 // ### implement dump() for all appropriate subclasses
1119 if (m_hasId) { *stream << " hasId"; }
1120 if (m_hasClass) { *stream << " hasClass"; }
1121 if (m_hasStyle) { *stream << " hasStyle"; }
1122 if (m_specified) { *stream << " specified"; }
1123 if (m_focused) { *stream << " focused"; }
1124 if (m_active) { *stream << " active"; }
1125 if (m_styleElement) { *stream << " styleElement"; }
1126 if (m_implicit) { *stream << " implicit"; }
1128 *stream << " tabIndex=" << m_tabIndex;
1129 if (m_regdListeners)
1130 *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1133 NodeImpl *child = firstChild();
1136 *stream << ind << child->nodeName().string().ascii() << ": ";
1137 child->dump(stream,ind+" ");
1138 child = child->nextSibling();
1143 void NodeImpl::attach()
1145 assert(!attached());
1146 assert(!m_render || (m_render->style() && m_render->parent()));
1150 void NodeImpl::detach()
1152 // assert(m_attached);
1161 bool NodeImpl::maintainsState()
1166 QString NodeImpl::state()
1168 return QString::null;
1171 void NodeImpl::restoreState(QStringList &/*states*/)
1175 void NodeImpl::insertedIntoDocument()
1177 setInDocument(true);
1180 void NodeImpl::removedFromDocument()
1182 setInDocument(false);
1185 void NodeImpl::childrenChanged()
1189 bool NodeImpl::disabled() const
1194 bool NodeImpl::isReadOnly()
1196 // Entity & Entity Reference nodes and their descendants are read-only
1199 if (n->nodeType() == Node::ENTITY_NODE ||
1200 n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1202 n = n->parentNode();
1207 NodeImpl *NodeImpl::previousEditable() const
1209 NodeImpl *node = previousLeafNode();
1211 if (node->isContentEditable())
1213 node = node->previousLeafNode();
1218 NodeImpl *NodeImpl::nextEditable() const
1220 NodeImpl *node = nextLeafNode();
1222 if (node->isContentEditable())
1224 node = node->nextLeafNode();
1229 RenderObject * NodeImpl::previousRenderer()
1231 for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1233 return n->renderer();
1238 RenderObject * NodeImpl::nextRenderer()
1240 for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1242 return n->renderer();
1247 bool NodeImpl::isAtomicNode() const
1249 return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1252 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1254 if (previousSibling()) {
1255 NodeImpl *n = previousSibling();
1256 while (!n->isAtomicNode() && n->lastChild())
1260 else if (parentNode()) {
1261 return parentNode();
1268 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1270 if (!isAtomicNode() && firstChild())
1271 return firstChild();
1273 return nextSibling();
1274 const NodeImpl *n = this;
1275 while (n && !n->nextSibling())
1276 n = n->parentNode();
1278 return n->nextSibling();
1282 NodeImpl *NodeImpl::previousLeafNode() const
1284 NodeImpl *node = previousNodeConsideringAtomicNodes();
1286 if (node->isAtomicNode())
1288 node = node->previousNodeConsideringAtomicNodes();
1293 NodeImpl *NodeImpl::nextLeafNode() const
1295 NodeImpl *node = nextNodeConsideringAtomicNodes();
1297 if (node->isAtomicNode())
1299 node = node->nextNodeConsideringAtomicNodes();
1304 void NodeImpl::createRendererIfNeeded()
1308 if (!getDocument()->shouldCreateRenderers())
1312 assert(!attached());
1315 NodeImpl *parent = parentNode();
1318 RenderObject *parentRenderer = parent->renderer();
1319 if (parentRenderer && parentRenderer->canHaveChildren()) {
1320 RenderStyle *style = styleForRenderer(parentRenderer);
1322 #ifndef KHTML_NO_XBL
1323 bool resolveStyle = false;
1324 if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
1325 rendererIsNeeded(style)) {
1328 style = styleForRenderer(parentRenderer);
1331 if (rendererIsNeeded(style)) {
1333 m_render = createRenderer(getDocument()->renderArena(), style);
1334 m_render->setStyle(style);
1335 parentRenderer->addChild(m_render, nextRenderer());
1336 #ifndef KHTML_NO_XBL
1337 } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1341 style->deref(getDocument()->renderArena());
1345 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1347 return parent->style();
1350 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1352 return (getDocument()->documentElement() == this) || (style->display() != NONE);
1355 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1361 long NodeImpl::maxOffset() const
1366 long NodeImpl::caretMinOffset() const
1368 return renderer() ? renderer()->caretMinOffset() : 0;
1371 long NodeImpl::caretMaxOffset() const
1373 return renderer() ? renderer()->caretMaxOffset() : 1;
1376 unsigned long NodeImpl::caretMaxRenderedOffset() const
1378 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1381 bool NodeImpl::isBlockFlow() const
1383 return renderer() && renderer()->isBlockFlow();
1386 bool NodeImpl::isEditableBlock() const
1388 return isContentEditable() && isBlockFlow();
1391 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1393 NodeImpl *n = const_cast<NodeImpl *>(this);
1395 return static_cast<ElementImpl *>(n);
1398 n = n->parentNode();
1401 if (n->isBlockFlow() || n->id() == ID_BODY)
1402 return static_cast<ElementImpl *>(n);
1407 ElementImpl *NodeImpl::enclosingInlineElement() const
1409 NodeImpl *n = const_cast<NodeImpl *>(this);
1413 p = n->parentNode();
1414 if (!p || p->isBlockFlow() || p->id() == ID_BODY)
1415 return static_cast<ElementImpl *>(n);
1418 ASSERT_NOT_REACHED();
1422 ElementImpl *NodeImpl::rootEditableElement() const
1424 if (!isContentEditable())
1427 NodeImpl *n = const_cast<NodeImpl *>(this);
1428 if (n->id() == ID_BODY)
1429 return static_cast<ElementImpl *>(n);
1431 NodeImpl *result = n->isEditableBlock() ? n : 0;
1433 n = n->parentNode();
1434 if (!n || !n->isContentEditable())
1436 if (n->id() == ID_BODY) {
1440 if (n->isBlockFlow())
1443 return static_cast<ElementImpl *>(result);
1446 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1448 return n ? rootEditableElement() == n->rootEditableElement() : false;
1451 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1453 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1457 NodeImpl::Id NodeImpl::identifier() const
1464 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1470 if (s.length() == 0)
1475 strncpy(buffer, result.string().latin1(), length - 1);
1479 //-------------------------------------------------------------------------
1481 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1488 NodeBaseImpl::~NodeBaseImpl()
1490 //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1492 // Avoid deep recursion when destroying the node tree.
1493 static bool alreadyInsideDestructor;
1494 bool topLevel = !alreadyInsideDestructor;
1496 alreadyInsideDestructor = true;
1498 // List of nodes to be deleted.
1499 static NodeImpl *head;
1500 static NodeImpl *tail;
1502 // We have to tell all children that their parent has died.
1506 for( n = _first; n != 0; n = next ) {
1507 next = n->nextSibling();
1508 n->setPreviousSibling(0);
1509 n->setNextSibling(0);
1512 if ( !n->refCount() ) {
1513 // Add the node to the list of nodes to be deleted.
1514 // Reuse the nextSibling pointer for this purpose.
1516 tail->setNextSibling(n);
1523 // Only for the top level call, do the actual deleting.
1525 while ((n = head) != 0) {
1526 next = n->nextSibling();
1527 n->setNextSibling(0);
1536 alreadyInsideDestructor = false;
1541 NodeImpl *NodeBaseImpl::firstChild() const
1546 NodeImpl *NodeBaseImpl::lastChild() const
1551 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1555 // insertBefore(...,null) is equivalent to appendChild()
1557 return appendChild(newChild, exceptioncode);
1559 // Make sure adding the new child is ok
1560 checkAddChild(newChild, exceptioncode);
1564 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1565 if (refChild->parentNode() != this) {
1566 exceptioncode = DOMException::NOT_FOUND_ERR;
1570 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1572 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1573 // Just return the document fragment
1574 if (isFragment && !newChild->firstChild())
1577 // Now actually add the child(ren)
1578 NodeImpl *nextChild;
1579 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1581 NodeImpl *prev = refChild->previousSibling();
1582 if ( prev == newChild || refChild == newChild ) // nothing to do
1586 nextChild = isFragment ? child->nextSibling() : 0;
1588 // If child is already present in the tree, first remove it
1589 NodeImpl *newParent = child->parentNode();
1591 newParent->removeChild( child, exceptioncode );
1592 if ( exceptioncode )
1595 // Add child in the correct position
1597 prev->setNextSibling(child);
1600 refChild->setPreviousSibling(child);
1601 child->setParent(this);
1602 child->setPreviousSibling(prev);
1603 child->setNextSibling(refChild);
1605 // Add child to the rendering tree
1606 // ### should we detach() it first if it's already attached?
1607 if (attached() && !child->attached())
1610 // Dispatch the mutation events
1611 dispatchChildInsertedEvents(child,exceptioncode);
1617 getDocument()->setDocumentChanged(true);
1618 dispatchSubtreeModifiedEvent();
1622 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1626 if ( oldChild == newChild ) // nothing to do
1629 // Make sure adding the new child is ok
1630 checkAddChild(newChild, exceptioncode);
1634 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1635 if (!oldChild || oldChild->parentNode() != this) {
1636 exceptioncode = DOMException::NOT_FOUND_ERR;
1640 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1641 NodeImpl *nextChild;
1642 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1645 // Remove the old child
1646 NodeImpl *prev = oldChild->previousSibling();
1647 NodeImpl *next = oldChild->nextSibling();
1649 removeChild(oldChild, exceptioncode);
1653 // Add the new child(ren)
1655 nextChild = isFragment ? child->nextSibling() : 0;
1657 // If child is already present in the tree, first remove it
1658 NodeImpl *newParent = child->parentNode();
1660 newParent->removeChild( child, exceptioncode );
1664 // Add child in the correct position
1665 if (prev) prev->setNextSibling(child);
1666 if (next) next->setPreviousSibling(child);
1667 if(!prev) _first = child;
1668 if(!next) _last = child;
1669 child->setParent(this);
1670 child->setPreviousSibling(prev);
1671 child->setNextSibling(next);
1673 // Add child to the rendering tree
1674 // ### should we detach() it first if it's already attached?
1675 if (attached() && !child->attached())
1678 // Dispatch the mutation events
1679 dispatchChildInsertedEvents(child,exceptioncode);
1685 // ### set style in case it's attached
1686 getDocument()->setDocumentChanged(true);
1687 dispatchSubtreeModifiedEvent();
1691 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1695 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1697 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1701 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1702 if (!oldChild || oldChild->parentNode() != this) {
1703 exceptioncode = DOMException::NOT_FOUND_ERR;
1707 // Dispatch pre-removal mutation events
1708 getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1709 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1710 oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1711 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1716 dispatchChildRemovalEvents(oldChild,exceptioncode);
1720 // Remove from rendering tree
1721 if (oldChild->attached())
1725 NodeImpl *prev, *next;
1726 prev = oldChild->previousSibling();
1727 next = oldChild->nextSibling();
1729 if(next) next->setPreviousSibling(prev);
1730 if(prev) prev->setNextSibling(next);
1731 if(_first == oldChild) _first = next;
1732 if(_last == oldChild) _last = prev;
1734 oldChild->setPreviousSibling(0);
1735 oldChild->setNextSibling(0);
1736 oldChild->setParent(0);
1738 getDocument()->setDocumentChanged(true);
1740 // Dispatch post-removal mutation events
1741 dispatchSubtreeModifiedEvent();
1743 if (oldChild->inDocument())
1744 oldChild->removedFromDocument();
1749 void NodeBaseImpl::removeChildren()
1752 while (NodeImpl *n = _first) {
1753 NodeImpl *next = n->nextSibling();
1757 // Fire removed from document mutation events.
1758 dispatchChildRemovalEvents(n, exceptionCode);
1762 n->setPreviousSibling(0);
1763 n->setNextSibling(0);
1766 if (n->inDocument())
1767 n->removedFromDocument();
1775 // Dispatch a single post-removal mutation event denoting a modified subtree.
1776 dispatchSubtreeModifiedEvent();
1780 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1784 // Make sure adding the new child is ok
1785 checkAddChild(newChild, exceptioncode);
1789 if ( newChild == _last ) // nothing to do
1792 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1794 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1795 // Just return the document fragment
1796 if (isFragment && !newChild->firstChild())
1799 // Now actually add the child(ren)
1800 NodeImpl *nextChild;
1801 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1804 nextChild = isFragment ? child->nextSibling() : 0;
1806 // If child is already present in the tree, first remove it
1807 NodeImpl *oldParent = child->parentNode();
1809 oldParent->removeChild( child, exceptioncode );
1814 // Append child to the end of the list
1815 child->setParent(this);
1819 child->setPreviousSibling(_last);
1820 _last->setNextSibling(child);
1825 _first = _last = child;
1828 // Add child to the rendering tree
1829 // ### should we detach() it first if it's already attached?
1830 if (attached() && !child->attached())
1833 // Dispatch the mutation events
1834 dispatchChildInsertedEvents(child,exceptioncode);
1839 getDocument()->setDocumentChanged(true);
1840 // ### set style in case it's attached
1841 dispatchSubtreeModifiedEvent();
1845 bool NodeBaseImpl::hasChildNodes ( ) const
1850 // not part of the DOM
1851 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1856 void NodeBaseImpl::setLastChild(NodeImpl *child)
1861 // check for same source document:
1862 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1865 DocumentImpl *ownerDocThis = getDocument();
1866 DocumentImpl *ownerDocNew = getDocument();
1867 if(ownerDocThis != ownerDocNew) {
1868 kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1869 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1875 // check for being (grand-..)father:
1876 // ### remove in favor or isAncestor()
1877 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1879 //check if newChild is parent of this...
1881 for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1883 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1889 // check for being child:
1890 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1892 if(!oldChild || oldChild->parentNode() != this) {
1893 exceptioncode = DOMException::NOT_FOUND_ERR;
1899 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1901 // do not add applyChanges here! This function is only used during parsing
1903 // short check for consistency with DTD
1904 if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1906 //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1911 newChild->setParent(this);
1915 newChild->setPreviousSibling(_last);
1916 _last->setNextSibling(newChild);
1921 _first = _last = newChild;
1924 newChild->insertedIntoDocument();
1927 if(newChild->nodeType() == Node::ELEMENT_NODE)
1932 void NodeBaseImpl::attach()
1934 NodeImpl *child = _first;
1938 child = child->nextSibling();
1943 void NodeBaseImpl::detach()
1945 NodeImpl *child = _first;
1948 NodeImpl* prev = child;
1949 child = child->nextSibling();
1955 void NodeBaseImpl::insertedIntoDocument()
1957 NodeImpl::insertedIntoDocument();
1958 for (NodeImpl *child = _first; child; child = child->nextSibling())
1959 child->insertedIntoDocument();
1962 void NodeBaseImpl::removedFromDocument()
1964 NodeImpl::removedFromDocument();
1965 for (NodeImpl *child = _first; child; child = child->nextSibling())
1966 child->removedFromDocument();
1969 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
1971 int exceptioncode = 0;
1973 for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
1975 clone->appendChild(n->cloneNode(true),exceptioncode);
1979 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
1980 DOMStringImpl* localName )
1982 if (!localName) return 0;
1984 NodeImpl::Id idMask = namespaceMask | localNameMask;
1985 if (localName->l && localName->s[0] == '*')
1986 idMask &= ~localNameMask;
1987 if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
1988 idMask &= ~namespaceMask;
1990 Id id = 0; // 0 means "all items"
1991 if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
1993 id = getDocument()->tagId( namespaceURI, localName, true);
1994 if ( !id ) // not found -> we want to return an empty list, not "all items"
1995 id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
1998 return new TagNodeListImpl( this, id, idMask );
2001 // I don't like this way of implementing the method, but I didn't find any
2003 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
2007 RenderObject *o = m_render;
2009 if ( !o->isInline() || o->isReplaced() ) {
2010 o->absolutePosition( xPos, yPos );
2014 // find the next text/image child, to get a position
2017 o = o->firstChild();
2018 else if(o->nextSibling())
2019 o = o->nextSibling();
2021 RenderObject *next = 0;
2024 if(!o) return false;
2025 next = o->nextSibling();
2029 if((o->isText() && !o->isBR()) || o->isReplaced()) {
2030 o->container()->absolutePosition( xPos, yPos );
2032 xPos += static_cast<RenderText *>(o)->minXPos();
2042 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2047 RenderObject *o = m_render;
2049 if (!o->isInline() || o->isReplaced())
2051 o->absolutePosition( xPos, yPos );
2053 yPos += o->height();
2056 // find the last text/image child, to get a position
2060 else if(o->previousSibling())
2061 o = o->previousSibling();
2063 RenderObject *prev = 0;
2066 if(!o) return false;
2067 prev = o->previousSibling();
2071 if(o->isText() || o->isReplaced()) {
2072 o->container()->absolutePosition(xPos, yPos);
2074 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2076 xPos += o->xPos()+o->width();
2077 yPos += o->yPos()+o->height();
2084 QRect NodeBaseImpl::getRect() const
2087 if (!getUpperLeftCorner(xPos,yPos))
2093 if (!getLowerRightCorner(xEnd,yEnd))
2107 if ( xEnd <= xPos || yEnd <= yPos )
2108 return QRect( QPoint( xPos, yPos ), QSize() );
2110 return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2113 void NodeBaseImpl::setFocus(bool received)
2115 if (m_focused == received) return;
2117 NodeImpl::setFocus(received);
2119 if (received && isEditableBlock() && !hasChildNodes()) {
2120 getDocument()->part()->setSelection(Position(this, 0));
2123 // note that we need to recalc the style
2127 void NodeBaseImpl::setActive(bool down)
2129 if (down == active()) return;
2131 NodeImpl::setActive(down);
2133 // note that we need to recalc the style
2134 if (m_render && m_render->style()->affectedByActiveRules())
2138 unsigned long NodeBaseImpl::childNodeCount() const
2140 unsigned long count = 0;
2142 for (n = firstChild(); n; n = n->nextSibling())
2147 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2150 NodeImpl *n = firstChild();
2151 for (i = 0; i < index; i++)
2152 n = n->nextSibling();
2156 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2158 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2159 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2160 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2165 // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2166 bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2168 while (p->parentNode())
2169 p = p->parentNode();
2170 if (p->nodeType() == Node::DOCUMENT_NODE) {
2171 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2172 c->insertedIntoDocument();
2174 if (hasInsertedListeners) {
2175 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2176 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2184 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2186 // Dispatch pre-removal mutation events
2187 getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2188 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2189 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2190 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2195 bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2197 // dispatch the DOMNOdeRemovedFromDocument event to all descendants
2199 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2200 if (hasRemovalListeners) {
2201 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2202 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2210 // ---------------------------------------------------------------------------
2213 NodeListImpl::NodeListImpl(NodeImpl *_rootNode)
2215 rootNode = _rootNode;
2217 rootNode->registerNodeList(this);
2220 NodeListImpl::~NodeListImpl()
2222 rootNode->unregisterNodeList(this);
2226 unsigned long NodeListImpl::recursiveLength( NodeImpl *start ) const
2231 if (isCacheValid && start == rootNode) {
2232 return cachedLength;
2235 unsigned long len = 0;
2237 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2238 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2241 len+= recursiveLength(n);
2245 if (start == rootNode) {
2247 isCacheValid = true;
2253 NodeImpl *NodeListImpl::recursiveItem ( unsigned long &offset, NodeImpl *start ) const
2258 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2259 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2264 NodeImpl *depthSearch= recursiveItem(offset, n);
2270 return 0; // no matching node in this subtree
2273 void NodeListImpl::rootNodeSubtreeModified()
2275 isCacheValid = false;
2279 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2284 unsigned long ChildNodeListImpl::length() const
2286 unsigned long len = 0;
2288 for(n = rootNode->firstChild(); n != 0; n = n->nextSibling())
2294 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2296 unsigned int pos = 0;
2297 NodeImpl *n = rootNode->firstChild();
2299 while( n != 0 && pos < index )
2301 n = n->nextSibling();
2308 bool ChildNodeListImpl::nodeMatches( NodeImpl */*testNode*/ ) const
2313 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2314 : NodeListImpl(n), m_id(_id & _idMask), m_idMask(_idMask)
2318 unsigned long TagNodeListImpl::length() const
2320 return recursiveLength();
2323 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2325 return recursiveItem( index );
2328 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2330 return ( testNode->isElementNode() &&
2331 (testNode->id() & m_idMask) == m_id);
2334 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2335 : NodeListImpl(n), nodeName(t)
2339 unsigned long NameNodeListImpl::length() const
2341 return recursiveLength();
2344 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2346 return recursiveItem( index );
2349 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2351 return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2354 // ---------------------------------------------------------------------------
2356 NamedNodeMapImpl::NamedNodeMapImpl()
2360 NamedNodeMapImpl::~NamedNodeMapImpl()
2364 // ----------------------------------------------------------------------------
2368 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2369 : NamedNodeMapImpl()
2371 m_doc = doc->document();
2372 m_contents = new QPtrList<NodeImpl>;
2375 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2377 while (m_contents->count() > 0)
2378 m_contents->take(0)->deref();
2383 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2385 QPtrListIterator<NodeImpl> it(*m_contents);
2386 for (; it.current(); ++it)
2387 if (it.current()->nodeName() == name)
2388 return it.current();
2392 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2394 // can't modify this list through standard DOM functions
2395 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2396 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2400 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2402 // can't modify this list through standard DOM functions
2403 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2404 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2408 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2410 // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2411 // (also for other similar methods)
2412 if (index >= m_contents->count())
2415 return m_contents->at(index);
2418 unsigned long GenericRONamedNodeMapImpl::length( ) const
2420 return m_contents->count();
2423 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2424 const DOMString &localName,
2425 int &/*exceptioncode*/ ) const
2427 NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2428 localName.implementation(), true);
2430 QPtrListIterator<NodeImpl> it(*m_contents);
2431 for (; it.current(); ++it)
2432 if (it.current()->id() == searchId)
2433 return it.current();
2438 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2440 // can't modify this list through standard DOM functions
2441 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2442 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2446 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2447 const DOMString &/*localName*/,
2448 int &exceptioncode )
2450 // can't modify this list through standard DOM functions
2451 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2455 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2457 // The spec says that in the case of duplicates we only keep the first one
2458 int exceptioncode = 0;
2459 if (getNamedItem(n->nodeName(),exceptioncode))
2463 m_contents->append(n);