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