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