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