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