Reviewed by Richard.
[WebKit-https.git] / WebCore / khtml / xml / dom_nodeimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #include "xml/dom_nodeimpl.h"
26 #include "dom/dom_exception.h"
27 #include "misc/htmlattrs.h"
28 #include "misc/htmltags.h"
29 #include "xml/dom_elementimpl.h"
30 #include "xml/dom_textimpl.h"
31 #include "xml/dom2_eventsimpl.h"
32 #include "xml/dom_docimpl.h"
33 #include "xml/dom_position.h"
34 #include "xml/dom_selection.h"
35 #include "xml/dom2_rangeimpl.h"
36 #include "css/csshelper.h"
37 #include "css/cssstyleselector.h"
38
39 #include <kglobal.h>
40 #include <kdebug.h>
41
42 #include "rendering/render_object.h"
43 #include "rendering/render_text.h"
44
45 #include "ecma/kjs_binding.h"
46 #include "ecma/kjs_proxy.h"
47 #include "khtmlview.h"
48 #include "khtml_part.h"
49
50 #include "html/dtd.h"
51
52 #ifndef KHTML_NO_XBL
53 #include "xbl/xbl_binding_manager.h"
54 #endif
55
56 using namespace DOM;
57 using namespace khtml;
58
59 NodeImpl::NodeImpl(DocumentPtr *doc)
60     : document(doc),
61       m_previous(0),
62       m_next(0),
63       m_render(0),
64       m_regdListeners( 0 ),
65       m_tabIndex( 0 ),
66       m_hasId( false ),
67       m_hasClass( false ),
68       m_hasStyle( false ),
69       m_attached(false),
70       m_changed( false ),
71       m_hasChangedChild( false ),
72       m_inDocument( false ),
73       m_hasAnchor( false ),
74       m_specified( false ),
75       m_focused( false ),
76       m_active( false ),
77       m_styleElement( false ),
78       m_implicit( false )
79 {
80     if (document)
81         document->ref();
82 }
83
84 void NodeImpl::setDocument(DocumentPtr *doc)
85 {
86     if (inDocument())
87         return;
88     
89     if (doc)
90         doc->ref();
91     
92     if (document)
93         document->deref();
94
95     document = doc;
96 }
97
98 NodeImpl::~NodeImpl()
99 {
100     if (m_render)
101         detach();
102     delete m_regdListeners;
103     if (document)
104         document->deref();
105     if (m_previous)
106         m_previous->setNextSibling(0);
107     if (m_next)
108         m_next->setPreviousSibling(0);
109 }
110
111 DOMString NodeImpl::nodeValue() const
112 {
113   return DOMString();
114 }
115
116 void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode )
117 {
118     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
119     if (isReadOnly()) {
120         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
121         return;
122     }
123
124     // be default nodeValue is null, so setting it has no effect
125 }
126
127 DOMString NodeImpl::nodeName() const
128 {
129   return DOMString();
130 }
131
132 unsigned short NodeImpl::nodeType() const
133 {
134   return 0;
135 }
136
137 NodeListImpl *NodeImpl::childNodes()
138 {
139   return new ChildNodeListImpl(this);
140 }
141
142 NodeImpl *NodeImpl::firstChild() const
143 {
144   return 0;
145 }
146
147 NodeImpl *NodeImpl::lastChild() const
148 {
149   return 0;
150 }
151
152 NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl *, int &exceptioncode )
153 {
154     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
155     return 0;
156 }
157
158 NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode )
159 {
160   exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
161   return 0;
162 }
163
164 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
165 {
166   exceptioncode = DOMException::NOT_FOUND_ERR;
167   return 0;
168 }
169
170 NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode )
171 {
172   exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
173   return 0;
174 }
175
176 void NodeImpl::remove(int &exceptioncode)
177 {
178     exceptioncode = 0;
179     if (!parentNode()) {
180         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
181         return;
182     }
183     
184     parentNode()->removeChild(this, exceptioncode);
185 }
186
187 bool NodeImpl::hasChildNodes(  ) const
188 {
189   return false;
190 }
191
192 void NodeImpl::normalize ()
193 {
194     // ### normalize attributes? (when we store attributes using child nodes)
195     int exceptioncode = 0;
196     NodeImpl *child = firstChild();
197
198     // Recursively go through the subtree beneath us, normalizing all nodes. In the case
199     // where there are two adjacent text nodes, they are merged together
200     while (child) {
201         NodeImpl *nextChild = child->nextSibling();
202
203         if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
204             // Current child and the next one are both text nodes... merge them
205             TextImpl *currentText = static_cast<TextImpl*>(child);
206             TextImpl *nextText = static_cast<TextImpl*>(nextChild);
207
208             currentText->appendData(nextText->data(),exceptioncode);
209             if (exceptioncode)
210                 return;
211
212             removeChild(nextChild,exceptioncode);
213             if (exceptioncode)
214                 return;
215         }
216         else {
217             child->normalize();
218             child = nextChild;
219         }
220     }
221 }
222
223 DOMString NodeImpl::prefix() const
224 {
225     // For nodes other than elements and attributes, the prefix is always null
226     return DOMString();
227 }
228
229 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
230 {
231     // The spec says that for nodes other than elements and attributes, prefix is always null.
232     // It does not say what to do when the user tries to set the prefix on another type of
233     // node, however mozilla throws a NAMESPACE_ERR exception
234     exceptioncode = DOMException::NAMESPACE_ERR;
235 }
236
237 DOMString NodeImpl::localName() const
238 {
239     return DOMString();
240 }
241
242 void NodeImpl::setFirstChild(NodeImpl *)
243 {
244 }
245
246 void NodeImpl::setLastChild(NodeImpl *)
247 {
248 }
249
250 NodeImpl *NodeImpl::addChild(NodeImpl *)
251 {
252   return 0;
253 }
254
255 QString NodeImpl::toHTML() const
256 {
257     NodeImpl* fc = firstChild();
258     if ( fc )
259         return fc->recursive_toHTML(true);
260
261     return "";
262 }
263
264 static QString escapeHTML( const QString& in )
265 {
266     QString s;
267     for ( unsigned int i = 0; i < in.length(); ++i ) {
268         switch( in[i].latin1() ) {
269         case '&':
270             s += "&amp;";
271             break;
272         case '<':
273             s += "&lt;";
274             break;
275         case '>':
276             s += "&gt;";
277             break;
278         default:
279             s += in[i];
280         }
281     }
282
283     return s;
284 }
285
286 QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes)
287
288 {
289     QString me = "";
290
291     for (const NodeImpl *current = startNode; current != NULL; current = current->nextSibling()) {
292         bool include = true;
293         if (onlyIncludeChildren) {
294             // Don't include the HTML of this node, but include the children in the next recursion.
295             include = false;
296         } else if (range) {
297             // If a range is passed, only include the node and its children's HTML if they are in the range or parents on nodes in the range.
298             include = false;
299             NodeImpl *pastEnd = range->pastEndNode();
300             for (NodeImpl *n = range->startNode(); n != pastEnd; n = n->traverseNextNode()) {
301                 for (NodeImpl *ancestor = n; ancestor; ancestor = ancestor->parentNode()) {
302                     if (current == ancestor) {
303                         include = true;
304                         break;
305                     }
306                 }
307                 if (include) {
308                     break;
309                 }
310             }
311         }
312         
313         if (include) {
314             if (nodes) {
315                 nodes->append(current);
316             }
317             // Copy who I am into the me string
318             if (current->nodeType() == Node::TEXT_NODE) {
319                 DOMString str = current->nodeValue().copy();
320                 if (range) {
321                     int exceptionCode;
322                     if (current == range->endContainer(exceptionCode)) {
323                         str.truncate(range->endOffset(exceptionCode));
324                     }
325                     if (current == range->startContainer(exceptionCode)) {
326                         str.remove(0, range->startOffset(exceptionCode));
327                     }
328                 }
329                 Id parentID = current->parentNode()->id();
330                 bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
331                 me += dontEscape ? str.string() : escapeHTML(str.string());
332             } else if (current->nodeType() != Node::DOCUMENT_NODE) {
333                 // If I am an element, not a text
334                 me += QChar('<') + current->nodeName().string();
335                 if (current->nodeType() == Node::ELEMENT_NODE) {
336                     const ElementImpl *el = static_cast<const ElementImpl *>(current);
337                     NamedAttrMapImpl *attrs = el->attributes();
338                     unsigned long length = attrs->length();
339                     for (unsigned int i=0; i<length; i++) {
340                         AttributeImpl *attr = attrs->attributeItem(i);
341                         me += " " + current->getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
342                     }
343                 }
344                 me += current->isHTMLElement() ? ">" : "/>";
345             }
346         }
347         
348         if (!current->isHTMLElement() || endTag[current->id()] != FORBIDDEN) {
349             // print children
350             if (NodeImpl *n = current->firstChild()) {
351                 me += recursive_toString(n, false, range, nodes);
352             }
353             // Print my ending tag
354             if (include && current->nodeType() != Node::TEXT_NODE && current->nodeType() != Node::DOCUMENT_NODE) {
355                 me += "</" + current->nodeName().string() + ">";
356             }
357         }
358         
359         // always include children for our siblings
360         onlyIncludeChildren = false;
361     }
362     
363     return me;
364
365 }
366
367 QString NodeImpl::recursive_toHTML(bool onlyIncludeChildren, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes) const
368 {       
369     return NodeImpl::recursive_toString(this, onlyIncludeChildren, range, nodes);
370 }
371
372 void NodeImpl::recursive_completeURLs(QString baseURL)
373 {
374     if (nodeType() == Node::ELEMENT_NODE) {
375         ElementImpl *el = static_cast<ElementImpl *>(this);
376         NamedAttrMapImpl *attrs = el->attributes();
377         unsigned long length = attrs->length();
378         for (unsigned int i=0; i<length; i++) {
379             AttributeImpl *attr = attrs->attributeItem(i);
380             if (el->isURLAttribute(attr)) {
381                 el->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url());
382             }
383         }
384     }
385     
386     NodeImpl *n;
387     if ((n = firstChild())) {
388         n->recursive_completeURLs(baseURL);
389     }
390     if ((n = nextSibling())) {
391         n->recursive_completeURLs(baseURL);
392     }
393 }
394
395 bool NodeImpl::isContentEditable() const
396 {
397     return m_parent ? m_parent->isContentEditable() : false;
398 }
399
400 QRect NodeImpl::getRect() const
401 {
402     int _x, _y;
403     if(m_render && m_render->absolutePosition(_x, _y))
404         return QRect( _x, _y, m_render->width(), m_render->height() );
405
406     return QRect();
407 }
408
409 void NodeImpl::setChanged(bool b)
410 {
411     if (b && !attached()) // changed compared to what?
412         return;
413
414     m_changed = b;
415     if ( b ) {
416         NodeImpl *p = parentNode();
417         while ( p ) {
418             p->setHasChangedChild( true );
419             p = p->parentNode();
420         }
421         getDocument()->setDocumentChanged(true);
422     }
423 }
424
425 bool NodeImpl::isInline() const
426 {
427     if (m_render) return m_render->style()->display() == khtml::INLINE;
428     return !isElementNode();
429 }
430
431 bool NodeImpl::isFocusable() const
432 {
433     return false;
434 }
435
436 bool NodeImpl::isKeyboardFocusable() const
437 {
438     return isFocusable();
439 }
440
441 bool NodeImpl::isMouseFocusable() const
442 {
443     return isFocusable();
444 }
445
446 unsigned long NodeImpl::nodeIndex() const
447 {
448     NodeImpl *_tempNode = previousSibling();
449     unsigned long count=0;
450     for( count=0; _tempNode; count++ )
451         _tempNode = _tempNode->previousSibling();
452     return count;
453 }
454
455 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
456 {
457     switch (id) {
458         case EventImpl::DOMSUBTREEMODIFIED_EVENT:
459             getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
460             break;
461         case EventImpl::DOMNODEINSERTED_EVENT:
462             getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
463             break;
464         case EventImpl::DOMNODEREMOVED_EVENT:
465             getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
466             break;
467         case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
468             getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
469             break;
470         case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
471             getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
472             break;
473         case EventImpl::DOMATTRMODIFIED_EVENT:
474             getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
475             break;
476         case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
477             getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
478             break;
479         default:
480             break;
481     }
482
483     RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
484     if (!m_regdListeners) {
485         m_regdListeners = new QPtrList<RegisteredEventListener>;
486         m_regdListeners->setAutoDelete(true);
487     }
488
489     listener->ref();
490
491     // remove existing identical listener set with identical arguments - the DOM2
492     // spec says that "duplicate instances are discarded" in this case.
493     removeEventListener(id,listener,useCapture);
494
495     m_regdListeners->append(rl);
496     listener->deref();
497 }
498
499 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
500 {
501     if (!m_regdListeners) // nothing to remove
502         return;
503
504     RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
505
506     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
507     for (; it.current(); ++it)
508         if (*(it.current()) == rl) {
509             m_regdListeners->removeRef(it.current());
510             return;
511         }
512 }
513
514 void NodeImpl::removeHTMLEventListener(int id)
515 {
516     if (!m_regdListeners) // nothing to remove
517         return;
518
519     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
520     for (; it.current(); ++it)
521         if (it.current()->id == id &&
522             it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
523             m_regdListeners->removeRef(it.current());
524             return;
525         }
526 }
527
528 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
529 {
530     // in case we already have it, we don't want removeHTMLEventListener to destroy it
531     if (listener)
532         listener->ref();
533     removeHTMLEventListener(id);
534     if (listener)
535     {
536         addEventListener(id,listener,false);
537         listener->deref();
538     }
539 }
540
541 EventListener *NodeImpl::getHTMLEventListener(int id)
542 {
543     if (!m_regdListeners)
544         return 0;
545
546     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
547     for (; it.current(); ++it)
548         if (it.current()->id == id &&
549             it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
550             return it.current()->listener;
551         }
552     return 0;
553 }
554
555
556 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
557 {
558     evt->setTarget(this);
559
560     KHTMLPart *part = document->document()->part();
561
562     // Since event handling code could cause this object to be deleted, grab a reference to the view now
563     KHTMLView *view = document->document()->view();
564     if (view)
565         view->ref();
566
567     bool ret = dispatchGenericEvent( evt, exceptioncode );
568
569     // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
570     // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
571     // So there is no need for the interpreter to keep the event in it's cache
572     if (tempEvent && part && part->jScript())
573         part->jScript()->finishedWithEvent(evt);
574
575     if (view)
576         view->deref();
577
578     return ret;
579 }
580
581 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
582 {
583     // ### check that type specified
584
585     // work out what nodes to send event to
586     QPtrList<NodeImpl> nodeChain;
587     NodeImpl *n;
588     for (n = this; n; n = n->parentNode()) {
589         n->ref();
590         nodeChain.prepend(n);
591     }
592
593     // trigger any capturing event handlers on our way down
594     evt->setEventPhase(Event::CAPTURING_PHASE);
595     QPtrListIterator<NodeImpl> it(nodeChain);
596     for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
597         evt->setCurrentTarget(it.current());
598         it.current()->handleLocalEvents(evt,true);
599     }
600
601     // dispatch to the actual target node
602     it.toLast();
603     if (!evt->propagationStopped()) {
604         evt->setEventPhase(Event::AT_TARGET);
605         evt->setCurrentTarget(it.current());
606
607         // Capturing first. -dwh
608         it.current()->handleLocalEvents(evt,true);
609
610         // Bubbling second. -dwh
611         if (!evt->propagationStopped())
612           it.current()->handleLocalEvents(evt,false);
613     }
614     --it;
615
616     // ok, now bubble up again (only non-capturing event handlers will be called)
617     // ### recalculate the node chain here? (e.g. if target node moved in document by previous event handlers)
618     // no. the DOM specs says:
619     // The chain of EventTargets from the event target to the top of the tree
620     // is determined before the initial dispatch of the event.
621     // If modifications occur to the tree during event processing,
622     // event flow will proceed based on the initial state of the tree.
623     //
624     // since the initial dispatch is before the capturing phase,
625     // there's no need to recalculate the node chain.
626     // (tobias)
627
628     if (evt->bubbles()) {
629         evt->setEventPhase(Event::BUBBLING_PHASE);
630         for (; it.current() && !evt->propagationStopped() && !evt->getCancelBubble(); --it) {
631             evt->setCurrentTarget(it.current());
632             it.current()->handleLocalEvents(evt,false);
633         }
634     }
635
636     evt->setCurrentTarget(0);
637     evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
638                            // anything about the default event handler phase.
639
640
641     if (evt->bubbles()) {
642         // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
643
644         it.toLast();
645         for (; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
646             it.current()->defaultEventHandler(evt);
647     }
648     
649     // In the case of a mouse click, also send a DOMActivate event, which causes things like form submissions
650     // to occur. Note that this only happens for _real_ mouse clicks (for which we get a KHTML_CLICK_EVENT or
651     // KHTML_DBLCLICK_EVENT), not the standard DOM "click" event that could be sent from js code.
652     if (!evt->defaultPrevented() && !disabled())
653         if (evt->id() == EventImpl::KHTML_CLICK_EVENT)
654             dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 1);
655         else if (evt->id() == EventImpl::KHTML_DBLCLICK_EVENT)
656             dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, 2);
657
658     // deref all nodes in chain
659     it.toFirst();
660     for (; it.current(); ++it)
661         it.current()->deref(); // this may delete us
662
663     DocumentImpl::updateDocumentsRendering();
664
665     return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent?
666 }
667
668 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
669 {
670     int exceptioncode = 0;
671     EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
672     evt->ref();
673     bool r = dispatchEvent(evt,exceptioncode,true);
674     evt->deref();
675     return r;
676 }
677
678 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
679 {
680     int exceptioncode = 0;
681     EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
682     evt->setTarget( 0 );
683     evt->ref();
684     DocumentPtr *doc = document;
685     doc->ref();
686     bool r = dispatchGenericEvent( evt, exceptioncode );
687     if (!evt->defaultPrevented() && doc->document())
688         doc->document()->defaultEventHandler(evt);
689     
690     if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc->document()) {
691         // For onload events, send them to the enclosing frame only.
692         // This is a DOM extension and is independent of bubbling/capturing rules of
693         // the DOM.  You send the event only to the enclosing frame.  It does not
694         // bubble through the parent document.
695         DOM::ElementImpl* elt = doc->document()->ownerElement();
696         if (elt && (elt->getDocument()->domain().isNull() ||
697                     elt->getDocument()->domain() == doc->document()->domain())) {
698             // We also do a security check, since we don't want to allow the enclosing
699             // iframe to see loads of child documents in other domains.
700             evt->setCurrentTarget(elt);
701
702             // Capturing first.
703             elt->handleLocalEvents(evt,true);
704
705             // Bubbling second.
706             if (!evt->propagationStopped())
707                 elt->handleLocalEvents(evt,false);
708             r = !evt->defaultPrevented();
709         }
710     }
711
712     doc->deref();
713     evt->deref();
714
715     return r;
716 }
717
718 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
719 {
720     bool cancelable = true;
721     int detail = overrideDetail; // defaults to 0
722     EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
723     if (overrideId) {
724         evtId = static_cast<EventImpl::EventId>(overrideId);
725     }
726     else {
727         switch (_mouse->type()) {
728             case QEvent::MouseButtonPress:
729                 evtId = EventImpl::MOUSEDOWN_EVENT;
730                 break;
731             case QEvent::MouseButtonRelease:
732                 evtId = EventImpl::MOUSEUP_EVENT;
733                 break;
734             case QEvent::MouseButtonDblClick:
735                 evtId = EventImpl::CLICK_EVENT;
736                 detail = 1; // ### support for multiple double clicks
737                 break;
738             case QEvent::MouseMove:
739                 evtId = EventImpl::MOUSEMOVE_EVENT;
740                 cancelable = false;
741                 break;
742             default:
743                 break;
744         }
745     }
746     if (evtId == EventImpl::UNKNOWN_EVENT)
747         return false; // shouldn't happen
748
749
750     int exceptioncode = 0;
751
752 #if APPLE_CHANGES
753 // Careful here - our viewportToContents() converts points from NSEvents, in NSWindow coord system to
754 // our khtmlview's coord system.  This works for QMouseEvents coming from Cocoa because those events
755 // hold the location from the NSEvent.  The QMouseEvent param here was made by other khtml code, so it
756 // will be a "proper" QT event with coords in terms of this widget.  So in WebCore it would never be
757 // right to pass coords from _mouse to viewportToContents().
758 #endif
759 //    int clientX, clientY;
760 //    viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
761     int clientX = _mouse->x(); // ### adjust to be relative to view
762     int clientY = _mouse->y(); // ### adjust to be relative to view
763
764 #if APPLE_CHANGES
765     int screenX;
766     int screenY;
767     KHTMLView *view = document->document()->view();
768     if (view) {
769         // This gets us as far as NSWindow coords
770         QPoint windowLoc = view->contentsToViewport(_mouse->pos());
771         // Then from NSWindow coords to screen coords
772         QPoint screenLoc = view->viewportToGlobal(windowLoc);
773         screenX = screenLoc.x();
774         screenY = screenLoc.y();
775     } else {
776         screenX = _mouse->x();
777         screenY = _mouse->y();
778     }
779 #else
780     int screenX = _mouse->globalX();
781     int screenY = _mouse->globalY();
782 #endif
783
784     int button = -1;
785     switch (_mouse->button()) {
786         case Qt::LeftButton:
787             button = 0;
788             break;
789         case Qt::MidButton:
790             button = 1;
791             break;
792         case Qt::RightButton:
793             button = 2;
794             break;
795         default:
796             break;
797     }
798     bool ctrlKey = (_mouse->state() & Qt::ControlButton);
799     bool altKey = (_mouse->state() & Qt::AltButton);
800     bool shiftKey = (_mouse->state() & Qt::ShiftButton);
801     bool metaKey = false; // ### qt support?
802
803     EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
804                    detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
805                    button,0);
806     evt->ref();
807     bool r = dispatchEvent(evt,exceptioncode,true);
808     evt->deref();
809     return r;
810
811 }
812
813 bool NodeImpl::dispatchUIEvent(int _id, int detail)
814 {
815     assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
816         _id != EventImpl::DOMFOCUSOUT_EVENT &&
817                 _id != EventImpl::DOMACTIVATE_EVENT)));
818
819     bool cancelable = false;
820     if (_id == EventImpl::DOMACTIVATE_EVENT)
821         cancelable = true;
822
823     int exceptioncode = 0;
824     UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
825                                        cancelable,getDocument()->defaultView(),detail);
826     evt->ref();
827     bool r = dispatchEvent(evt,exceptioncode,true);
828     evt->deref();
829     return r;
830 }
831
832 bool NodeImpl::dispatchSubtreeModifiedEvent()
833 {
834     childrenChanged();
835     if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
836         return false;
837     int exceptioncode = 0;
838     return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
839                          true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
840 }
841
842 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
843 {
844     int exceptioncode = 0;
845     //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
846     KeyboardEventImpl *keyboardEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
847     keyboardEventImpl->ref();
848     bool r = dispatchEvent(keyboardEventImpl,exceptioncode,true);
849
850 #if APPLE_CHANGES
851     // we want to return false if default is prevented (already taken care of)
852     // or if the element is default-handled by the DOM. Otherwise we let it just
853     // let it get handled by AppKit 
854     if (keyboardEventImpl->defaultHandled())
855 #else
856     // the default event handler should accept() the internal QKeyEvent
857     // to prevent the view from further evaluating it.
858     if (!keyboardEventImpl->defaultPrevented() && !keyboardEventImpl->qKeyEvent->isAccepted())
859 #endif
860       r = false;
861
862     keyboardEventImpl->deref();
863     return r;
864 }
865
866 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
867 {
868     if (!m_regdListeners)
869         return;
870
871     if (disabled() && evt->isMouseEvent())
872         return;
873
874     QPtrList<RegisteredEventListener> listenersCopy = *m_regdListeners;
875     QPtrListIterator<RegisteredEventListener> it(listenersCopy);
876     Event ev = evt;
877     for (; it.current(); ++it) {
878         if (it.current()->id == evt->id() && it.current()->useCapture == useCapture)
879             it.current()->listener->handleEvent(ev, false);
880     }
881
882 }
883
884 void NodeImpl::defaultEventHandler(EventImpl *evt)
885 {
886 }
887
888 unsigned long NodeImpl::childNodeCount() const
889 {
890     return 0;
891 }
892
893 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
894 {
895     return 0;
896 }
897
898 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
899 {
900     if (firstChild())
901         return firstChild();
902     if (nextSibling())
903         return nextSibling();
904     const NodeImpl *n = this;
905     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
906         n = n->parentNode();
907     if (n && (!stayWithin || n->parentNode() != stayWithin))
908         return n->nextSibling();
909     return 0;
910 }
911
912 NodeImpl *NodeImpl::traverseNextSibling(NodeImpl *stayWithin) const
913 {
914     if (nextSibling())
915         return nextSibling();
916     const NodeImpl *n = this;
917     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
918         n = n->parentNode();
919     if (n && (!stayWithin || n->parentNode() != stayWithin))
920         return n->nextSibling();
921     return 0;
922 }
923
924 NodeImpl *NodeImpl::traversePreviousNode() const
925 {
926     if (previousSibling()) {
927         NodeImpl *n = previousSibling();
928         while (n->lastChild())
929             n = n->lastChild();
930         return n;
931     }
932     else if (parentNode()) {
933         return parentNode();
934     }
935     else {
936         return 0;
937     }
938 }
939
940 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
941 {
942     // Perform error checking as required by spec for setting Node.prefix. Used by
943     // ElementImpl::setPrefix() and AttrImpl::setPrefix()
944
945     // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
946     if (!Element::khtmlValidPrefix(_prefix)) {
947         exceptioncode = DOMException::INVALID_CHARACTER_ERR;
948         return;
949     }
950
951     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
952     if (isReadOnly()) {
953         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
954         return;
955     }
956
957     // NAMESPACE_ERR: - Raised if the specified prefix is malformed
958     // - if the namespaceURI of this node is null,
959     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
960     //   "http://www.w3.org/XML/1998/namespace",
961     // - if this node is an attribute and the specified prefix is "xmlns" and
962     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
963     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
964     if (Element::khtmlMalformedPrefix(_prefix) || (namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
965         (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
966         exceptioncode = DOMException::NAMESPACE_ERR;
967         return;
968     }
969 }
970
971 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
972 {
973     // Perform error checking as required by spec for adding a new child. Used by
974     // appendChild(), replaceChild() and insertBefore()
975
976     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
977     if (!newChild) {
978         exceptioncode = DOMException::NOT_FOUND_ERR;
979         return;
980     }
981
982     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
983     if (isReadOnly()) {
984         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
985         return;
986     }
987
988     bool shouldAdoptChild = false;
989
990     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
991     // created this node.
992     // We assume that if newChild is a DocumentFragment, all children are created from the same document
993     // as the fragment itself (otherwise they could not have been added as children)
994     if (newChild->getDocument() != getDocument()) {
995         // but if the child is not in a document yet then loosen the
996         // restriction, so that e.g. creating an element with the Option()
997         // constructor and then adding it to a different document works,
998         // as it does in Mozilla and Mac IE.
999         if (!newChild->inDocument()) {
1000             shouldAdoptChild = true;
1001         } else {
1002             exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1003             return;
1004         }
1005     }
1006
1007     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1008     // newChild node, or if the node to append is one of this node's ancestors.
1009
1010     // check for ancestor/same node
1011     if (newChild == this || isAncestor(newChild)) {
1012         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1013         return;
1014     }
1015
1016     // only do this once we know there won't be an exception
1017     if (shouldAdoptChild) {
1018         KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
1019         newChild->setDocument(getDocument()->docPtr());
1020     }
1021 }
1022
1023 bool NodeImpl::isAncestor(const NodeImpl *other) const
1024 {
1025     // Return true if other is an ancestor of this, otherwise false
1026     for (const NodeImpl *n = parentNode(); n; n = n->parentNode()) {
1027         if (n == other)
1028             return true;
1029     }
1030     return false;
1031 }
1032
1033 bool NodeImpl::childAllowed( NodeImpl *newChild )
1034 {
1035     return childTypeAllowed(newChild->nodeType());
1036 }
1037
1038 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
1039 {
1040     // FIXME: The behavior of this function is just totally wrong.  It doesn't handle
1041     // explicit inheritance of non-inherited properties and so you end up not re-resolving
1042     // style in cases where you need to.
1043     StyleChange ch = NoInherit;
1044     EDisplay display1 = s1 ? s1->display() : NONE;
1045     bool fl1 = s1 ? s1->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1046     EDisplay display2 = s2 ? s2->display() : NONE;
1047     bool fl2 = s2 ? s2->hasPseudoStyle(RenderStyle::FIRST_LETTER) : false;
1048     if (display1 != display2 || fl1 != fl2)
1049         ch = Detach;
1050     else if ( !s1 || !s2 )
1051         ch = Inherit;
1052     else if ( *s1 == *s2 )
1053         ch = NoChange;
1054     else if ( s1->inheritedNotEqual( s2 ) )
1055         ch = Inherit;
1056     return ch;
1057 }
1058
1059 #ifndef NDEBUG
1060 void NodeImpl::dump(QTextStream *stream, QString ind) const
1061 {
1062     // ### implement dump() for all appropriate subclasses
1063
1064     if (m_hasId) { *stream << " hasId"; }
1065     if (m_hasClass) { *stream << " hasClass"; }
1066     if (m_hasStyle) { *stream << " hasStyle"; }
1067     if (m_specified) { *stream << " specified"; }
1068     if (m_focused) { *stream << " focused"; }
1069     if (m_active) { *stream << " active"; }
1070     if (m_styleElement) { *stream << " styleElement"; }
1071     if (m_implicit) { *stream << " implicit"; }
1072
1073     *stream << " tabIndex=" << m_tabIndex;
1074     if (m_regdListeners)
1075         *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
1076     *stream << endl;
1077
1078     NodeImpl *child = firstChild();
1079     while( child != 0 )
1080     {
1081         *stream << ind << child->nodeName().string().ascii() << ": ";
1082         child->dump(stream,ind+"  ");
1083         child = child->nextSibling();
1084     }
1085 }
1086 #endif
1087
1088 void NodeImpl::attach()
1089 {
1090     assert(!attached());
1091     assert(!m_render || (m_render->style() && m_render->parent()));
1092     m_attached = true;
1093 }
1094
1095 void NodeImpl::detach()
1096 {
1097 //    assert(m_attached);
1098
1099     if (m_render)
1100         m_render->detach();
1101
1102     m_render = 0;
1103     m_attached = false;
1104 }
1105
1106 bool NodeImpl::maintainsState()
1107 {
1108     return false;
1109 }
1110
1111 QString NodeImpl::state()
1112 {
1113     return QString::null;
1114 }
1115
1116 void NodeImpl::restoreState(QStringList &/*states*/)
1117 {
1118 }
1119
1120 void NodeImpl::insertedIntoDocument()
1121 {
1122     setInDocument(true);
1123 }
1124
1125 void NodeImpl::removedFromDocument()
1126 {
1127     setInDocument(false);
1128 }
1129
1130 void NodeImpl::childrenChanged()
1131 {
1132 }
1133
1134 bool NodeImpl::disabled() const
1135 {
1136     return false;
1137 }
1138
1139 bool NodeImpl::isReadOnly()
1140 {
1141     // Entity & Entity Reference nodes and their descendants are read-only
1142     NodeImpl *n = this;
1143     while (n) {
1144         if (n->nodeType() == Node::ENTITY_NODE ||
1145             n->nodeType() == Node::ENTITY_REFERENCE_NODE)
1146             return true;
1147         n = n->parentNode();
1148     }
1149     return false;
1150 }
1151
1152 NodeImpl *NodeImpl::previousEditable() const
1153 {
1154     NodeImpl *node = previousLeafNode();
1155     while (node) {
1156         if (node->isContentEditable())
1157             return node;
1158         node = node->previousLeafNode();
1159     }
1160     return 0;
1161 }
1162
1163 NodeImpl *NodeImpl::nextEditable() const
1164 {
1165     NodeImpl *node = nextLeafNode();
1166     while (node) {
1167         if (node->isContentEditable())
1168             return node;
1169         node = node->nextLeafNode();
1170     }
1171     return 0;
1172 }
1173
1174 RenderObject * NodeImpl::previousRenderer()
1175 {
1176     for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
1177         if (n->renderer())
1178             return n->renderer();
1179     }
1180     return 0;
1181 }
1182
1183 RenderObject * NodeImpl::nextRenderer()
1184 {
1185     for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
1186         if (n->renderer())
1187             return n->renderer();
1188     }
1189     return 0;
1190 }
1191
1192 bool NodeImpl::isAtomicNode() const
1193 {
1194     return !hasChildNodes() || (id() == ID_OBJECT && renderer() && renderer()->isReplaced());
1195 }
1196
1197 NodeImpl *NodeImpl::previousNodeConsideringAtomicNodes() const
1198 {
1199     if (previousSibling()) {
1200         NodeImpl *n = previousSibling();
1201         while (!n->isAtomicNode() && n->lastChild())
1202             n = n->lastChild();
1203         return n;
1204     }
1205     else if (parentNode()) {
1206         return parentNode();
1207     }
1208     else {
1209         return 0;
1210     }
1211 }
1212
1213 NodeImpl *NodeImpl::nextNodeConsideringAtomicNodes() const
1214 {
1215     if (!isAtomicNode() && firstChild())
1216         return firstChild();
1217     if (nextSibling())
1218         return nextSibling();
1219     const NodeImpl *n = this;
1220     while (n && !n->nextSibling())
1221         n = n->parentNode();
1222     if (n)
1223         return n->nextSibling();
1224     return 0;
1225 }
1226
1227 NodeImpl *NodeImpl::previousLeafNode() const
1228 {
1229     NodeImpl *node = previousNodeConsideringAtomicNodes();
1230     while (node) {
1231         if (node->isAtomicNode())
1232             return node;
1233         node = node->previousNodeConsideringAtomicNodes();
1234     }
1235     return 0;
1236 }
1237
1238 NodeImpl *NodeImpl::nextLeafNode() const
1239 {
1240     NodeImpl *node = nextNodeConsideringAtomicNodes();
1241     while (node) {
1242         if (node->isAtomicNode())
1243             return node;
1244         node = node->nextNodeConsideringAtomicNodes();
1245     }
1246     return 0;
1247 }
1248
1249 void NodeImpl::createRendererIfNeeded()
1250 {
1251
1252 #if APPLE_CHANGES
1253     if (!getDocument()->shouldCreateRenderers())
1254         return;
1255 #endif
1256         
1257     assert(!attached());
1258     assert(!m_render);
1259     
1260     NodeImpl *parent = parentNode();    
1261     assert(parent);
1262     
1263     RenderObject *parentRenderer = parent->renderer();
1264     if (parentRenderer && parentRenderer->canHaveChildren()) {
1265         RenderStyle *style = styleForRenderer(parentRenderer);
1266         style->ref();
1267 #ifndef KHTML_NO_XBL
1268         bool resolveStyle = false;
1269         if (getDocument()->bindingManager()->loadBindings(this, style->bindingURIs(), true, &resolveStyle) && 
1270             rendererIsNeeded(style)) {
1271             if (resolveStyle) {
1272                 style->deref();
1273                 style = styleForRenderer(parentRenderer);
1274             }
1275 #else
1276         if (rendererIsNeeded(style)) {
1277 #endif
1278             m_render = createRenderer(getDocument()->renderArena(), style);
1279             m_render->setStyle(style);
1280             parentRenderer->addChild(m_render, nextRenderer());
1281 #ifndef KHTML_NO_XBL
1282         } // avoid confusing the change log code parser by having two close braces to match the two open braces above
1283 #else
1284         }
1285 #endif
1286         style->deref(getDocument()->renderArena());
1287     }
1288 }
1289
1290 RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
1291 {
1292     return parent->style();
1293 }
1294
1295 bool NodeImpl::rendererIsNeeded(RenderStyle *style)
1296 {
1297     return (getDocument()->documentElement() == this) || (style->display() != NONE);
1298 }
1299
1300 RenderObject *NodeImpl::createRenderer(RenderArena *arena, RenderStyle *style)
1301 {
1302     assert(false);
1303     return 0;
1304 }
1305
1306 long NodeImpl::maxOffset() const
1307 {
1308     return 1;
1309 }
1310
1311 long NodeImpl::caretMinOffset() const
1312 {
1313     return renderer() ? renderer()->caretMinOffset() : 0;
1314 }
1315
1316 long NodeImpl::caretMaxOffset() const
1317 {
1318     return renderer() ? renderer()->caretMaxOffset() : 1;
1319 }
1320
1321 unsigned long NodeImpl::caretMaxRenderedOffset() const
1322 {
1323     return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1324 }
1325
1326 bool NodeImpl::isBlockFlow() const
1327 {
1328     return renderer() && renderer()->isBlockFlow();
1329 }
1330
1331 bool NodeImpl::isEditableBlock() const
1332 {
1333     return isContentEditable() && isBlockFlow();
1334 }
1335
1336 ElementImpl *NodeImpl::enclosingBlockFlowElement() const
1337 {
1338     NodeImpl *n = const_cast<NodeImpl *>(this);
1339     if (isBlockFlow())
1340         return static_cast<ElementImpl *>(n);
1341
1342     while (1) {
1343         n = n->parentNode();
1344         if (!n)
1345             break;
1346         if (n->isBlockFlow() || n->id() == ID_BODY)
1347             return static_cast<ElementImpl *>(n);
1348     }
1349     return 0;
1350 }
1351
1352 ElementImpl *NodeImpl::rootEditableElement() const
1353 {
1354     if (!isContentEditable())
1355         return 0;
1356
1357     NodeImpl *n = const_cast<NodeImpl *>(this);
1358     NodeImpl *result = n->isEditableBlock() ? n : 0;
1359     while (1) {
1360         n = n->parentNode();
1361         if (!n || !n->isContentEditable())
1362             break;
1363         if (n->id() == ID_BODY) {
1364             result = n;
1365             break;
1366         }
1367         if (n->isBlockFlow())
1368             result = n;
1369     }
1370     return static_cast<ElementImpl *>(result);
1371 }
1372
1373 bool NodeImpl::inSameRootEditableElement(NodeImpl *n)
1374 {
1375     return n ? rootEditableElement() == n->rootEditableElement() : false;
1376 }
1377
1378 bool NodeImpl::inSameContainingBlockFlowElement(NodeImpl *n)
1379 {
1380     return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1381 }
1382
1383 #if APPLE_CHANGES
1384 NodeImpl::Id NodeImpl::identifier() const
1385 {
1386     return id();
1387 }
1388 #endif
1389
1390 Position NodeImpl::positionForCoordinates(int x, int y)
1391 {
1392     if (renderer())
1393         return renderer()->positionForCoordinates(x, y);
1394     
1395     return Position(this, 0);
1396 }
1397
1398 #ifndef NDEBUG
1399 void NodeImpl::formatForDebugger(char *buffer, unsigned length) const
1400 {
1401     DOMString result;
1402     DOMString s;
1403     
1404     s = nodeName();
1405     if (s.length() == 0)
1406         result += "<none>";
1407     else
1408         result += s;
1409           
1410     strncpy(buffer, result.string().latin1(), length - 1);
1411 }
1412 #endif
1413
1414 //-------------------------------------------------------------------------
1415
1416 NodeBaseImpl::NodeBaseImpl(DocumentPtr *doc)
1417     : NodeImpl(doc)
1418 {
1419     _first = _last = 0;
1420 }
1421
1422
1423 NodeBaseImpl::~NodeBaseImpl()
1424 {
1425     //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
1426
1427     // Avoid deep recursion when destroying the node tree.
1428     static bool alreadyInsideDestructor; 
1429     bool topLevel = !alreadyInsideDestructor;
1430     if (topLevel)
1431         alreadyInsideDestructor = true;
1432     
1433     // List of nodes to be deleted.
1434     static NodeImpl *head;
1435     static NodeImpl *tail;
1436     
1437     // We have to tell all children that their parent has died.
1438     NodeImpl *n;
1439     NodeImpl *next;
1440
1441     for( n = _first; n != 0; n = next ) {
1442         next = n->nextSibling();
1443         n->setPreviousSibling(0);
1444         n->setNextSibling(0);
1445         n->setParent(0);
1446         
1447         if ( !n->refCount() ) {
1448             // Add the node to the list of nodes to be deleted.
1449             // Reuse the nextSibling pointer for this purpose.
1450             if (tail)
1451                 tail->setNextSibling(n);
1452             else
1453                 head = n;
1454             tail = n;
1455         }
1456     }
1457     
1458     // Only for the top level call, do the actual deleting.
1459     if (topLevel) {
1460         while ((n = head) != 0) {
1461             next = n->nextSibling();
1462             n->setNextSibling(0);
1463
1464             head = next;
1465             if (next == 0)
1466                 tail = 0;
1467             
1468             delete n;
1469         }
1470         
1471         alreadyInsideDestructor = false;
1472     }
1473 }
1474
1475
1476 NodeImpl *NodeBaseImpl::firstChild() const
1477 {
1478     return _first;
1479 }
1480
1481 NodeImpl *NodeBaseImpl::lastChild() const
1482 {
1483     return _last;
1484 }
1485
1486 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
1487 {
1488     exceptioncode = 0;
1489
1490     // insertBefore(...,null) is equivalent to appendChild()
1491     if(!refChild)
1492         return appendChild(newChild, exceptioncode);
1493
1494     // Make sure adding the new child is ok
1495     checkAddChild(newChild, exceptioncode);
1496     if (exceptioncode)
1497         return 0;
1498
1499     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
1500     if (refChild->parentNode() != this) {
1501         exceptioncode = DOMException::NOT_FOUND_ERR;
1502         return 0;
1503     }
1504
1505     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1506
1507     // If newChild is a DocumentFragment with no children.... there's nothing to do.
1508     // Just return the document fragment
1509     if (isFragment && !newChild->firstChild())
1510         return newChild;
1511
1512     // Now actually add the child(ren)
1513     NodeImpl *nextChild;
1514     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1515
1516     NodeImpl *prev = refChild->previousSibling();
1517     if ( prev == newChild || refChild == newChild ) // nothing to do
1518         return newChild;
1519     
1520     while (child) {
1521         nextChild = isFragment ? child->nextSibling() : 0;
1522
1523         // If child is already present in the tree, first remove it
1524         NodeImpl *newParent = child->parentNode();
1525         if(newParent)
1526             newParent->removeChild( child, exceptioncode );
1527         if ( exceptioncode )
1528             return 0;
1529
1530         // Add child in the correct position
1531         if (prev)
1532             prev->setNextSibling(child);
1533         else
1534             _first = child;
1535         refChild->setPreviousSibling(child);
1536         child->setParent(this);
1537         child->setPreviousSibling(prev);
1538         child->setNextSibling(refChild);
1539
1540         // Add child to the rendering tree
1541         // ### should we detach() it first if it's already attached?
1542         if (attached() && !child->attached())
1543             child->attach();
1544
1545         // Dispatch the mutation events
1546         dispatchChildInsertedEvents(child,exceptioncode);
1547
1548         prev = child;
1549         child = nextChild;
1550     }
1551
1552     getDocument()->setDocumentChanged(true);
1553     dispatchSubtreeModifiedEvent();
1554     return newChild;
1555 }
1556
1557 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
1558 {
1559     exceptioncode = 0;
1560
1561     if ( oldChild == newChild ) // nothing to do
1562         return oldChild;
1563     
1564     // Make sure adding the new child is ok
1565     checkAddChild(newChild, exceptioncode);
1566     if (exceptioncode)
1567         return 0;
1568
1569     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1570     if (!oldChild || oldChild->parentNode() != this) {
1571         exceptioncode = DOMException::NOT_FOUND_ERR;
1572         return 0;
1573     }
1574
1575     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1576     NodeImpl *nextChild;
1577     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1578
1579
1580     // Remove the old child
1581     NodeImpl *prev = oldChild->previousSibling();
1582     NodeImpl *next = oldChild->nextSibling();
1583
1584     removeChild(oldChild, exceptioncode);
1585     if (exceptioncode)
1586         return 0;
1587
1588     // Add the new child(ren)
1589     while (child) {
1590         nextChild = isFragment ? child->nextSibling() : 0;
1591
1592         // If child is already present in the tree, first remove it
1593         NodeImpl *newParent = child->parentNode();
1594         if(newParent)
1595             newParent->removeChild( child, exceptioncode );
1596         if (exceptioncode)
1597             return 0;
1598
1599         // Add child in the correct position
1600         if (prev) prev->setNextSibling(child);
1601         if (next) next->setPreviousSibling(child);
1602         if(!prev) _first = child;
1603         if(!next) _last = child;
1604         child->setParent(this);
1605         child->setPreviousSibling(prev);
1606         child->setNextSibling(next);
1607
1608         // Add child to the rendering tree
1609         // ### should we detach() it first if it's already attached?
1610         if (attached() && !child->attached())
1611             child->attach();
1612
1613         // Dispatch the mutation events
1614         dispatchChildInsertedEvents(child,exceptioncode);
1615
1616         prev = child;
1617         child = nextChild;
1618     }
1619
1620     // ### set style in case it's attached
1621     getDocument()->setDocumentChanged(true);
1622     dispatchSubtreeModifiedEvent();
1623     return oldChild;
1624 }
1625
1626 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
1627 {
1628     exceptioncode = 0;
1629
1630     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
1631     if (isReadOnly()) {
1632         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
1633         return 0;
1634     }
1635
1636     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
1637     if (!oldChild || oldChild->parentNode() != this) {
1638         exceptioncode = DOMException::NOT_FOUND_ERR;
1639         return 0;
1640     }
1641
1642     // Dispatch pre-removal mutation events
1643     getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
1644     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
1645         oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
1646                              true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
1647         if (exceptioncode)
1648             return 0;
1649     }
1650
1651     dispatchChildRemovalEvents(oldChild,exceptioncode);
1652     if (exceptioncode)
1653         return 0;
1654
1655     // Remove from rendering tree
1656     if (oldChild->attached())
1657         oldChild->detach();
1658
1659     // Remove the child
1660     NodeImpl *prev, *next;
1661     prev = oldChild->previousSibling();
1662     next = oldChild->nextSibling();
1663
1664     if(next) next->setPreviousSibling(prev);
1665     if(prev) prev->setNextSibling(next);
1666     if(_first == oldChild) _first = next;
1667     if(_last == oldChild) _last = prev;
1668
1669     oldChild->setPreviousSibling(0);
1670     oldChild->setNextSibling(0);
1671     oldChild->setParent(0);
1672
1673     getDocument()->setDocumentChanged(true);
1674
1675     // Dispatch post-removal mutation events
1676     dispatchSubtreeModifiedEvent();
1677
1678     if (oldChild->inDocument())
1679         oldChild->removedFromDocument();
1680
1681     return oldChild;
1682 }
1683
1684 void NodeBaseImpl::removeChildren()
1685 {
1686     int exceptionCode;
1687     while (NodeImpl *n = _first) {
1688         NodeImpl *next = n->nextSibling();
1689         
1690         // Fire removed from document mutation events.
1691         dispatchChildRemovalEvents(n, exceptionCode);
1692     
1693         if (n->attached())
1694             n->detach();
1695         n->setPreviousSibling(0);
1696         n->setNextSibling(0);
1697         n->setParent(0);
1698         
1699         if (n->inDocument())
1700             n->removedFromDocument();
1701         if (!n->refCount())
1702             delete n;
1703         _first = next;
1704     }
1705     _last = 0;
1706     
1707     // Dispatch a single post-removal mutation event denoting a modified subtree.
1708     dispatchSubtreeModifiedEvent();
1709 }
1710
1711
1712 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
1713 {
1714     exceptioncode = 0;
1715
1716     // Make sure adding the new child is ok
1717     checkAddChild(newChild, exceptioncode);
1718     if (exceptioncode)
1719         return 0;
1720     
1721     if ( newChild == _last ) // nothing to do
1722         return newChild;
1723
1724     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
1725
1726     // If newChild is a DocumentFragment with no children.... there's nothing to do.
1727     // Just return the document fragment
1728     if (isFragment && !newChild->firstChild())
1729         return newChild;
1730
1731     // Now actually add the child(ren)
1732     NodeImpl *nextChild;
1733     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
1734
1735     while (child) {
1736         nextChild = isFragment ? child->nextSibling() : 0;
1737
1738         // If child is already present in the tree, first remove it
1739         NodeImpl *oldParent = child->parentNode();
1740         if(oldParent) {
1741             oldParent->removeChild( child, exceptioncode );
1742             if (exceptioncode)
1743                 return 0;
1744         }
1745
1746         // Append child to the end of the list
1747         child->setParent(this);
1748
1749         if(_last)
1750         {
1751             child->setPreviousSibling(_last);
1752             _last->setNextSibling(child);
1753             _last = child;
1754         }
1755         else
1756         {
1757             _first = _last = child;
1758         }
1759
1760         // Add child to the rendering tree
1761         // ### should we detach() it first if it's already attached?
1762         if (attached() && !child->attached())
1763             child->attach();
1764           
1765         // Dispatch the mutation events
1766         dispatchChildInsertedEvents(child,exceptioncode);
1767
1768         child = nextChild;
1769     }
1770
1771     getDocument()->setDocumentChanged(true);
1772     // ### set style in case it's attached
1773     dispatchSubtreeModifiedEvent();
1774     return newChild;
1775 }
1776
1777 bool NodeBaseImpl::hasChildNodes (  ) const
1778 {
1779     return _first != 0;
1780 }
1781
1782 // not part of the DOM
1783 void NodeBaseImpl::setFirstChild(NodeImpl *child)
1784 {
1785     _first = child;
1786 }
1787
1788 void NodeBaseImpl::setLastChild(NodeImpl *child)
1789 {
1790     _last = child;
1791 }
1792
1793 // check for same source document:
1794 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
1795 {
1796     exceptioncode = 0;
1797     DocumentImpl *ownerDocThis = getDocument();
1798     DocumentImpl *ownerDocNew = getDocument();
1799     if(ownerDocThis != ownerDocNew) {
1800         kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
1801         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
1802         return true;
1803     }
1804     return false;
1805 }
1806
1807 // check for being (grand-..)father:
1808 // ### remove in favor or isAncestor()
1809 bool NodeBaseImpl::checkNoOwner( NodeImpl *newChild, int &exceptioncode )
1810 {
1811   //check if newChild is parent of this...
1812   NodeImpl *n;
1813   for( n = this; (n != getDocument()) && (n!= 0); n = n->parentNode() )
1814       if(n == newChild) {
1815           exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
1816           return true;
1817       }
1818   return false;
1819 }
1820
1821 // check for being child:
1822 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
1823 {
1824     if(!oldChild || oldChild->parentNode() != this) {
1825         exceptioncode = DOMException::NOT_FOUND_ERR;
1826         return true;
1827     }
1828     return false;
1829 }
1830
1831 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
1832 {
1833     // do not add applyChanges here! This function is only used during parsing
1834
1835     // short check for consistency with DTD
1836     if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
1837     {
1838         //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
1839         return 0;
1840     }
1841
1842     // just add it...
1843     newChild->setParent(this);
1844
1845     if(_last)
1846     {
1847         newChild->setPreviousSibling(_last);
1848         _last->setNextSibling(newChild);
1849         _last = newChild;
1850     }
1851     else
1852     {
1853         _first = _last = newChild;
1854     }
1855
1856     newChild->insertedIntoDocument();
1857     childrenChanged();
1858
1859     if(newChild->nodeType() == Node::ELEMENT_NODE)
1860         return newChild;
1861     return this;
1862 }
1863
1864 void NodeBaseImpl::attach()
1865 {
1866     NodeImpl *child = _first;
1867     while(child != 0)
1868     {
1869         child->attach();
1870         child = child->nextSibling();
1871     }
1872     NodeImpl::attach();
1873 }
1874
1875 void NodeBaseImpl::detach()
1876 {
1877     NodeImpl *child = _first;
1878     while(child != 0)
1879     {
1880         NodeImpl* prev = child;
1881         child = child->nextSibling();
1882         prev->detach();
1883     }
1884     NodeImpl::detach();
1885 }
1886
1887 void NodeBaseImpl::insertedIntoDocument()
1888 {
1889     NodeImpl::insertedIntoDocument();
1890     for (NodeImpl *child = _first; child; child = child->nextSibling())
1891         child->insertedIntoDocument();
1892 }
1893
1894 void NodeBaseImpl::removedFromDocument()
1895 {
1896     NodeImpl::removedFromDocument();
1897     for (NodeImpl *child = _first; child; child = child->nextSibling())
1898         child->removedFromDocument();
1899 }
1900
1901 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
1902 {
1903     int exceptioncode = 0;
1904     NodeImpl *n;
1905     for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
1906     {
1907         clone->appendChild(n->cloneNode(true),exceptioncode);
1908     }
1909 }
1910
1911 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
1912                                                      DOMStringImpl* localName )
1913 {
1914     if (!localName) return 0;
1915
1916     NodeImpl::Id idMask = namespaceMask | localNameMask;
1917     if (localName->l && localName->s[0] == '*')
1918         idMask &= ~localNameMask;
1919     if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
1920         idMask &= ~namespaceMask;
1921
1922     Id id = 0; // 0 means "all items"
1923     if ( (idMask & localNameMask) || namespaceURI ) // not getElementsByTagName("*")
1924     {
1925         id = getDocument()->tagId( namespaceURI, localName, true);
1926         if ( !id ) // not found -> we want to return an empty list, not "all items"
1927             id = (Id)-1; // HACK. HEAD has a cleaner implementation of TagNodeListImpl it seems.
1928     }
1929
1930     return new TagNodeListImpl( this, id, idMask );
1931 }
1932
1933 // I don't like this way of implementing the method, but I didn't find any
1934 // other way. Lars
1935 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
1936 {
1937     if (!m_render)
1938         return false;
1939     RenderObject *o = m_render;
1940     xPos = yPos = 0;
1941     if ( !o->isInline() || o->isReplaced() ) {
1942         o->absolutePosition( xPos, yPos );
1943         return true;
1944     }
1945
1946     // find the next text/image child, to get a position
1947     while(o) {
1948         if(o->firstChild())
1949             o = o->firstChild();
1950         else if(o->nextSibling())
1951             o = o->nextSibling();
1952         else {
1953             RenderObject *next = 0;
1954             while(!next) {
1955                 o = o->parent();
1956                 if(!o) return false;
1957                 next = o->nextSibling();
1958             }
1959             o = next;
1960         }
1961         if((o->isText() && !o->isBR()) || o->isReplaced()) {
1962             o->container()->absolutePosition( xPos, yPos );
1963             if (o->isText())
1964                 xPos += static_cast<RenderText *>(o)->minXPos();
1965             else
1966                 xPos += o->xPos();
1967             yPos += o->yPos();
1968             return true;
1969         }
1970     }
1971     return true;
1972 }
1973
1974 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
1975 {
1976     if (!m_render)
1977         return false;
1978
1979     RenderObject *o = m_render;
1980     xPos = yPos = 0;
1981     if (!o->isInline() || o->isReplaced())
1982     {
1983         o->absolutePosition( xPos, yPos );
1984         xPos += o->width();
1985         yPos += o->height();
1986         return true;
1987     }
1988     // find the last text/image child, to get a position
1989     while(o) {
1990         if(o->lastChild())
1991             o = o->lastChild();
1992         else if(o->previousSibling())
1993             o = o->previousSibling();
1994         else {
1995             RenderObject *prev = 0;
1996             while(!prev) {
1997                 o = o->parent();
1998                 if(!o) return false;
1999                 prev = o->previousSibling();
2000             }
2001             o = prev;
2002         }
2003         if(o->isText() || o->isReplaced()) {
2004             o->container()->absolutePosition(xPos, yPos);
2005             if (o->isText())
2006                 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
2007             else
2008                 xPos += o->xPos()+o->width();
2009             yPos += o->yPos()+o->height();
2010             return true;
2011         }
2012     }
2013     return true;
2014 }
2015
2016 QRect NodeBaseImpl::getRect() const
2017 {
2018     int xPos, yPos;
2019     if (!getUpperLeftCorner(xPos,yPos))
2020     {
2021         xPos=0;
2022         yPos=0;
2023     }
2024     int xEnd, yEnd;
2025     if (!getLowerRightCorner(xEnd,yEnd))
2026     {
2027         if (xPos)
2028             xEnd = xPos;
2029         if (yPos)
2030             yEnd = yPos;
2031     }
2032     else
2033     {
2034         if (xPos==0)
2035             xPos = xEnd;
2036         if (yPos==0)
2037             yPos = yEnd;
2038     }
2039     if ( xEnd <= xPos || yEnd <= yPos )
2040         return QRect( QPoint( xPos, yPos ), QSize() );
2041
2042     return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
2043 }
2044
2045 void NodeBaseImpl::setFocus(bool received)
2046 {
2047     if (m_focused == received) return;
2048
2049     NodeImpl::setFocus(received);
2050
2051     if (received && isEditableBlock() && !hasChildNodes()) {
2052         KHTMLPart *part = getDocument()->part();
2053         part->setSelection(Selection(Position(this, 0)));
2054     }
2055
2056     // note that we need to recalc the style
2057     setChanged();
2058 }
2059
2060 void NodeBaseImpl::setActive(bool down)
2061 {
2062     if (down == active()) return;
2063
2064     NodeImpl::setActive(down);
2065
2066     // note that we need to recalc the style
2067     if (m_render && m_render->style()->affectedByActiveRules())
2068         setChanged();
2069 }
2070
2071 unsigned long NodeBaseImpl::childNodeCount() const
2072 {
2073     unsigned long count = 0;
2074     NodeImpl *n;
2075     for (n = firstChild(); n; n = n->nextSibling())
2076         count++;
2077     return count;
2078 }
2079
2080 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
2081 {
2082     unsigned long i;
2083     NodeImpl *n = firstChild();
2084     for (i = 0; i < index; i++)
2085         n = n->nextSibling();
2086     return n;
2087 }
2088
2089 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
2090 {
2091     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
2092         child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
2093                                                    true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2094         if (exceptioncode)
2095             return;
2096     }
2097
2098     // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
2099     bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
2100     NodeImpl *p = this;
2101     while (p->parentNode())
2102         p = p->parentNode();
2103     if (p->nodeType() == Node::DOCUMENT_NODE) {
2104         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2105             c->insertedIntoDocument();
2106
2107             if (hasInsertedListeners) {
2108                 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
2109                                                        false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2110                 if (exceptioncode)
2111                     return;
2112             }
2113         }
2114     }
2115 }
2116
2117 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
2118 {
2119     // Dispatch pre-removal mutation events
2120     getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
2121     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
2122         child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
2123                              true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2124         if (exceptioncode)
2125             return;
2126     }
2127
2128     bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
2129
2130     // dispatch the DOMNOdeRemovedFromDocument event to all descendants
2131     if (inDocument()) {
2132         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
2133             if (hasRemovalListeners) {
2134                 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
2135                                  false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
2136                 if (exceptioncode)
2137                     return;
2138             }
2139         }
2140     }
2141 }
2142
2143 // ---------------------------------------------------------------------------
2144
2145 NodeImpl *NodeListImpl::item( unsigned long /*index*/ ) const
2146 {
2147     return 0;
2148 }
2149
2150 unsigned long NodeListImpl::length() const
2151 {
2152     return 0;
2153 }
2154
2155 unsigned long NodeListImpl::recursiveLength(NodeImpl *start) const
2156 {
2157     unsigned long len = 0;
2158
2159     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2160         if ( n->nodeType() == Node::ELEMENT_NODE ) {
2161             if (nodeMatches(n))
2162                 len++;
2163             len+= recursiveLength(n);
2164         }
2165     }
2166
2167     return len;
2168 }
2169
2170 NodeImpl *NodeListImpl::recursiveItem ( NodeImpl *start, unsigned long &offset ) const
2171 {
2172     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
2173         if ( n->nodeType() == Node::ELEMENT_NODE ) {
2174             if (nodeMatches(n))
2175                 if (!offset--)
2176                     return n;
2177
2178             NodeImpl *depthSearch= recursiveItem(n, offset);
2179             if (depthSearch)
2180                 return depthSearch;
2181         }
2182     }
2183
2184     return 0; // no matching node in this subtree
2185 }
2186
2187 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
2188 {
2189     refNode = n;
2190     refNode->ref();
2191 }
2192
2193 ChildNodeListImpl::~ChildNodeListImpl()
2194 {
2195     refNode->deref();
2196 }
2197
2198 unsigned long ChildNodeListImpl::length() const
2199 {
2200     unsigned long len = 0;
2201     NodeImpl *n;
2202     for(n = refNode->firstChild(); n != 0; n = n->nextSibling())
2203         len++;
2204
2205     return len;
2206 }
2207
2208 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
2209 {
2210     unsigned int pos = 0;
2211     NodeImpl *n = refNode->firstChild();
2212
2213     while( n != 0 && pos < index )
2214     {
2215         n = n->nextSibling();
2216         pos++;
2217     }
2218
2219     return n;
2220 }
2221
2222 bool ChildNodeListImpl::nodeMatches( NodeImpl */*testNode*/ ) const
2223 {
2224     return true;
2225 }
2226
2227 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
2228     : refNode(n), m_id(_id & _idMask), m_idMask(_idMask)
2229 {
2230     refNode->ref();
2231 }
2232
2233 TagNodeListImpl::~TagNodeListImpl()
2234 {
2235     refNode->deref();
2236 }
2237
2238 unsigned long TagNodeListImpl::length() const
2239 {
2240     return recursiveLength( refNode );
2241 }
2242
2243 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
2244 {
2245     return recursiveItem( refNode, index );
2246 }
2247
2248 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2249 {
2250     return ( testNode->isElementNode() &&
2251              (testNode->id() & m_idMask) == m_id);
2252 }
2253
2254 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
2255   : nodeName(t)
2256 {
2257     refNode= n;
2258     refNode->ref();
2259 }
2260
2261 NameNodeListImpl::~NameNodeListImpl()
2262 {
2263     refNode->deref();
2264 }
2265
2266 unsigned long NameNodeListImpl::length() const
2267 {
2268     return recursiveLength( refNode );
2269 }
2270
2271 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
2272 {
2273     return recursiveItem( refNode, index );
2274 }
2275
2276 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
2277 {
2278     return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
2279 }
2280
2281 // ---------------------------------------------------------------------------
2282
2283 NamedNodeMapImpl::NamedNodeMapImpl()
2284 {
2285 }
2286
2287 NamedNodeMapImpl::~NamedNodeMapImpl()
2288 {
2289 }
2290
2291 // ----------------------------------------------------------------------------
2292
2293 // ### unused
2294 #if 0
2295 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
2296     : NamedNodeMapImpl()
2297 {
2298     m_doc = doc->document();
2299     m_contents = new QPtrList<NodeImpl>;
2300 }
2301
2302 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
2303 {
2304     while (m_contents->count() > 0)
2305         m_contents->take(0)->deref();
2306
2307     delete m_contents;
2308 }
2309
2310 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
2311 {
2312     QPtrListIterator<NodeImpl> it(*m_contents);
2313     for (; it.current(); ++it)
2314         if (it.current()->nodeName() == name)
2315             return it.current();
2316     return 0;
2317 }
2318
2319 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
2320 {
2321     // can't modify this list through standard DOM functions
2322     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2323     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2324     return 0;
2325 }
2326
2327 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
2328 {
2329     // can't modify this list through standard DOM functions
2330     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2331     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2332     return 0;
2333 }
2334
2335 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
2336 {
2337     // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
2338     // (also for other similar methods)
2339     if (index >= m_contents->count())
2340         return 0;
2341
2342     return m_contents->at(index);
2343 }
2344
2345 unsigned long GenericRONamedNodeMapImpl::length(  ) const
2346 {
2347     return m_contents->count();
2348 }
2349
2350 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
2351                                                      const DOMString &localName,
2352                                                      int &/*exceptioncode*/ ) const
2353 {
2354     NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
2355                                                    localName.implementation(), true);
2356
2357     QPtrListIterator<NodeImpl> it(*m_contents);
2358     for (; it.current(); ++it)
2359         if (it.current()->id() == searchId)
2360             return it.current();
2361
2362     return 0;
2363 }
2364
2365 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
2366 {
2367     // can't modify this list through standard DOM functions
2368     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
2369     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2370     return 0;
2371 }
2372
2373 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
2374                                                         const DOMString &/*localName*/,
2375                                                         int &exceptioncode )
2376 {
2377     // can't modify this list through standard DOM functions
2378     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
2379     return 0;
2380 }
2381
2382 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
2383 {
2384     // The spec says that in the case of duplicates we only keep the first one
2385     int exceptioncode = 0;
2386     if (getNamedItem(n->nodeName(),exceptioncode))
2387         return;
2388
2389     n->ref();
2390     m_contents->append(n);
2391 }
2392
2393 #endif