khtml Library API Documentation

dom_nodeimpl.cpp

00001 
00024 #include "dom/dom_exception.h"
00025 #include "misc/htmlattrs.h"
00026 #include "misc/htmltags.h"
00027 #include "xml/dom_elementimpl.h"
00028 #include "xml/dom_textimpl.h"
00029 #include "xml/dom2_eventsimpl.h"
00030 #include "xml/dom_docimpl.h"
00031 #include "xml/dom_nodeimpl.h"
00032 
00033 #include <kglobal.h>
00034 #include <kdebug.h>
00035 
00036 #include "rendering/render_text.h"
00037 
00038 #include "ecma/kjs_proxy.h"
00039 #include "khtmlview.h"
00040 #include "khtml_part.h"
00041 
00042 
00043 using namespace DOM;
00044 using namespace khtml;
00045 
00046 NodeImpl::NodeImpl(DocumentPtr *doc)
00047     : document(doc),
00048       m_previous(0),
00049       m_next(0),
00050       m_render(0),
00051       m_regdListeners( 0 ),
00052       m_tabIndex( 0 ),
00053       m_hasId( false ),
00054       m_hasStyle( false ),
00055       m_pressed( false ),
00056       m_attached(false),
00057       m_changed( false ),
00058       m_hasChangedChild( false ),
00059       m_inDocument( false ),
00060       m_hasAnchor( false ),
00061       m_specified( false ),
00062       m_focused( false ),
00063       m_active( false ),
00064       m_styleElement( false ),
00065       m_implicit( false )
00066 {
00067     if (document)
00068         document->ref();
00069 }
00070 
00071 NodeImpl::~NodeImpl()
00072 {
00073     if (m_render)
00074         detach();
00075     delete m_regdListeners;
00076     if (document)
00077         document->deref();
00078     if (m_previous)
00079         m_previous->setNextSibling(0);
00080     if (m_next)
00081         m_next->setPreviousSibling(0);
00082 }
00083 
00084 DOMString NodeImpl::nodeValue() const
00085 {
00086   return DOMString();
00087 }
00088 
00089 void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &exceptioncode )
00090 {
00091     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
00092     if (isReadOnly()) {
00093         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00094         return;
00095     }
00096 
00097     // be default nodeValue is null, so setting it has no effect
00098 }
00099 
00100 DOMString NodeImpl::nodeName() const
00101 {
00102   return DOMString();
00103 }
00104 
00105 unsigned short NodeImpl::nodeType() const
00106 {
00107   return 0;
00108 }
00109 
00110 NodeListImpl *NodeImpl::childNodes()
00111 {
00112   return new ChildNodeListImpl(this);
00113 }
00114 
00115 NodeImpl *NodeImpl::firstChild() const
00116 {
00117   return 0;
00118 }
00119 
00120 NodeImpl *NodeImpl::lastChild() const
00121 {
00122   return 0;
00123 }
00124 
00125 NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl *, int &exceptioncode )
00126 {
00127     exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00128     return 0;
00129 }
00130 
00131 NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode )
00132 {
00133   exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00134   return 0;
00135 }
00136 
00137 NodeImpl *NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
00138 {
00139   exceptioncode = DOMException::NOT_FOUND_ERR;
00140   return 0;
00141 }
00142 
00143 NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode )
00144 {
00145   exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00146   return 0;
00147 }
00148 
00149 bool NodeImpl::hasChildNodes(  ) const
00150 {
00151   return false;
00152 }
00153 
00154 void NodeImpl::normalize ()
00155 {
00156     // ### normalize attributes? (when we store attributes using child nodes)
00157     int exceptioncode = 0;
00158     NodeImpl *child = firstChild();
00159 
00160     // Recursively go through the subtree beneath us, normalizing all nodes. In the case
00161     // where there are two adjacent text nodes, they are merged together
00162     while (child) {
00163         NodeImpl *nextChild = child->nextSibling();
00164 
00165         if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
00166             // Current child and the next one are both text nodes... merge them
00167             TextImpl *currentText = static_cast<TextImpl*>(child);
00168             TextImpl *nextText = static_cast<TextImpl*>(nextChild);
00169 
00170             currentText->appendData(nextText->data(),exceptioncode);
00171             if (exceptioncode)
00172                 return;
00173 
00174             removeChild(nextChild,exceptioncode);
00175             if (exceptioncode)
00176                 return;
00177         }
00178         else {
00179             child->normalize();
00180             child = nextChild;
00181         }
00182     }
00183 }
00184 
00185 DOMString NodeImpl::prefix() const
00186 {
00187     // For nodes other than elements and attributes, the prefix is always null
00188     return DOMString();
00189 }
00190 
00191 void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
00192 {
00193     // The spec says that for nodes other than elements and attributes, prefix is always null.
00194     // It does not say what to do when the user tries to set the prefix on another type of
00195     // node, however mozilla throws a NAMESPACE_ERR exception
00196     exceptioncode = DOMException::NAMESPACE_ERR;
00197 }
00198 
00199 DOMString NodeImpl::localName() const
00200 {
00201     return DOMString();
00202 }
00203 
00204 void NodeImpl::setFirstChild(NodeImpl *)
00205 {
00206 }
00207 
00208 void NodeImpl::setLastChild(NodeImpl *)
00209 {
00210 }
00211 
00212 NodeImpl *NodeImpl::addChild(NodeImpl *)
00213 {
00214   return 0;
00215 }
00216 
00217 QString NodeImpl::toHTML() const
00218 {
00219     qDebug("NodeImpl::toHTML");
00220     NodeImpl* fc = firstChild();
00221     if ( fc )
00222         return fc->recursive_toHTML(true);
00223 
00224     return "";
00225 }
00226 
00227 static QString escapeHTML( const QString& in )
00228 {
00229     QString s;
00230     for ( unsigned int i = 0; i < in.length(); ++i ) {
00231         switch( in[i].latin1() ) {
00232         case '&':
00233             s += "&amp;";
00234             break;
00235         case '<':
00236             s += "&lt;";
00237             break;
00238         case '>':
00239             s += "&gt;";
00240             break;
00241         default:
00242             s += in[i];
00243         }
00244     }
00245 
00246     return s;
00247 }
00248 
00249 QString NodeImpl::recursive_toHTML(bool start) const
00250 {
00251     QString me = "";
00252 
00253     // Copy who I am into the htmlText string
00254     if ( nodeType() == Node::TEXT_NODE )
00255         me = escapeHTML( nodeValue().string() );
00256     else
00257     {
00258         // If I am an element, not a text
00259         NodeImpl* temp = previousSibling();
00260         if(temp)
00261         {
00262             if( !start && (temp->nodeType() != Node::TEXT_NODE && nodeType() != Node::TEXT_NODE ) )
00263                 me = QString("    ") + QChar('<') + nodeName().string();
00264             else
00265                 me = QChar('<') + nodeName().string();
00266         }
00267         else
00268             me = QChar('<') + nodeName().string();
00269         // print attributes
00270         if( nodeType() == Node::ELEMENT_NODE )
00271         {
00272             const ElementImpl *el = static_cast<const ElementImpl *>(this);
00273             NamedNodeMap attrs = el->attributes();
00274             unsigned long lmap = attrs.length();
00275             for( unsigned int j=0; j<lmap; j++ )
00276                 me += " " + attrs.item(j).nodeName().string() + "=\"" + attrs.item(j).nodeValue().string() + "\"";
00277         }
00278         // print ending bracket of start tag
00279         if( firstChild() == 0 )     // if element has no endtag
00280                 me += " />\n";
00281         else                        // if element has endtag
00282         {
00283                 NodeImpl* temp = nextSibling();
00284                 if(temp)
00285                 {
00286                     if( (temp->nodeType() != Node::TEXT_NODE) )
00287                         me += ">\n";
00288                     else
00289                         me += ">";
00290                 }
00291                 else
00292                     me += ">";
00293         }
00294     }
00295 
00296     NodeImpl* n;
00297 
00298     if( (n = firstChild()) )
00299     {
00300         // print firstChild
00301         me += n->recursive_toHTML( );
00302 
00303         // Print my ending tag
00304         if ( nodeType() != Node::TEXT_NODE )
00305             me += "</" + nodeName().string() + ">\n";
00306     }
00307     // print next sibling
00308     if( (n = nextSibling()) )
00309         me += n->recursive_toHTML( );
00310 
00311     return me;
00312 }
00313 
00314 void NodeImpl::getCursor(int offset, int &_x, int &_y, int &height)
00315 {
00316     if(m_render) m_render->cursorPos(offset, _x, _y, height);
00317     else _x = _y = height = -1;
00318 }
00319 
00320 QRect NodeImpl::getRect() const
00321 {
00322     int _x, _y;
00323     if(m_render && m_render->absolutePosition(_x, _y))
00324         return QRect( _x, _y, m_render->width(), m_render->height() );
00325 
00326     return QRect();
00327 }
00328 
00329 void NodeImpl::setChanged(bool b)
00330 {
00331     if (b && !attached()) // changed compared to what?
00332         return;
00333 
00334     m_changed = b;
00335     if ( b ) {
00336         NodeImpl *p = parentNode();
00337         while ( p ) {
00338             p->setHasChangedChild( true );
00339             p = p->parentNode();
00340         }
00341         getDocument()->setDocumentChanged();
00342     }
00343 }
00344 
00345 bool NodeImpl::isInline() const
00346 {
00347     if (m_render) return m_render->style()->display() == khtml::INLINE;
00348     return !isElementNode();
00349 }
00350 
00351 
00352 unsigned long NodeImpl::nodeIndex() const
00353 {
00354     NodeImpl *_tempNode = previousSibling();
00355     unsigned long count=0;
00356     for( count=0; _tempNode; count++ )
00357         _tempNode = _tempNode->previousSibling();
00358     return count;
00359 }
00360 
00361 void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
00362 {
00363     switch (id) {
00364         case EventImpl::DOMSUBTREEMODIFIED_EVENT:
00365             getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
00366             break;
00367         case EventImpl::DOMNODEINSERTED_EVENT:
00368             getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
00369             break;
00370         case EventImpl::DOMNODEREMOVED_EVENT:
00371             getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
00372             break;
00373         case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
00374             getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
00375             break;
00376         case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
00377             getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
00378             break;
00379         case EventImpl::DOMATTRMODIFIED_EVENT:
00380             getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
00381             break;
00382         case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
00383             getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
00384             break;
00385         default:
00386             break;
00387     }
00388 
00389     RegisteredEventListener *rl = new RegisteredEventListener(static_cast<EventImpl::EventId>(id),listener,useCapture);
00390     if (!m_regdListeners) {
00391         m_regdListeners = new QPtrList<RegisteredEventListener>;
00392         m_regdListeners->setAutoDelete(true);
00393     }
00394 
00395     // remove existing ones of the same type - ### is this correct (or do we ignore the new one?)
00396     removeEventListener(id,listener,useCapture);
00397 
00398     m_regdListeners->append(rl);
00399 }
00400 
00401 void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
00402 {
00403     if (!m_regdListeners) // nothing to remove
00404         return;
00405 
00406     RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
00407 
00408     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
00409     for (; it.current(); ++it)
00410         if (*(it.current()) == rl) {
00411             m_regdListeners->removeRef(it.current());
00412             return;
00413         }
00414 }
00415 
00416 void NodeImpl::removeHTMLEventListener(int id)
00417 {
00418     if (!m_regdListeners) // nothing to remove
00419         return;
00420 
00421     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
00422     for (; it.current(); ++it)
00423         if (it.current()->id == id &&
00424             it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
00425             m_regdListeners->removeRef(it.current());
00426             return;
00427         }
00428 }
00429 
00430 void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
00431 {
00432     // in case we already have it, we don't want removeHTMLEventListener to destroy it
00433     if (listener)
00434         listener->ref();
00435     removeHTMLEventListener(id);
00436     if (listener)
00437     {
00438         addEventListener(id,listener,false);
00439         listener->deref();
00440     }
00441 }
00442 
00443 EventListener *NodeImpl::getHTMLEventListener(int id)
00444 {
00445     if (!m_regdListeners)
00446         return 0;
00447 
00448     QPtrListIterator<RegisteredEventListener> it(*m_regdListeners);
00449     for (; it.current(); ++it)
00450         if (it.current()->id == id &&
00451             it.current()->listener->eventListenerType() == "_khtml_HTMLEventListener") {
00452             return it.current()->listener;
00453         }
00454     return 0;
00455 }
00456 
00457 
00458 bool NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
00459 {
00460     // Not mentioned in spec: throw NOT_FOUND_ERR if evt is null
00461     if (!evt) {
00462         exceptioncode = DOMException::NOT_FOUND_ERR;
00463         return false;
00464     }
00465 
00466     evt->setTarget(this);
00467 
00468     // Since event handling code could cause this object to be deleted, grab a reference to the view now
00469     KHTMLView *view = document->document()->view();
00470 
00471     bool ret = dispatchGenericEvent( evt, exceptioncode );
00472 
00473     // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
00474     // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
00475     // So there is no need for the interpreter to keep the event in its cache
00476     if (tempEvent && view && view->part() && view->part()->jScript())
00477         view->part()->jScript()->finishedWithEvent(evt);
00478 
00479     return ret;
00480 }
00481 
00482 bool NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
00483 {
00484     // ### check that type specified
00485 
00486     // work out what nodes to send event to
00487     QPtrList<NodeImpl> nodeChain;
00488     NodeImpl *n;
00489     for (n = this; n; n = n->parentNode()) {
00490         n->ref();
00491         nodeChain.prepend(n);
00492     }
00493 
00494     // trigger any capturing event handlers on our way down
00495     evt->setEventPhase(Event::CAPTURING_PHASE);
00496     QPtrListIterator<NodeImpl> it(nodeChain);
00497     for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
00498         evt->setCurrentTarget(it.current());
00499         it.current()->handleLocalEvents(evt,true);
00500     }
00501 
00502     // dispatch to the actual target node
00503     it.toLast();
00504     if (!evt->propagationStopped()) {
00505         evt->setEventPhase(Event::AT_TARGET);
00506         evt->setCurrentTarget(it.current());
00507         it.current()->handleLocalEvents(evt, true);
00508         if (!evt->propagationStopped())
00509         it.current()->handleLocalEvents(evt,false);
00510     }
00511     --it;
00512 
00513     if (evt->bubbles()) {
00514         evt->stopPropagation(false);
00515         NodeImpl* propagationSentinel = 0;
00516 
00517         evt->setEventPhase(Event::BUBBLING_PHASE);
00518         for (; it.current() && !evt->propagationStopped(); --it) {
00519             if (evt->propagationStopped()) propagationSentinel = it.current();
00520             evt->setCurrentTarget(it.current());
00521             it.current()->handleLocalEvents(evt,false);
00522         }
00523 
00524         // now we call all default event handlers (this is not part of DOM - it is internal to khtml)
00525         evt->setCurrentTarget(0);
00526         evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
00527         for (it.toLast(); it.current() && it.current() != propagationSentinel &&
00528                  !evt->defaultPrevented() && !evt->defaultHandled(); --it)
00529             it.current()->defaultEventHandler(evt);
00530 
00531         if (evt->id() == EventImpl::CLICK_EVENT && !evt->defaultPrevented() &&
00532                         static_cast<MouseEventImpl*>(evt)->button() == 0)
00533             dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, static_cast<UIEventImpl*>(evt)->detail());
00534     }
00535 
00536     // copy this over into a local variable, as the following deref() calls might cause this to be deleted.
00537     DocumentPtr *doc = document;
00538     doc->ref();
00539 
00540     // deref all nodes in chain
00541     it.toFirst();
00542     for (; it.current(); ++it)
00543         it.current()->deref(); // this may delete us
00544 
00545     DocumentImpl::updateDocumentsRendering();
00546     doc->deref();
00547 
00548     return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent?
00549 }
00550 
00551 bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
00552 {
00553     int exceptioncode = 0;
00554     EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
00555     evt->ref();
00556     bool r = dispatchEvent(evt,exceptioncode,true);
00557     evt->deref();
00558     return r;
00559 }
00560 
00561 bool NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
00562 {
00563     int exceptioncode = 0;
00564     EventImpl *evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
00565     evt->setTarget( 0 );
00566     evt->ref();
00567     DocumentPtr *doc = document;
00568     doc->ref();
00569     bool r = dispatchGenericEvent( evt, exceptioncode );
00570     if (!evt->defaultPrevented())
00571         doc->document()->defaultEventHandler(evt);
00572     doc->deref();
00573     evt->deref();
00574     return r;
00575 }
00576 
00577 bool NodeImpl::dispatchMouseEvent(QMouseEvent *_mouse, int overrideId, int overrideDetail)
00578 {
00579     bool cancelable = true;
00580     int detail = overrideDetail; // defaults to 0
00581     EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
00582     if (overrideId) {
00583         evtId = static_cast<EventImpl::EventId>(overrideId);
00584     }
00585     else {
00586         switch (_mouse->type()) {
00587             case QEvent::MouseButtonPress:
00588                 evtId = EventImpl::MOUSEDOWN_EVENT;
00589                 break;
00590             case QEvent::MouseButtonRelease:
00591                 evtId = EventImpl::MOUSEUP_EVENT;
00592                 break;
00593             case QEvent::MouseButtonDblClick:
00594                 evtId = EventImpl::CLICK_EVENT;
00595                 detail = 1; // ### support for multiple double clicks
00596                 break;
00597             case QEvent::MouseMove:
00598                 evtId = EventImpl::MOUSEMOVE_EVENT;
00599                 cancelable = false;
00600                 break;
00601             default:
00602                 break;
00603         }
00604     }
00605     if (evtId == EventImpl::UNKNOWN_EVENT)
00606         return false; // shouldn't happen
00607 
00608 
00609     int exceptioncode = 0;
00610 
00611 //    int clientX, clientY;
00612 //    viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
00613     int clientX = _mouse->x(); // ### adjust to be relative to view
00614     int clientY = _mouse->y(); // ### adjust to be relative to view
00615 
00616     int screenX = _mouse->globalX();
00617     int screenY = _mouse->globalY();
00618 
00619     int button = -1;
00620     switch (_mouse->button()) {
00621         case Qt::LeftButton:
00622             button = 0;
00623             break;
00624         case Qt::MidButton:
00625             button = 1;
00626             break;
00627         case Qt::RightButton:
00628             button = 2;
00629             break;
00630         default:
00631             break;
00632     }
00633     bool ctrlKey = (_mouse->state() & Qt::ControlButton) == Qt::ControlButton;
00634     bool altKey = (_mouse->state() & Qt::AltButton) == Qt::AltButton;
00635     bool shiftKey = (_mouse->state() & Qt::ShiftButton) == Qt::ShiftButton;
00636     bool metaKey = false; // ### qt support?
00637 
00638     EventImpl *evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
00639                    detail,screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,
00640                    button,0);
00641     evt->ref();
00642     bool r = dispatchEvent(evt,exceptioncode,true);
00643     evt->deref();
00644     return r;
00645 
00646 }
00647 
00648 bool NodeImpl::dispatchUIEvent(int _id, int detail)
00649 {
00650     assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
00651         _id != EventImpl::DOMFOCUSOUT_EVENT &&
00652                 _id != EventImpl::DOMACTIVATE_EVENT)));
00653 
00654     bool cancelable = false;
00655     if (_id == EventImpl::DOMACTIVATE_EVENT)
00656         cancelable = true;
00657 
00658     int exceptioncode = 0;
00659     UIEventImpl *evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
00660                                        cancelable,getDocument()->defaultView(),detail);
00661     evt->ref();
00662     bool r = dispatchEvent(evt,exceptioncode,true);
00663     evt->deref();
00664     return r;
00665 }
00666 
00667 bool NodeImpl::dispatchSubtreeModifiedEvent()
00668 {
00669     childrenChanged();
00670     if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
00671         return false;
00672     int exceptioncode = 0;
00673     return dispatchEvent(new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,
00674                          true,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
00675 }
00676 
00677 bool NodeImpl::dispatchKeyEvent(QKeyEvent *key)
00678 {
00679     int exceptioncode = 0;
00680     //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
00681     TextEventImpl *keyEventImpl = new TextEventImpl(key, getDocument()->defaultView());
00682     keyEventImpl->ref();
00683     bool r = dispatchEvent(keyEventImpl,exceptioncode,true);
00684     // the default event handler should accept() the internal QKeyEvent
00685     // to prevent the view from further evaluating it.
00686     if (!keyEventImpl->defaultPrevented() && !keyEventImpl->qKeyEvent->isAccepted())
00687       r = false;
00688     keyEventImpl->deref();
00689     return r;
00690 }
00691 
00692 void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
00693 {
00694     if (!m_regdListeners)
00695         return;
00696 
00697     Event ev = evt;
00698     for (QPtrListIterator<RegisteredEventListener> it(*m_regdListeners); it.current();) {
00699         RegisteredEventListener* current = it();
00700         if (current->id == evt->id() && current->useCapture == useCapture)
00701             current->listener->handleEvent(ev);
00702         // ECMA legacy hack
00703         if (current->useCapture == useCapture && evt->id() == EventImpl::CLICK_EVENT &&
00704             ( ( static_cast<MouseEventImpl*>(evt)->detail() == 1 && current->id == EventImpl::KHTML_ECMA_CLICK_EVENT) ||
00705               ( static_cast<MouseEventImpl*>(evt)->detail() > 1 && current->id == EventImpl::KHTML_ECMA_DBLCLICK_EVENT) ) )
00706             current->listener->handleEvent(ev);
00707     }
00708 }
00709 
00710 void NodeImpl::defaultEventHandler(EventImpl *)
00711 {
00712 }
00713 
00714 unsigned long NodeImpl::childNodeCount()
00715 {
00716     return 0;
00717 }
00718 
00719 NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
00720 {
00721     return 0;
00722 }
00723 
00724 NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
00725 {
00726     if (firstChild())
00727         return firstChild();
00728     else if (nextSibling())
00729         return nextSibling();
00730     else {
00731         const NodeImpl *n = this;
00732         while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
00733             n = n->parentNode();
00734         if (n && (!stayWithin || n->parentNode() != stayWithin))
00735             return n->nextSibling();
00736     }
00737     return 0;
00738 }
00739 
00740 NodeImpl *NodeImpl::traversePreviousNode() const
00741 {
00742     if (previousSibling()) {
00743         NodeImpl *n = previousSibling();
00744         while (n->lastChild())
00745             n = n->lastChild();
00746         return n;
00747     }
00748     else if (parentNode()) {
00749         return parentNode();
00750     }
00751     else {
00752         return 0;
00753     }
00754 }
00755 
00756 void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
00757 {
00758     // Perform error checking as required by spec for setting Node.prefix. Used by
00759     // ElementImpl::setPrefix() and AttrImpl::setPrefix()
00760 
00761     // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
00762     if (!Element::khtmlValidPrefix(_prefix)) {
00763         exceptioncode = DOMException::INVALID_CHARACTER_ERR;
00764         return;
00765     }
00766 
00767     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
00768     if (isReadOnly()) {
00769         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00770         return;
00771     }
00772 
00773     // NAMESPACE_ERR: - Raised if the specified prefix is malformed
00774     // - if the namespaceURI of this node is null,
00775     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
00776     //   "http://www.w3.org/XML/1998/namespace",
00777     // - if this node is an attribute and the specified prefix is "xmlns" and
00778     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
00779     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
00780     if (Element::khtmlMalformedPrefix(_prefix) || (!(id() & NodeImpl_IdNSMask) && id() > ID_LAST_TAG) ||
00781         (_prefix == "xml" && DOMString(getDocument()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
00782         exceptioncode = DOMException::NAMESPACE_ERR;
00783         return;
00784     }
00785 }
00786 
00787 void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
00788 {
00789     // Perform error checking as required by spec for adding a new child. Used by
00790     // appendChild(), replaceChild() and insertBefore()
00791 
00792     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
00793     if (!newChild) {
00794         exceptioncode = DOMException::NOT_FOUND_ERR;
00795         return;
00796     }
00797 
00798     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
00799     if (isReadOnly()) {
00800         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00801         return;
00802     }
00803 
00804     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
00805     // created this node.
00806     // We assume that if newChild is a DocumentFragment, all children are created from the same document
00807     // as the fragment itself (otherwise they could not have been added as children)
00808     if (newChild->getDocument() != getDocument()) {
00809         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00810         return;
00811     }
00812 
00813     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
00814     // newChild node, or if the node to append is one of this node's ancestors.
00815 
00816     // check for ancestor/same node
00817     if (isAncestor(newChild)) {
00818         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00819         return;
00820     }
00821 
00822     // check node allowed
00823     if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
00824         // newChild is a DocumentFragment... check all its children instead of newChild itself
00825         NodeImpl *child;
00826         for (child = newChild->firstChild(); child; child = child->nextSibling()) {
00827             if (!childAllowed(child)) {
00828                 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00829                 return;
00830             }
00831         }
00832     }
00833     else {
00834         // newChild is not a DocumentFragment... check if it's allowed directly
00835         if(!childAllowed(newChild)) {
00836             exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00837             return;
00838         }
00839     }
00840 }
00841 
00842 bool NodeImpl::isAncestor( NodeImpl *other )
00843 {
00844     // Return true if other is the same as this node or an ancestor of it, otherwise false
00845     NodeImpl *n;
00846     for (n = this; n; n = n->parentNode()) {
00847         if (n == other)
00848             return true;
00849     }
00850     return false;
00851 }
00852 
00853 bool NodeImpl::childAllowed( NodeImpl *newChild )
00854 {
00855     return childTypeAllowed(newChild->nodeType());
00856 }
00857 
00858 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
00859 {
00860     StyleChange ch = NoInherit;
00861     if ( !s1 || !s2 )
00862         ch = Inherit;
00863     else if ( *s1 == *s2 )
00864         ch = NoChange;
00865     else if ( s1->inheritedNotEqual( s2 ) )
00866         ch = Inherit;
00867     return ch;
00868 }
00869 
00870 #ifndef NDEBUG
00871 void NodeImpl::dump(QTextStream *stream, QString ind) const
00872 {
00873     // ### implement dump() for all appropriate subclasses
00874 
00875     if (m_hasId) { *stream << " hasId"; }
00876     if (m_hasStyle) { *stream << " hasStyle"; }
00877     if (m_specified) { *stream << " specified"; }
00878     if (m_focused) { *stream << " focused"; }
00879     if (m_active) { *stream << " active"; }
00880     if (m_styleElement) { *stream << " styleElement"; }
00881     if (m_implicit) { *stream << " implicit"; }
00882 
00883     *stream << " tabIndex=" << m_tabIndex;
00884     if (m_regdListeners)
00885         *stream << " #regdListeners=" << m_regdListeners->count(); // ### more detail
00886     *stream << endl;
00887 
00888     NodeImpl *child = firstChild();
00889     while( child != 0 )
00890     {
00891         *stream << ind << child->nodeName().string().ascii() << ": ";
00892         child->dump(stream,ind+"  ");
00893         child = child->nextSibling();
00894     }
00895 }
00896 #endif
00897 
00898 void NodeImpl::attach()
00899 {
00900     assert(!attached());
00901     assert(!m_render || (m_render->style() && m_render->parent()));
00902     m_attached = true;
00903 }
00904 
00905 void NodeImpl::detach()
00906 {
00907 //    assert(m_attached);
00908 
00909     if ( m_render )
00910         m_render->detach();
00911 
00912     m_render = 0;
00913     m_attached = false;
00914 }
00915 
00916 bool NodeImpl::maintainsState()
00917 {
00918     return false;
00919 }
00920 
00921 QString NodeImpl::state()
00922 {
00923     return QString::null;
00924 }
00925 
00926 void NodeImpl::restoreState(const QString &/*state*/)
00927 {
00928 }
00929 
00930 void NodeImpl::insertedIntoDocument()
00931 {
00932     setInDocument(true);
00933 }
00934 
00935 void NodeImpl::removedFromDocument()
00936 {
00937     setInDocument(false);
00938 }
00939 
00940 void NodeImpl::childrenChanged()
00941 {
00942     if (parentNode())
00943         parentNode()->childrenChanged();
00944 }
00945 
00946 bool NodeImpl::isReadOnly()
00947 {
00948     // Entity & Entity Reference nodes and their descendants are read-only
00949     NodeImpl *n = this;
00950     while (n) {
00951         if (n->nodeType() == Node::ENTITY_NODE ||
00952             n->nodeType() == Node::ENTITY_REFERENCE_NODE)
00953             return true;
00954         n = n->parentNode();
00955     }
00956     return false;
00957 }
00958 
00959 RenderObject * NodeImpl::nextRenderer()
00960 {
00961     for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
00962         if (n->renderer())
00963             return n->renderer();
00964     }
00965     return 0;
00966 }
00967 
00968 //-------------------------------------------------------------------------
00969 
00970 NodeBaseImpl::~NodeBaseImpl()
00971 {
00972     //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
00973     // we have to tell all children, that the parent has died...
00974     NodeImpl *n;
00975     NodeImpl *next;
00976 
00977     for( n = _first; n != 0; n = next ) {
00978         next = n->nextSibling();
00979         n->setPreviousSibling(0);
00980         n->setNextSibling(0);
00981         n->setParent(0);
00982         if ( !n->refCount() )
00983             delete n;
00984     }
00985 }
00986 
00987 
00988 NodeImpl *NodeBaseImpl::firstChild() const
00989 {
00990     return _first;
00991 }
00992 
00993 NodeImpl *NodeBaseImpl::lastChild() const
00994 {
00995     return _last;
00996 }
00997 
00998 NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
00999 {
01000     exceptioncode = 0;
01001 
01002     // insertBefore(...,null) is equivalent to appendChild()
01003     if(!refChild)
01004         return appendChild(newChild, exceptioncode);
01005 
01006     // Make sure adding the new child is ok
01007     checkAddChild(newChild, exceptioncode);
01008     if (exceptioncode)
01009         return 0;
01010 
01011     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
01012     if (refChild->parentNode() != this) {
01013         exceptioncode = DOMException::NOT_FOUND_ERR;
01014         return 0;
01015     }
01016 
01017     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
01018 
01019     // If newChild is a DocumentFragment with no children.... there's nothing to do.
01020     // Just return the document fragment
01021     if (isFragment && !newChild->firstChild())
01022         return newChild;
01023 
01024     // Now actually add the child(ren)
01025     NodeImpl *nextChild;
01026     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
01027 
01028     NodeImpl *prev = refChild->previousSibling();
01029     if ( prev == newChild || refChild == newChild ) // nothing to do
01030         return newChild;
01031 
01032     while (child) {
01033         nextChild = isFragment ? child->nextSibling() : 0;
01034 
01035         // If child is already present in the tree, first remove it
01036         NodeImpl *newParent = child->parentNode();
01037         if(newParent)
01038             newParent->removeChild( child, exceptioncode );
01039         if ( exceptioncode )
01040             return 0;
01041 
01042         // Add child in the correct position
01043         if (prev)
01044             prev->setNextSibling(child);
01045         else
01046             _first = child;
01047         refChild->setPreviousSibling(child);
01048         child->setParent(this);
01049         child->setPreviousSibling(prev);
01050         child->setNextSibling(refChild);
01051 
01052         // Add child to the rendering tree
01053         // ### should we detach() it first if it's already attached?
01054         if (attached() && !child->attached())
01055             child->attach();
01056 
01057         // Dispatch the mutation events
01058         dispatchChildInsertedEvents(child,exceptioncode);
01059 
01060         prev = child;
01061         child = nextChild;
01062     }
01063 
01064     // ### set style in case it's attached
01065     setChanged(true);
01066     dispatchSubtreeModifiedEvent();
01067     return newChild;
01068 }
01069 
01070 NodeImpl *NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
01071 {
01072     exceptioncode = 0;
01073 
01074     if ( oldChild == newChild ) // nothing to do
01075         return oldChild;
01076 
01077     // Make sure adding the new child is ok
01078     checkAddChild(newChild, exceptioncode);
01079     if (exceptioncode)
01080         return 0;
01081 
01082     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
01083     if (!oldChild || oldChild->parentNode() != this) {
01084         exceptioncode = DOMException::NOT_FOUND_ERR;
01085         return 0;
01086     }
01087 
01088     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
01089     NodeImpl *nextChild;
01090     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
01091 
01092 
01093     // Remove the old child
01094     NodeImpl *prev = oldChild->previousSibling();
01095     NodeImpl *next = oldChild->nextSibling();
01096 
01097     removeChild(oldChild, exceptioncode);
01098     if (exceptioncode)
01099         return 0;
01100 
01101     // Add the new child(ren)
01102     while (child) {
01103         nextChild = isFragment ? child->nextSibling() : 0;
01104 
01105         // If child is already present in the tree, first remove it
01106         NodeImpl *newParent = child->parentNode();
01107         if(newParent)
01108             newParent->removeChild( child, exceptioncode );
01109         if (exceptioncode)
01110             return 0;
01111 
01112         // Add child in the correct position
01113         if (prev) prev->setNextSibling(child);
01114         if (next) next->setPreviousSibling(child);
01115         if(!prev) _first = child;
01116         if(!next) _last = child;
01117         child->setParent(this);
01118         child->setPreviousSibling(prev);
01119         child->setNextSibling(next);
01120 
01121         // Add child to the rendering tree
01122         // ### should we detach() it first if it's already attached?
01123         if (attached() && !child->attached())
01124             child->attach();
01125 
01126         // Dispatch the mutation events
01127         dispatchChildInsertedEvents(child,exceptioncode);
01128 
01129         prev = child;
01130         child = nextChild;
01131     }
01132 
01133     // ### set style in case it's attached
01134     setChanged(true);
01135     dispatchSubtreeModifiedEvent();
01136     return oldChild;
01137 }
01138 
01139 NodeImpl *NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
01140 {
01141     exceptioncode = 0;
01142 
01143     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
01144     if (isReadOnly()) {
01145         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01146         return 0;
01147     }
01148 
01149     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
01150     if (!oldChild || oldChild->parentNode() != this) {
01151         exceptioncode = DOMException::NOT_FOUND_ERR;
01152         return 0;
01153     }
01154 
01155     // Dispatch pre-removal mutation events
01156     getDocument()->notifyBeforeNodeRemoval(oldChild); // ### use events instead
01157     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
01158         oldChild->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
01159                              true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01160         if (exceptioncode)
01161             return 0;
01162     }
01163 
01164     dispatchChildRemovalEvents(oldChild,exceptioncode);
01165     if (exceptioncode)
01166         return 0;
01167 
01168     // Remove from rendering tree
01169     if (oldChild->attached())
01170         oldChild->detach();
01171 
01172     // Remove the child
01173     NodeImpl *prev, *next;
01174     prev = oldChild->previousSibling();
01175     next = oldChild->nextSibling();
01176 
01177     if(next) next->setPreviousSibling(prev);
01178     if(prev) prev->setNextSibling(next);
01179     if(_first == oldChild) _first = next;
01180     if(_last == oldChild) _last = prev;
01181 
01182     oldChild->setPreviousSibling(0);
01183     oldChild->setNextSibling(0);
01184     oldChild->setParent(0);
01185 
01186     setChanged(true);
01187 
01188     // Dispatch post-removal mutation events
01189     dispatchSubtreeModifiedEvent();
01190 
01191     NodeImpl *p = this;
01192     while (p->parentNode())
01193         p = p->parentNode();
01194     if (p->nodeType() == Node::DOCUMENT_NODE) {
01195         for (NodeImpl *c = oldChild; c; c = c->traverseNextNode(oldChild))
01196             c->removedFromDocument();
01197     }
01198 
01199     return oldChild;
01200 }
01201 
01202 void NodeBaseImpl::removeChildren()
01203 {
01204     NodeImpl *n, *next;
01205     for( n = _first; n; n = next )
01206     {
01207         next = n->nextSibling();
01208         if (n->attached())
01209             n->detach();
01210         n->setPreviousSibling(0);
01211         n->setNextSibling(0);
01212         n->setParent(0);
01213         if( !n->refCount() )
01214             delete n;
01215         else
01216             for ( NodeImpl* c = n; c; c = c->traverseNextNode( n ) )
01217                 c->removedFromDocument();
01218     }
01219     _first = _last = 0;
01220 }
01221 
01222 
01223 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
01224 {
01225     exceptioncode = 0;
01226 
01227     // Make sure adding the new child is ok
01228     checkAddChild(newChild, exceptioncode);
01229     if (exceptioncode)
01230         return 0;
01231 
01232     if ( newChild == _last ) // nothing to do
01233         return newChild;
01234 
01235     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
01236 
01237     // If newChild is a DocumentFragment with no children.... there's nothing to do.
01238     // Just return the document fragment
01239     if (isFragment && !newChild->firstChild())
01240         return newChild;
01241 
01242     // Now actually add the child(ren)
01243     NodeImpl *nextChild;
01244     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
01245 
01246     while (child) {
01247         nextChild = isFragment ? child->nextSibling() : 0;
01248 
01249         // If child is already present in the tree, first remove it
01250         NodeImpl *oldParent = child->parentNode();
01251         if(oldParent) {
01252             oldParent->removeChild( child, exceptioncode );
01253             if (exceptioncode)
01254                 return 0;
01255         }
01256 
01257         // Append child to the end of the list
01258         child->setParent(this);
01259 
01260         if(_last)
01261         {
01262             child->setPreviousSibling(_last);
01263             _last->setNextSibling(child);
01264             _last = child;
01265         }
01266         else
01267         {
01268             _first = _last = child;
01269         }
01270 
01271         // Add child to the rendering tree
01272         // ### should we detach() it first if it's already attached?
01273         if (attached() && !child->attached())
01274             child->attach();
01275 
01276         // Dispatch the mutation events
01277         dispatchChildInsertedEvents(child,exceptioncode);
01278 
01279         child = nextChild;
01280     }
01281 
01282     setChanged(true);
01283     // ### set style in case it's attached
01284     dispatchSubtreeModifiedEvent();
01285     return newChild;
01286 }
01287 
01288 bool NodeBaseImpl::hasChildNodes (  ) const
01289 {
01290     return _first != 0;
01291 }
01292 
01293 // not part of the DOM
01294 void NodeBaseImpl::setFirstChild(NodeImpl *child)
01295 {
01296     _first = child;
01297 }
01298 
01299 void NodeBaseImpl::setLastChild(NodeImpl *child)
01300 {
01301     _last = child;
01302 }
01303 
01304 // check for same source document:
01305 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
01306 {
01307     exceptioncode = 0;
01308     DocumentImpl *ownerDocThis = getDocument();
01309     DocumentImpl *ownerDocNew = getDocument();
01310     if(ownerDocThis != ownerDocNew) {
01311         kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
01312         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
01313         return true;
01314     }
01315     return false;
01316 }
01317 
01318 // check for being child:
01319 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
01320 {
01321     if(!oldChild || oldChild->parentNode() != this) {
01322         exceptioncode = DOMException::NOT_FOUND_ERR;
01323         return true;
01324     }
01325     return false;
01326 }
01327 
01328 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
01329 {
01330     // do not add applyChanges here! This function is only used during parsing
01331 
01332     // short check for consistency with DTD
01333     if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
01334     {
01335         //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
01336         return 0;
01337     }
01338 
01339     // just add it...
01340     newChild->setParent(this);
01341 
01342     if(_last)
01343     {
01344         newChild->setPreviousSibling(_last);
01345         _last->setNextSibling(newChild);
01346         _last = newChild;
01347     }
01348     else
01349     {
01350         _first = _last = newChild;
01351     }
01352 
01353     newChild->insertedIntoDocument();
01354     childrenChanged();
01355 
01356     if(newChild->nodeType() == Node::ELEMENT_NODE)
01357         return newChild;
01358     return this;
01359 }
01360 
01361 void NodeBaseImpl::attach()
01362 {
01363     NodeImpl *child = _first;
01364     while(child != 0)
01365     {
01366         child->attach();
01367         child = child->nextSibling();
01368     }
01369     NodeImpl::attach();
01370 }
01371 
01372 void NodeBaseImpl::detach()
01373 {
01374     NodeImpl *child = _first;
01375     while(child != 0)
01376     {
01377         NodeImpl* prev = child;
01378         child = child->nextSibling();
01379         prev->detach();
01380     }
01381     NodeImpl::detach();
01382 }
01383 
01384 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
01385 {
01386     int exceptioncode = 0;
01387     NodeImpl *n;
01388     for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
01389     {
01390         clone->appendChild(n->cloneNode(true),exceptioncode);
01391     }
01392 }
01393 
01394 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
01395                                                      DOMStringImpl* localName )
01396 {
01397     if (!localName) return 0;
01398 
01399     NodeImpl::Id idMask = NodeImpl_IdNSMask | NodeImpl_IdLocalMask;
01400     if (localName->l && localName->s[0] == '*')
01401         idMask &= ~NodeImpl_IdLocalMask;
01402     if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
01403         idMask &= ~NodeImpl_IdNSMask;
01404 
01405     Id id = 0; // 0 means "all items"
01406     if ( (idMask & NodeImpl_IdLocalMask) || namespaceURI ) // not getElementsByTagName("*")
01407     {
01408         id = getDocument()->tagId( namespaceURI, localName, true /*readonly*/, 0 );
01409         if ( !id ) // not found -> we want to return an empty list, not "all items"
01410             id = (Id)-1;
01411     }
01412 
01413     return new TagNodeListImpl( this, id, idMask );
01414 }
01415 
01416 // I don't like this way of implementing the method, but I didn't find any
01417 // other way. Lars
01418 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
01419 {
01420     if (!m_render)
01421         return false;
01422     RenderObject *o = m_render;
01423     xPos = yPos = 0;
01424     if ( !o->isInline() || o->isReplaced() ) {
01425         o->absolutePosition( xPos, yPos );
01426         return true;
01427     }
01428 
01429     // find the next text/image child, to get a position
01430     while(o) {
01431         if(o->firstChild())
01432             o = o->firstChild();
01433         else if(o->nextSibling())
01434             o = o->nextSibling();
01435         else {
01436             RenderObject *next = 0;
01437             while(!next) {
01438                 o = o->parent();
01439                 if(!o) return false;
01440                 next = o->nextSibling();
01441             }
01442             o = next;
01443         }
01444         if((o->isText() && !o->isBR()) || o->isReplaced()) {
01445             o->container()->absolutePosition( xPos, yPos );
01446             if (o->isText())
01447                 xPos += static_cast<RenderText *>(o)->minXPos();
01448             else
01449                 xPos += o->xPos();
01450             yPos += o->yPos();
01451             return true;
01452         }
01453     }
01454     return true;
01455 }
01456 
01457 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
01458 {
01459     if (!m_render)
01460         return false;
01461 
01462     RenderObject *o = m_render;
01463     xPos = yPos = 0;
01464     if (!o->isInline() || o->isReplaced())
01465     {
01466         o->absolutePosition( xPos, yPos );
01467         xPos += o->width();
01468         yPos += o->height();
01469         return true;
01470     }
01471     // find the last text/image child, to get a position
01472     while(o) {
01473         if(o->lastChild())
01474             o = o->lastChild();
01475         else if(o->previousSibling())
01476             o = o->previousSibling();
01477         else {
01478             RenderObject *prev = 0;
01479             while(!prev) {
01480                 o = o->parent();
01481                 if(!o) return false;
01482                 prev = o->previousSibling();
01483             }
01484             o = prev;
01485         }
01486         if((o->isText() && !o->isBR()) || o->isReplaced()) {
01487             o->container()->absolutePosition(xPos, yPos);
01488             if (o->isText())
01489                 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
01490             else
01491                 xPos += o->xPos()+o->width();
01492             yPos += o->yPos()+o->height();
01493             return true;
01494         }
01495     }
01496     return true;
01497 }
01498 
01499 QRect NodeBaseImpl::getRect() const
01500 {
01501     int xPos, yPos;
01502     if (!getUpperLeftCorner(xPos,yPos))
01503     {
01504         xPos=0;
01505         yPos=0;
01506     }
01507     int xEnd, yEnd;
01508     if (!getLowerRightCorner(xEnd,yEnd))
01509     {
01510         if (xPos)
01511             xEnd = xPos;
01512         if (yPos)
01513             yEnd = yPos;
01514     }
01515     else
01516     {
01517         if (xPos==0)
01518             xPos = xEnd;
01519         if (yPos==0)
01520             yPos = yEnd;
01521     }
01522     if ( xEnd <= xPos || yEnd <= yPos )
01523         return QRect( QPoint( xPos, yPos ), QSize() );
01524 
01525     return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
01526 }
01527 
01528 void NodeBaseImpl::setFocus(bool received)
01529 {
01530     if (m_focused == received) return;
01531 
01532     NodeImpl::setFocus(received);
01533     for(NodeImpl *it=_first;it;it=it->nextSibling())
01534         it->setFocus(received);
01535 
01536     // note that we need to recalc the style
01537     setChanged();
01538 }
01539 
01540 void NodeBaseImpl::setActive(bool down)
01541 {
01542     if (down == active()) return;
01543 
01544     NodeImpl::setActive(down);
01545 
01546     // note that we need to recalc the style
01547     if (m_render && m_render->style()->hasActive())
01548         setChanged();
01549 }
01550 
01551 unsigned long NodeBaseImpl::childNodeCount()
01552 {
01553     unsigned long count = 0;
01554     NodeImpl *n;
01555     for (n = firstChild(); n; n = n->nextSibling())
01556         count++;
01557     return count;
01558 }
01559 
01560 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
01561 {
01562     unsigned long i;
01563     NodeImpl *n = firstChild();
01564     for (i = 0; i < index; i++)
01565         n = n->nextSibling();
01566     return n;
01567 }
01568 
01569 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
01570 {
01571     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
01572         child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
01573                                                    true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01574         if (exceptioncode)
01575             return;
01576     }
01577 
01578     // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
01579     bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
01580     NodeImpl *p = this;
01581     while (p->parentNode())
01582         p = p->parentNode();
01583     if (p->nodeType() == Node::DOCUMENT_NODE) {
01584         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
01585             c->insertedIntoDocument();
01586 
01587             if (hasInsertedListeners) {
01588                 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
01589                                                        false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01590                 if (exceptioncode)
01591                     return;
01592             }
01593         }
01594     }
01595 }
01596 
01597 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
01598 {
01599     // Dispatch pre-removal mutation events
01600     getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
01601     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
01602         child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
01603                              true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01604         if (exceptioncode)
01605             return;
01606     }
01607 
01608     bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
01609 
01610     // dispatch the DOMNOdeRemovedFromDocument event to all descendants
01611     NodeImpl *p = this;
01612     while (p->parentNode())
01613         p = p->parentNode();
01614     if (p->nodeType() == Node::DOCUMENT_NODE) {
01615         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
01616             if (hasRemovalListeners) {
01617                 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
01618                                  false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01619                 if (exceptioncode)
01620                     return;
01621             }
01622         }
01623     }
01624 }
01625 
01626 // ---------------------------------------------------------------------------
01627 
01628 NodeImpl *NodeListImpl::item( unsigned long /*index*/ ) const
01629 {
01630     return 0;
01631 }
01632 
01633 unsigned long NodeListImpl::length() const
01634 {
01635     return 0;
01636 }
01637 
01638 unsigned long NodeListImpl::recursiveLength(NodeImpl *start) const
01639 {
01640     unsigned long len = 0;
01641 
01642     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
01643         if ( n->nodeType() == Node::ELEMENT_NODE ) {
01644             if (nodeMatches(n))
01645                 len++;
01646             len+= recursiveLength(n);
01647         }
01648     }
01649 
01650     return len;
01651 }
01652 
01653 NodeImpl *NodeListImpl::recursiveItem ( NodeImpl *start, unsigned long &offset ) const
01654 {
01655     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
01656         if ( n->nodeType() == Node::ELEMENT_NODE ) {
01657             if (nodeMatches(n))
01658                 if (!offset--)
01659                     return n;
01660 
01661             NodeImpl *depthSearch= recursiveItem(n, offset);
01662             if (depthSearch)
01663                 return depthSearch;
01664         }
01665     }
01666 
01667     return 0; // no matching node in this subtree
01668 }
01669 
01670 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
01671 {
01672     refNode = n;
01673     refNode->ref();
01674 }
01675 
01676 ChildNodeListImpl::~ChildNodeListImpl()
01677 {
01678     refNode->deref();
01679 }
01680 
01681 unsigned long ChildNodeListImpl::length() const
01682 {
01683     unsigned long len = 0;
01684     NodeImpl *n;
01685     for(n = refNode->firstChild(); n != 0; n = n->nextSibling())
01686         len++;
01687 
01688     return len;
01689 }
01690 
01691 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
01692 {
01693     unsigned int pos = 0;
01694     NodeImpl *n = refNode->firstChild();
01695 
01696     while( n != 0 && pos < index )
01697     {
01698         n = n->nextSibling();
01699         pos++;
01700     }
01701 
01702     return n;
01703 }
01704 
01705 bool ChildNodeListImpl::nodeMatches( NodeImpl */*testNode*/ ) const
01706 {
01707     return true;
01708 }
01709 
01710 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
01711     : refNode(n), m_id(_id & _idMask), m_idMask(_idMask)
01712 {
01713     refNode->ref();
01714 }
01715 
01716 TagNodeListImpl::~TagNodeListImpl()
01717 {
01718     refNode->deref();
01719 }
01720 
01721 unsigned long TagNodeListImpl::length() const
01722 {
01723     return recursiveLength( refNode );
01724 }
01725 
01726 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
01727 {
01728     return recursiveItem( refNode, index );
01729 }
01730 
01731 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01732 {
01733     return testNode->isElementNode() &&
01734            ((testNode->id() & m_idMask) == m_id);
01735 }
01736 
01737 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
01738   : nodeName(t)
01739 {
01740     refNode= n;
01741     refNode->ref();
01742 }
01743 
01744 NameNodeListImpl::~NameNodeListImpl()
01745 {
01746     refNode->deref();
01747 }
01748 
01749 unsigned long NameNodeListImpl::length() const
01750 {
01751     return recursiveLength( refNode );
01752 }
01753 
01754 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
01755 {
01756     return recursiveItem( refNode, index );
01757 }
01758 
01759 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01760 {
01761     return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
01762 }
01763 
01764 NamedTagNodeListImpl::NamedTagNodeListImpl( NodeImpl *n, NodeImpl::Id tagId, const DOMString& name, NodeImpl::Id tagIdMask )
01765     : TagNodeListImpl( n, tagId, tagIdMask ), nodeName( name )
01766 {
01767 }
01768 
01769 bool NamedTagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01770 {
01771     return TagNodeListImpl::nodeMatches( testNode )
01772         && static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
01773 }
01774 
01775 
01776 // ---------------------------------------------------------------------------
01777 
01778 NamedNodeMapImpl::NamedNodeMapImpl()
01779 {
01780 }
01781 
01782 NamedNodeMapImpl::~NamedNodeMapImpl()
01783 {
01784 }
01785 
01786 // ----------------------------------------------------------------------------
01787 
01788 // ### unused
01789 #if 0
01790 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
01791     : NamedNodeMapImpl()
01792 {
01793     m_doc = doc->document();
01794     m_contents = new QPtrList<NodeImpl>;
01795 }
01796 
01797 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
01798 {
01799     while (m_contents->count() > 0)
01800         m_contents->take(0)->deref();
01801 
01802     delete m_contents;
01803 }
01804 
01805 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
01806 {
01807     QPtrListIterator<NodeImpl> it(*m_contents);
01808     for (; it.current(); ++it)
01809         if (it.current()->nodeName() == name)
01810             return it.current();
01811     return 0;
01812 }
01813 
01814 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
01815 {
01816     // can't modify this list through standard DOM functions
01817     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01818     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01819     return 0;
01820 }
01821 
01822 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
01823 {
01824     // can't modify this list through standard DOM functions
01825     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01826     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01827     return 0;
01828 }
01829 
01830 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
01831 {
01832     // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
01833     // (also for other similar methods)
01834     if (index >= m_contents->count())
01835         return 0;
01836 
01837     return m_contents->at(index);
01838 }
01839 
01840 unsigned long GenericRONamedNodeMapImpl::length(  ) const
01841 {
01842     return m_contents->count();
01843 }
01844 
01845 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
01846                                                      const DOMString &localName,
01847                                                      int &/*exceptioncode*/ ) const
01848 {
01849     NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
01850                                          localName.implementation(), true, 0);
01851 
01852     QPtrListIterator<NodeImpl> it(*m_contents);
01853     for (; it.current(); ++it)
01854         if (it.current()->id() == searchId)
01855             return it.current();
01856 
01857     return 0;
01858 }
01859 
01860 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
01861 {
01862     // can't modify this list through standard DOM functions
01863     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01864     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01865     return 0;
01866 }
01867 
01868 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
01869                                                         const DOMString &/*localName*/,
01870                                                         int &exceptioncode )
01871 {
01872     // can't modify this list through standard DOM functions
01873     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01874     return 0;
01875 }
01876 
01877 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
01878 {
01879     // The spec says that in the case of duplicates we only keep the first one
01880     int exceptioncode = 0;
01881     if (getNamedItem(n->nodeName(),exceptioncode))
01882         return;
01883 
01884     n->ref();
01885     m_contents->append(n);
01886 }
01887 
01888 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:46 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001