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