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