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();
866 void NodeImpl::notifyNodeListsSubtreeModified()
868 for (NodeImpl *n = this; n; n = n->parentNode()) {
869 n->notifyLocalNodeListsSubtreeModified();
873 bool NodeImpl::dispatchSubtreeModifiedEvent()
875 notifyNodeListsSubtreeModified();
877 if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
879 int exceptioncode = 0;
880 return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
881 true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
884 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
886 int exceptioncode = 0;
887 //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
888 KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
889 keyboardEventImpl->ref();
890 bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
893 // we want to return false if default is prevented (already taken care of)
894 // or if the element is default-handled by the DOM. Otherwise we let it just
895 // let it get handled by AppKit
896 if (keyboardEventImpl->defaultHandled())
898 // the default event handler should accept() the internal QKeyEvent
899 // to prevent the view from further evaluating it.
900 if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
904 keyboardEventImpl->deref();
908 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
910 if (!m_regdListeners)
913 if (disabled() && evt->isMouseEvent())
916 QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
917 QPtrListIterator<RegisteredEventListener> it(listenersCopy);
919 for (; it.current(); ++it) {
920 if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
921 it.current()->listener->handleEvent(ev, false);
926 void NodeImpl::defaultEventHandler(EventImpl *evt)
930 unsigned long NodeImpl::childNodeCount() const
935 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
940 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
945 return nextSibling();
946 const NodeImpl *n = this;
947 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
950 return n->nextSibling();
954 NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const
957 return nextSibling();
958 const NodeImpl *n = this;
959 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
962 return n->nextSibling();
966 NodeImpl *NodeImpl::traversePreviousNode() const
968 if (previousSibling()) {
969 NodeImpl *n = previousSibling();
970 while (n->lastChild())
974 else if (parentNode()) {
982 NodeImpl *NodeImpl::traversePreviousNodePostOrder(NodeImpl *stayWithin) const
986 if (previousSibling())
987 return previousSibling();
988 const NodeImpl *n = this;
989 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
992 return n->previousSibling();
996 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
998 // Perform error checking as required by spec for setting Node.prefix. Used by
999 // ElementImpl::setPrefix() and AttrImpl::setPrefix()
1001 // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
1002 if (!Element::khtmlValidPrefix(_prefix)) {
1003 exceptioncode = DOMException::INVALID_CHARACTER_ERR;
1007 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1009 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1013 // NAMESPACE_ERR: - Raised if the specified prefix is malformed
1014 // - if the namespaceURI of this node is null,
1015 // - if the specified prefix is "xml" and the namespaceURI of this node is different from
1016 // "http://www.w3.org/XML/1998/namespace",
1017 // - if this node is an attribute and the specified prefix is "xmlns" and
1018 // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
1019 // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
1020 if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
1021 (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
1022 exceptioncode = DOMException::NAMESPACE_ERR;
1027 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
1029 // Perform error checking as required by spec for adding a new child. Used by
1030 // appendChild(), replaceChild() and insertBefore()
1032 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
1034 exceptioncode = DOMException::NOT_FOUND_ERR;
1038 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
1040 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1044 bool shouldAdoptChild = false;
1046 // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
1047 // created this node.
1048 // We assume that if newChild is a DocumentFragment, all children are created from the same document
1049 // as the fragment itself (otherwise they could not have been added as children)
1050 if (newChild->getDocument() != getDocument()) {
1051 // but if the child is not in a document yet then loosen the
1052 // restriction, so that e.g. creating an element with the Option()
1053 // constructor and then adding it to a different document works,
1054 // as it does in Mozilla and Mac IE.
1055 if (!newChild->inDocument()) {
1056 shouldAdoptChild = true;
1058 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1063 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1064 // newChild node, or if the node to append is one of this node's ancestors.
1066 // check for ancestor/same node
1067 if (newChild == this || isAncestor(newChild)) {
1068 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1072 // only do this once we know there won't be an exception
1073 if (shouldAdoptChild) {
1074 KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
1075 newChild->setDocument(getDocument()->docPtr());
1079 bool NodeImpl::isAncestor(const NodeImpl *other) const
1081 // Return true if other is an ancestor of this, otherwise false
1082 for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1089 bool NodeImpl::childAllowed( NodeImpl *newChild )
1091 return childTypeAllowed(newChild->nodeType());
1094 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1096 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
1097 // explicit inheritance of non-inherited properties and so you end up not re-resolving
1098 // style in cases where you need to.
1099 StyleChange ch = NoInherit;
1100 EDisplay display1 = s1 ? s1->display() : NONE;
1101 bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1102 EDisplay display2 = s2 ? s2->display() : NONE;
1103 bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1104 if (display1 != display2 || fl1 != fl2)
1106 else if ( !s1 || !s2 )
1108 else if ( *s1 == *s2 )
1110 else if ( s1->inheritedNotEqual( s2 ) )
1116 void NodeImpl::dump(QTextStream *stream, QString ind) const
1118 // ### implement dump() for all appropriate subclasses
1120 if (m_hasId) { *stream << " hasId"; }
1121 if (m_hasClass) { *stream << " hasClass"; }
1122 if (m_hasStyle) { *stream << " hasStyle"; }
1123 if (m_specified) { *stream << " specified"; }
1124 if (m_focused) { *stream << " focused"; }
1125 if (m_active) { *stream << " active"; }
1126 if (m_styleElement) { *stream << " styleElement"; }
1127 if (m_implicit) { *stream << " implicit"; }
1129 *stream << " tabIndex=" << m_tabIndex;
1130 if (m_regdListeners)
1131 *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1134 NodeImpl *child = firstChild();
1137 *stream << ind << child->nodeName().string().ascii() << ": ";
1138 child->dump(stream,ind+" ");
1139 child = child->nextSibling();
1144 void NodeImpl::attach()
1146 assert(!attached());
1147 assert(!m_render || (m_render->style() && m_render->parent()));
1151 void NodeImpl::detach()
1153 // assert(m_attached);
1162 bool NodeImpl::maintainsState()
1167 QString NodeImpl::state()
1169 return QString::null;
1172 void NodeImpl::restoreState(QStringList &/*states*/)
1176 void NodeImpl::insertedIntoDocument()
1178 setInDocument(true);
1181 void NodeImpl::removedFromDocument()
1183 setInDocument(false);
1186 void NodeImpl::childrenChanged()
1190 bool NodeImpl::disabled() const
1195 bool NodeImpl::isReadOnly()
1197 // Entity & Entity Reference nodes and their descendants are read-only
1200 if (n->nodeType() == Node::ENTITY_NODE ||
1201 n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1203 n = n->parentNode();
1208 NodeImpl *NodeImpl::previousEditable() const
1210 NodeImpl *node = previousLeafNode();
1212 if (node->isContentEditable())
1214 node = node->previousLeafNode();
1219 NodeImpl *NodeImpl::nextEditable() const
1221 NodeImpl *node = nextLeafNode();
1223 if (node->isContentEditable())
1225 node = node->nextLeafNode();
1230 RenderObject * NodeImpl::previousRenderer()
1232 for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1234 return n->renderer();
1239 RenderObject * NodeImpl::nextRenderer()
1241 for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1243 return n->renderer();
1248 bool NodeImpl::isAtomicNode() const
1250 return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1253 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1255 if (previousSibling()) {
1256 NodeImpl *n = previousSibling();
1257 while (!n->isAtomicNode() && n->lastChild())
1261 else if (parentNode()) {
1262 return parentNode();
1269 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1271 if (!isAtomicNode() && firstChild())
1272 return firstChild();
1274 return nextSibling();
1275 const NodeImpl *n = this;
1276 while (n && !n->nextSibling())
1277 n = n->parentNode();
1279 return n->nextSibling();
1283 NodeImpl *NodeImpl::previousLeafNode() const
1285 NodeImpl *node = previousNodeConsideringAtomicNodes();
1287 if (node->isAtomicNode())
1289 node = node->previousNodeConsideringAtomicNodes();
1294 NodeImpl *NodeImpl::nextLeafNode() const
1296 NodeImpl *node = nextNodeConsideringAtomicNodes();
1298 if (node->isAtomicNode())
1300 node = node->nextNodeConsideringAtomicNodes();
1305 void NodeImpl::createRendererIfNeeded()
1309 if (!getDocument()->shouldCreateRenderers())
1313 assert(!attached());
1316 NodeImpl *parent = parentNode();
1319 RenderObject *parentRenderer = parent->renderer();
1320 if (parentRenderer && parentRenderer->canHaveChildren()) {
1321 RenderStyle *style = styleForRenderer(parentRenderer);
1323 #ifndef KHTML_NO_XBL
1324 bool resolveStyle = false;
1325 if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) &&
1326 rendererIsNeeded(style)) {
1329 style = styleForRenderer(parentRenderer);
1332 if (rendererIsNeeded(style)) {
1334 m_render = createRenderer(getDocument()->renderArena(), style);
1335 m_render->setStyle(style);
1336 parentRenderer->addChild(m_render, nextRenderer());
1337 #ifndef KHTML_NO_XBL
1338 } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1342 style->deref(getDocument()->renderArena());
1346 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1348 return parent->style();
1351 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1353 return (getDocument()->documentElement() == this) || (style->display() != NONE);
1356 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1362 long NodeImpl::maxOffset() const
1367 long NodeImpl::caretMinOffset() const
1369 return renderer() ? renderer()->caretMinOffset() : 0;
1372 long NodeImpl::caretMaxOffset() const
1374 return renderer() ? renderer()->caretMaxOffset() : 1;
1377 unsigned long NodeImpl::caretMaxRenderedOffset() const
1379 return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1382 bool NodeImpl::isBlockFlow() const
1384 return renderer() && renderer()->isBlockFlow();
1387 bool NodeImpl::isEditableBlock() const
1389 return isContentEditable() && isBlockFlow();
1392 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1394 NodeImpl *n = const_cast<NodeImpl *>(this);
1396 return static_cast<ElementImpl *>(n);
1399 n = n->parentNode();
1402 if (n->isBlockFlow() || n->id() == ID_BODY)
1403 return static_cast<ElementImpl *>(n);
1408 ElementImpl *NodeImpl::enclosingInlineElement() const
1410 NodeImpl *n = const_cast<NodeImpl *>(this);
1414 p = n->parentNode();
1415 if (!p || p->isBlockFlow() || p->id() == ID_BODY)
1416 return static_cast<ElementImpl *>(n);
1419 ASSERT_NOT_REACHED();
1423 ElementImpl *NodeImpl::rootEditableElement() const
1425 if (!isContentEditable())
1428 NodeImpl *n = const_cast<NodeImpl *>(this);
1429 if (n->id() == ID_BODY)
1430 return static_cast<ElementImpl *>(n);
1432 NodeImpl *result = n->isEditableBlock() ? n : 0;
1434 n = n->parentNode();
1435 if (!n || !n->isContentEditable())
1437 if (n->id() == ID_BODY) {
1441 if (n->isBlockFlow())
1444 return static_cast<ElementImpl *>(result);
1447 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1449 return n ? rootEditableElement() == n->rootEditableElement() : false;
1452 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1454 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1458 NodeImpl::Id NodeImpl::identifier() const
1465 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1471 if (s.length() == 0)
1476 strncpy(buffer, result.string().latin1(), length - 1);
1480 //-------------------------------------------------------------------------
1482 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1489 NodeBaseImpl::~NodeBaseImpl()
1491 //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1493 // Avoid deep recursion when destroying the node tree.
1494 static bool alreadyInsideDestructor;
1495 bool topLevel = !alreadyInsideDestructor;
1497 alreadyInsideDestructor = true;
1499 // List of nodes to be deleted.
1500 static NodeImpl *head;
1501 static NodeImpl *tail;
1503 // We have to tell all children that their parent has died.
1507 for( n = _first; n != 0; n = next ) {
1508 next = n->nextSibling();
1509 n->setPreviousSibling(0);
1510 n->setNextSibling(0);
1513 if ( !n->refCount() ) {
1514 // Add the node to the list of nodes to be deleted.
1515 // Reuse the nextSibling pointer for this purpose.
1517 tail->setNextSibling(n);
1524 // Only for the top level call, do the actual deleting.
1526 while ((n = head) != 0) {
1527 next = n->nextSibling();
1528 n->setNextSibling(0);
1537 alreadyInsideDestructor = false;
1542 NodeImpl *NodeBaseImpl::firstChild() const
1547 NodeImpl *NodeBaseImpl::lastChild() const
1552 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1556 // insertBefore(...,null) is equivalent to appendChild()
1558 return appendChild(newChild, exceptioncode);
1560 // Make sure adding the new child is ok
1561 checkAddChild(newChild, exceptioncode);
1565 // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1566 if (refChild->parentNode() != this) {
1567 exceptioncode = DOMException::NOT_FOUND_ERR;
1571 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1573 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1574 // Just return the document fragment
1575 if (isFragment && !newChild->firstChild())
1578 // Now actually add the child(ren)
1579 NodeImpl *nextChild;
1580 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1582 NodeImpl *prev = refChild->previousSibling();
1583 if ( prev == newChild || refChild == newChild ) // nothing to do
1587 nextChild = isFragment ? child->nextSibling() : 0;
1589 // If child is already present in the tree, first remove it
1590 NodeImpl *newParent = child->parentNode();
1592 newParent->removeChild( child, exceptioncode );
1593 if ( exceptioncode )
1596 // Add child in the correct position
1598 prev->setNextSibling(child);
1601 refChild->setPreviousSibling(child);
1602 child->setParent(this);
1603 child->setPreviousSibling(prev);
1604 child->setNextSibling(refChild);
1606 // Add child to the rendering tree
1607 // ### should we detach() it first if it's already attached?
1608 if (attached() && !child->attached())
1611 // Dispatch the mutation events
1612 dispatchChildInsertedEvents(child,exceptioncode);
1618 getDocument()->setDocumentChanged(true);
1619 dispatchSubtreeModifiedEvent();
1623 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1627 if ( oldChild == newChild ) // nothing to do
1630 // Make sure adding the new child is ok
1631 checkAddChild(newChild, exceptioncode);
1635 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1636 if (!oldChild || oldChild->parentNode() != this) {
1637 exceptioncode = DOMException::NOT_FOUND_ERR;
1641 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1642 NodeImpl *nextChild;
1643 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1646 // Remove the old child
1647 NodeImpl *prev = oldChild->previousSibling();
1648 NodeImpl *next = oldChild->nextSibling();
1650 removeChild(oldChild, exceptioncode);
1654 // Add the new child(ren)
1656 nextChild = isFragment ? child->nextSibling() : 0;
1658 // If child is already present in the tree, first remove it
1659 NodeImpl *newParent = child->parentNode();
1661 newParent->removeChild( child, exceptioncode );
1665 // Add child in the correct position
1666 if (prev) prev->setNextSibling(child);
1667 if (next) next->setPreviousSibling(child);
1668 if(!prev) _first = child;
1669 if(!next) _last = child;
1670 child->setParent(this);
1671 child->setPreviousSibling(prev);
1672 child->setNextSibling(next);
1674 // Add child to the rendering tree
1675 // ### should we detach() it first if it's already attached?
1676 if (attached() && !child->attached())
1679 // Dispatch the mutation events
1680 dispatchChildInsertedEvents(child,exceptioncode);
1686 // ### set style in case it's attached
1687 getDocument()->setDocumentChanged(true);
1688 dispatchSubtreeModifiedEvent();
1692 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1696 // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1698 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1702 // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1703 if (!oldChild || oldChild->parentNode() != this) {
1704 exceptioncode = DOMException::NOT_FOUND_ERR;
1708 // Dispatch pre-removal mutation events
1709 getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1710 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1711 oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1712 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1717 dispatchChildRemovalEvents(oldChild,exceptioncode);
1721 // Remove from rendering tree
1722 if (oldChild->attached())
1726 NodeImpl *prev, *next;
1727 prev = oldChild->previousSibling();
1728 next = oldChild->nextSibling();
1730 if(next) next->setPreviousSibling(prev);
1731 if(prev) prev->setNextSibling(next);
1732 if(_first == oldChild) _first = next;
1733 if(_last == oldChild) _last = prev;
1735 oldChild->setPreviousSibling(0);
1736 oldChild->setNextSibling(0);
1737 oldChild->setParent(0);
1739 getDocument()->setDocumentChanged(true);
1741 // Dispatch post-removal mutation events
1742 dispatchSubtreeModifiedEvent();
1744 if (oldChild->inDocument())
1745 oldChild->removedFromDocument();
1750 void NodeBaseImpl::removeChildren()
1753 while (NodeImpl *n = _first) {
1754 NodeImpl *next = n->nextSibling();
1758 // Fire removed from document mutation events.
1759 dispatchChildRemovalEvents(n, exceptionCode);
1763 n->setPreviousSibling(0);
1764 n->setNextSibling(0);
1767 if (n->inDocument())
1768 n->removedFromDocument();
1776 // Dispatch a single post-removal mutation event denoting a modified subtree.
1777 dispatchSubtreeModifiedEvent();
1781 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1785 // Make sure adding the new child is ok
1786 checkAddChild(newChild, exceptioncode);
1790 if ( newChild == _last ) // nothing to do
1793 bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1795 // If newChild is a DocumentFragment with no children.... there's nothing to do.
1796 // Just return the document fragment
1797 if (isFragment && !newChild->firstChild())
1800 // Now actually add the child(ren)
1801 NodeImpl *nextChild;
1802 NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1805 nextChild = isFragment ? child->nextSibling() : 0;
1807 // If child is already present in the tree, first remove it
1808 NodeImpl *oldParent = child->parentNode();
1810 oldParent->removeChild( child, exceptioncode );
1815 // Append child to the end of the list
1816 child->setParent(this);
1820 child->setPreviousSibling(_last);
1821 _last->setNextSibling(child);
1826 _first = _last = child;
1829 // Add child to the rendering tree
1830 // ### should we detach() it first if it's already attached?
1831 if (attached() && !child->attached())
1834 // Dispatch the mutation events
1835 dispatchChildInsertedEvents(child,exceptioncode);
1840 getDocument()->setDocumentChanged(true);
1841 // ### set style in case it's attached
1842 dispatchSubtreeModifiedEvent();
1846 bool NodeBaseImpl::hasChildNodes ( ) const
1851 // not part of the DOM
1852 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1857 void NodeBaseImpl::setLastChild(NodeImpl *child)
1862 // check for same source document:
1863 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1866 DocumentImpl *ownerDocThis = getDocument();
1867 DocumentImpl *ownerDocNew = getDocument();
1868 if(ownerDocThis != ownerDocNew) {
1869 kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1870 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1876 // check for being (grand-..)father:
1877 // ### remove in favor or isAncestor()
1878 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1880 //check if newChild is parent of this...
1882 for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1884 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1890 // check for being child:
1891 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1893 if(!oldChild || oldChild->parentNode() != this) {
1894 exceptioncode = DOMException::NOT_FOUND_ERR;
1900 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1902 // do not add applyChanges here! This function is only used during parsing
1904 // short check for consistency with DTD
1905 if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1907 //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1912 newChild->setParent(this);
1916 newChild->setPreviousSibling(_last);
1917 _last->setNextSibling(newChild);
1922 _first = _last = newChild;
1925 newChild->insertedIntoDocument();
1928 if(newChild->nodeType() == Node::ELEMENT_NODE)
1933 void NodeBaseImpl::attach()
1935 NodeImpl *child = _first;
1939 child = child->nextSibling();
1944 void NodeBaseImpl::detach()
1946 NodeImpl *child = _first;
1949 NodeImpl* prev = child;
1950 child = child->nextSibling();
1956 void NodeBaseImpl::insertedIntoDocument()
1958 NodeImpl::insertedIntoDocument();
1959 for (NodeImpl *child = _first; child; child = child->nextSibling())
1960 child->insertedIntoDocument();
1963 void NodeBaseImpl::removedFromDocument()
1965 NodeImpl::removedFromDocument();
1966 for (NodeImpl *child = _first; child; child = child->nextSibling())
1967 child->removedFromDocument();
1970 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
1972 int exceptioncode = 0;
1974 for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
1976 clone->appendChild(n->cloneNode(true),exceptioncode);
1980 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
1981 DOMStringImpl* localName )
1983 if (!localName) return 0;
1985 NodeImpl::Id idMask = namespaceMask | localNameMask;
1986 if (localName->l && localName->s[0] == '*')
1987 idMask &= ~localNameMask;
1988 if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
1989 idMask &= ~namespaceMask;
1991 Id id = 0; // 0 means "all items"
1992 if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
1994 id = getDocument()->tagId( namespaceURI, localName, true);
1995 if ( !id ) // not found -> we want to return an empty list, not "all items"
1996 id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
1999 return new TagNodeListImpl( this, id, idMask );
2002 // I don't like this way of implementing the method, but I didn't find any
2004 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
2008 RenderObject *o = m_render;
2010 if ( !o->isInline() || o->isReplaced() ) {
2011 o->absolutePosition( xPos, yPos );
2015 // find the next text/image child, to get a position
2018 o = o->firstChild();
2019 else if(o->nextSibling())
2020 o = o->nextSibling();
2022 RenderObject *next = 0;
2025 if(!o) return false;
2026 next = o->nextSibling();
2030 if((o->isText() && !o->isBR()) || o->isReplaced()) {
2031 o->container()->absolutePosition( xPos, yPos );
2033 xPos += static_cast<RenderText *>(o)->minXPos();
2043 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
2048 RenderObject *o = m_render;
2050 if (!o->isInline() || o->isReplaced())
2052 o->absolutePosition( xPos, yPos );
2054 yPos += o->height();
2057 // find the last text/image child, to get a position
2061 else if(o->previousSibling())
2062 o = o->previousSibling();
2064 RenderObject *prev = 0;
2067 if(!o) return false;
2068 prev = o->previousSibling();
2072 if(o->isText() || o->isReplaced()) {
2073 o->container()->absolutePosition(xPos, yPos);
2075 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2077 xPos += o->xPos()+o->width();
2078 yPos += o->yPos()+o->height();
2085 QRect NodeBaseImpl::getRect() const
2088 if (!getUpperLeftCorner(xPos,yPos))
2094 if (!getLowerRightCorner(xEnd,yEnd))
2108 if ( xEnd <= xPos || yEnd <= yPos )
2109 return QRect( QPoint( xPos, yPos ), QSize() );
2111 return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2114 void NodeBaseImpl::setFocus(bool received)
2116 if (m_focused == received) return;
2118 NodeImpl::setFocus(received);
2120 if (received && isEditableBlock() && !hasChildNodes()) {
2121 getDocument()->part()->setSelection(Position(this, 0));
2124 // note that we need to recalc the style
2128 void NodeBaseImpl::setActive(bool down)
2130 if (down == active()) return;
2132 NodeImpl::setActive(down);
2134 // note that we need to recalc the style
2135 if (m_render && m_render->style()->affectedByActiveRules())
2139 unsigned long NodeBaseImpl::childNodeCount() const
2141 unsigned long count = 0;
2143 for (n = firstChild(); n; n = n->nextSibling())
2148 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2151 NodeImpl *n = firstChild();
2152 for (i = 0; i < index; i++)
2153 n = n->nextSibling();
2157 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2159 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2160 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2161 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2166 // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2167 bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2169 while (p->parentNode())
2170 p = p->parentNode();
2171 if (p->nodeType() == Node::DOCUMENT_NODE) {
2172 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2173 c->insertedIntoDocument();
2175 if (hasInsertedListeners) {
2176 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2177 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2185 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2187 // Dispatch pre-removal mutation events
2188 getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2189 if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2190 child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2191 true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2196 bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2198 // dispatch the DOMNOdeRemovedFromDocument event to all descendants
2200 for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2201 if (hasRemovalListeners) {
2202 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2203 false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2211 // ---------------------------------------------------------------------------
2214 NodeListImpl::NodeListImpl(NodeImpl *_rootNode)
2215 : rootNode(_rootNode),
2219 rootNode->registerNodeList(this);
2222 NodeListImpl::~NodeListImpl()
2224 rootNode->unregisterNodeList(this);
2228 unsigned long NodeListImpl::recursiveLength( NodeImpl *start ) const
2233 if (isCacheValid && start == rootNode) {
2234 return cachedLength;
2237 unsigned long len = 0;
2239 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2240 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2243 len+= recursiveLength(n);
2247 if (start == rootNode) {
2249 isCacheValid = true;
2255 NodeImpl *NodeListImpl::recursiveItem ( unsigned long &offset, NodeImpl *start ) const
2260 for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2261 if ( n->nodeType() == Node::ELEMENT_NODE ) {
2266 NodeImpl *depthSearch= recursiveItem(offset, n);
2272 return 0; // no matching node in this subtree
2275 NodeImpl *NodeListImpl::itemById (const DOMString& elementId) const
2277 if (rootNode->isDocumentNode()) {
2278 DOM::NodeImpl *node = static_cast<DocumentImpl *>(rootNode)->getElementById(elementId);
2279 if (nodeMatches(node))
2285 unsigned long l = length();
2287 for ( unsigned long i = 0; i < l; i++ ) {
2288 DOM::NodeImpl *node = item(i);
2290 if ( static_cast<ElementImpl *>(node)->getIDAttribute() == elementId ) {
2299 void NodeListImpl::rootNodeSubtreeModified()
2301 isCacheValid = false;
2305 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2310 unsigned long ChildNodeListImpl::length() const
2312 unsigned long len = 0;
2314 for(n = rootNode->firstChild(); n != 0; n = n->nextSibling())
2320 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2322 unsigned int pos = 0;
2323 NodeImpl *n = rootNode->firstChild();
2325 while( n != 0 && pos < index )
2327 n = n->nextSibling();
2334 bool ChildNodeListImpl::nodeMatches(NodeImpl *testNode) const
2336 return testNode->parentNode() == rootNode;
2339 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2341 m_id(_id & _idMask),
2346 unsigned long TagNodeListImpl::length() const
2348 return recursiveLength();
2351 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2353 return recursiveItem( index );
2356 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2358 return ( testNode->isElementNode() &&
2359 (testNode->id() & m_idMask) == m_id);
2362 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2363 : NodeListImpl(n), nodeName(t)
2367 unsigned long NameNodeListImpl::length() const
2369 return recursiveLength();
2372 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2374 return recursiveItem( index );
2377 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2379 return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2382 // ---------------------------------------------------------------------------
2384 NamedNodeMapImpl::NamedNodeMapImpl()
2388 NamedNodeMapImpl::~NamedNodeMapImpl()
2392 // ----------------------------------------------------------------------------
2396 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2397 : NamedNodeMapImpl()
2399 m_doc = doc->document();
2400 m_contents = new QPtrList<NodeImpl>;
2403 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2405 while (m_contents->count() > 0)
2406 m_contents->take(0)->deref();
2411 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2413 QPtrListIterator<NodeImpl> it(*m_contents);
2414 for (; it.current(); ++it)
2415 if (it.current()->nodeName() == name)
2416 return it.current();
2420 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2422 // can't modify this list through standard DOM functions
2423 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2424 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2428 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2430 // can't modify this list through standard DOM functions
2431 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2432 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2436 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2438 // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2439 // (also for other similar methods)
2440 if (index >= m_contents->count())
2443 return m_contents->at(index);
2446 unsigned long GenericRONamedNodeMapImpl::length( ) const
2448 return m_contents->count();
2451 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2452 const DOMString &localName,
2453 int &/*exceptioncode*/ ) const
2455 NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2456 localName.implementation(), true);
2458 QPtrListIterator<NodeImpl> it(*m_contents);
2459 for (; it.current(); ++it)
2460 if (it.current()->id() == searchId)
2461 return it.current();
2466 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2468 // can't modify this list through standard DOM functions
2469 // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2470 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2474 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2475 const DOMString &/*localName*/,
2476 int &exceptioncode )
2478 // can't modify this list through standard DOM functions
2479 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2483 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2485 // The spec says that in the case of duplicates we only keep the first one
2486 int exceptioncode = 0;
2487 if (getNamedItem(n->nodeName(),exceptioncode))
2491 m_contents->append(n);