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