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 != 0; 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     }
01216     _first = _last = 0;
01217 }
01218 
01219 
01220 NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
01221 {
01222     exceptioncode = 0;
01223 
01224     // Make sure adding the new child is ok
01225     checkAddChild(newChild, exceptioncode);
01226     if (exceptioncode)
01227         return 0;
01228 
01229     if ( newChild == _last ) // nothing to do
01230     return newChild;
01231 
01232     bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
01233 
01234     // If newChild is a DocumentFragment with no children.... there's nothing to do.
01235     // Just return the document fragment
01236     if (isFragment && !newChild->firstChild())
01237         return newChild;
01238 
01239     // Now actually add the child(ren)
01240     NodeImpl *nextChild;
01241     NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
01242 
01243     while (child) {
01244         nextChild = isFragment ? child->nextSibling() : 0;
01245 
01246         // If child is already present in the tree, first remove it
01247         NodeImpl *oldParent = child->parentNode();
01248         if(oldParent) {
01249             oldParent->removeChild( child, exceptioncode );
01250             if (exceptioncode)
01251                 return 0;
01252         }
01253 
01254         // Append child to the end of the list
01255         child->setParent(this);
01256 
01257         if(_last)
01258         {
01259             child->setPreviousSibling(_last);
01260             _last->setNextSibling(child);
01261             _last = child;
01262         }
01263         else
01264         {
01265             _first = _last = child;
01266         }
01267 
01268         // Add child to the rendering tree
01269         // ### should we detach() it first if it's already attached?
01270         if (attached() && !child->attached())
01271             child->attach();
01272 
01273         // Dispatch the mutation events
01274         dispatchChildInsertedEvents(child,exceptioncode);
01275 
01276         child = nextChild;
01277     }
01278 
01279     setChanged(true);
01280     // ### set style in case it's attached
01281     dispatchSubtreeModifiedEvent();
01282     return newChild;
01283 }
01284 
01285 bool NodeBaseImpl::hasChildNodes (  ) const
01286 {
01287     return _first != 0;
01288 }
01289 
01290 // not part of the DOM
01291 void NodeBaseImpl::setFirstChild(NodeImpl *child)
01292 {
01293     _first = child;
01294 }
01295 
01296 void NodeBaseImpl::setLastChild(NodeImpl *child)
01297 {
01298     _last = child;
01299 }
01300 
01301 // check for same source document:
01302 bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
01303 {
01304     exceptioncode = 0;
01305     DocumentImpl *ownerDocThis = getDocument();
01306     DocumentImpl *ownerDocNew = getDocument();
01307     if(ownerDocThis != ownerDocNew) {
01308         kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
01309         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
01310         return true;
01311     }
01312     return false;
01313 }
01314 
01315 // check for being child:
01316 bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
01317 {
01318     if(!oldChild || oldChild->parentNode() != this) {
01319         exceptioncode = DOMException::NOT_FOUND_ERR;
01320         return true;
01321     }
01322     return false;
01323 }
01324 
01325 NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
01326 {
01327     // do not add applyChanges here! This function is only used during parsing
01328 
01329     // short check for consistency with DTD
01330     if(!isXMLElementNode() && !newChild->isXMLElementNode() && !childAllowed(newChild))
01331     {
01332         //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
01333         return 0;
01334     }
01335 
01336     // just add it...
01337     newChild->setParent(this);
01338 
01339     if(_last)
01340     {
01341         newChild->setPreviousSibling(_last);
01342         _last->setNextSibling(newChild);
01343         _last = newChild;
01344     }
01345     else
01346     {
01347         _first = _last = newChild;
01348     }
01349 
01350     newChild->insertedIntoDocument();
01351     childrenChanged();
01352 
01353     if(newChild->nodeType() == Node::ELEMENT_NODE)
01354         return newChild;
01355     return this;
01356 }
01357 
01358 void NodeBaseImpl::attach()
01359 {
01360     NodeImpl *child = _first;
01361     while(child != 0)
01362     {
01363         child->attach();
01364         child = child->nextSibling();
01365     }
01366     NodeImpl::attach();
01367 }
01368 
01369 void NodeBaseImpl::detach()
01370 {
01371     NodeImpl *child = _first;
01372     while(child != 0)
01373     {
01374         NodeImpl* prev = child;
01375         child = child->nextSibling();
01376         prev->detach();
01377     }
01378     NodeImpl::detach();
01379 }
01380 
01381 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
01382 {
01383     int exceptioncode = 0;
01384     NodeImpl *n;
01385     for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
01386     {
01387         clone->appendChild(n->cloneNode(true),exceptioncode);
01388     }
01389 }
01390 
01391 NodeListImpl* NodeBaseImpl::getElementsByTagNameNS ( DOMStringImpl* namespaceURI,
01392                                                      DOMStringImpl* localName )
01393 {
01394     if (!localName) return 0;
01395 
01396     NodeImpl::Id idMask = NodeImpl_IdNSMask | NodeImpl_IdLocalMask;
01397     if (localName->l && localName->s[0] == '*')
01398         idMask &= ~NodeImpl_IdLocalMask;
01399     if (namespaceURI && namespaceURI->l && namespaceURI->s[0] == '*')
01400         idMask &= ~NodeImpl_IdNSMask;
01401 
01402     return new TagNodeListImpl( this,
01403                                 getDocument()->tagId(namespaceURI, localName, true), idMask);
01404 }
01405 
01406 // I don't like this way of implementing the method, but I didn't find any
01407 // other way. Lars
01408 bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
01409 {
01410     if (!m_render)
01411         return false;
01412     RenderObject *o = m_render;
01413     xPos = yPos = 0;
01414     if ( !o->isInline() || o->isReplaced() ) {
01415         o->absolutePosition( xPos, yPos );
01416         return true;
01417     }
01418 
01419     // find the next text/image child, to get a position
01420     while(o) {
01421         if(o->firstChild())
01422             o = o->firstChild();
01423         else if(o->nextSibling())
01424             o = o->nextSibling();
01425         else {
01426             RenderObject *next = 0;
01427             while(!next) {
01428                 o = o->parent();
01429                 if(!o) return false;
01430                 next = o->nextSibling();
01431             }
01432             o = next;
01433         }
01434         if((o->isText() && !o->isBR()) || o->isReplaced()) {
01435             o->container()->absolutePosition( xPos, yPos );
01436             if (o->isText())
01437                 xPos += static_cast<RenderText *>(o)->minXPos();
01438             else
01439                 xPos += o->xPos();
01440             yPos += o->yPos();
01441             return true;
01442         }
01443     }
01444     return true;
01445 }
01446 
01447 bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
01448 {
01449     if (!m_render)
01450         return false;
01451 
01452     RenderObject *o = m_render;
01453     xPos = yPos = 0;
01454     if (!o->isInline() || o->isReplaced())
01455     {
01456         o->absolutePosition( xPos, yPos );
01457         xPos += o->width();
01458         yPos += o->height();
01459         return true;
01460     }
01461     // find the last text/image child, to get a position
01462     while(o) {
01463         if(o->lastChild())
01464             o = o->lastChild();
01465         else if(o->previousSibling())
01466             o = o->previousSibling();
01467         else {
01468             RenderObject *prev = 0;
01469             while(!prev) {
01470                 o = o->parent();
01471                 if(!o) return false;
01472                 prev = o->previousSibling();
01473             }
01474             o = prev;
01475         }
01476         if((o->isText() && !o->isBR()) || o->isReplaced()) {
01477             o->container()->absolutePosition(xPos, yPos);
01478             if (o->isText())
01479                 xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
01480             else
01481                 xPos += o->xPos()+o->width();
01482             yPos += o->yPos()+o->height();
01483             return true;
01484         }
01485     }
01486     return true;
01487 }
01488 
01489 QRect NodeBaseImpl::getRect() const
01490 {
01491     int xPos, yPos;
01492     if (!getUpperLeftCorner(xPos,yPos))
01493     {
01494         xPos=0;
01495         yPos=0;
01496     }
01497     int xEnd, yEnd;
01498     if (!getLowerRightCorner(xEnd,yEnd))
01499     {
01500         if (xPos)
01501             xEnd = xPos;
01502         if (yPos)
01503             yEnd = yPos;
01504     }
01505     else
01506     {
01507         if (xPos==0)
01508             xPos = xEnd;
01509         if (yPos==0)
01510             yPos = yEnd;
01511     }
01512     if ( xEnd <= xPos || yEnd <= yPos )
01513         return QRect( QPoint( xPos, yPos ), QSize() );
01514 
01515     return QRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
01516 }
01517 
01518 void NodeBaseImpl::setFocus(bool received)
01519 {
01520     if (m_focused == received) return;
01521 
01522     NodeImpl::setFocus(received);
01523     for(NodeImpl *it=_first;it;it=it->nextSibling())
01524         it->setFocus(received);
01525 
01526     // note that we need to recalc the style
01527     setChanged();
01528 }
01529 
01530 void NodeBaseImpl::setActive(bool down)
01531 {
01532     if (down == active()) return;
01533 
01534     NodeImpl::setActive(down);
01535 
01536     // note that we need to recalc the style
01537     if (m_render && m_render->style()->hasActive())
01538         setChanged();
01539 }
01540 
01541 unsigned long NodeBaseImpl::childNodeCount()
01542 {
01543     unsigned long count = 0;
01544     NodeImpl *n;
01545     for (n = firstChild(); n; n = n->nextSibling())
01546         count++;
01547     return count;
01548 }
01549 
01550 NodeImpl *NodeBaseImpl::childNode(unsigned long index)
01551 {
01552     unsigned long i;
01553     NodeImpl *n = firstChild();
01554     for (i = 0; i < index; i++)
01555         n = n->nextSibling();
01556     return n;
01557 }
01558 
01559 void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
01560 {
01561     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
01562         child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,
01563                                                    true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01564         if (exceptioncode)
01565             return;
01566     }
01567 
01568     // dispatch the DOMNOdeInsertedInfoDocument event to all descendants
01569     bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
01570     NodeImpl *p = this;
01571     while (p->parentNode())
01572         p = p->parentNode();
01573     if (p->nodeType() == Node::DOCUMENT_NODE) {
01574         for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
01575             c->insertedIntoDocument();
01576 
01577             if (hasInsertedListeners) {
01578                 c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,
01579                                                        false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01580                 if (exceptioncode)
01581                     return;
01582             }
01583         }
01584     }
01585 }
01586 
01587 void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
01588 {
01589     // Dispatch pre-removal mutation events
01590     getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
01591     if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
01592     child->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,
01593                  true,false,this,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01594     if (exceptioncode)
01595         return;
01596     }
01597 
01598     bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
01599 
01600     // dispatch the DOMNOdeRemovedFromDocument event to all descendants
01601     NodeImpl *p = this;
01602     while (p->parentNode())
01603     p = p->parentNode();
01604     if (p->nodeType() == Node::DOCUMENT_NODE) {
01605     for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
01606         if (hasRemovalListeners) {
01607         c->dispatchEvent(new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,
01608                  false,false,0,DOMString(),DOMString(),DOMString(),0),exceptioncode,true);
01609         if (exceptioncode)
01610             return;
01611         }
01612     }
01613     }
01614 }
01615 
01616 // ---------------------------------------------------------------------------
01617 
01618 NodeImpl *NodeListImpl::item( unsigned long /*index*/ ) const
01619 {
01620     return 0;
01621 }
01622 
01623 unsigned long NodeListImpl::length() const
01624 {
01625     return 0;
01626 }
01627 
01628 unsigned long NodeListImpl::recursiveLength(NodeImpl *start) const
01629 {
01630     unsigned long len = 0;
01631 
01632     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
01633         if ( n->nodeType() == Node::ELEMENT_NODE ) {
01634             if (nodeMatches(n))
01635                 len++;
01636             len+= recursiveLength(n);
01637         }
01638     }
01639 
01640     return len;
01641 }
01642 
01643 NodeImpl *NodeListImpl::recursiveItem ( NodeImpl *start, unsigned long &offset ) const
01644 {
01645     for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
01646         if ( n->nodeType() == Node::ELEMENT_NODE ) {
01647             if (nodeMatches(n))
01648                 if (!offset--)
01649                     return n;
01650 
01651             NodeImpl *depthSearch= recursiveItem(n, offset);
01652             if (depthSearch)
01653                 return depthSearch;
01654         }
01655     }
01656 
01657     return 0; // no matching node in this subtree
01658 }
01659 
01660 ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n )
01661 {
01662     refNode = n;
01663     refNode->ref();
01664 }
01665 
01666 ChildNodeListImpl::~ChildNodeListImpl()
01667 {
01668     refNode->deref();
01669 }
01670 
01671 unsigned long ChildNodeListImpl::length() const
01672 {
01673     unsigned long len = 0;
01674     NodeImpl *n;
01675     for(n = refNode->firstChild(); n != 0; n = n->nextSibling())
01676         len++;
01677 
01678     return len;
01679 }
01680 
01681 NodeImpl *ChildNodeListImpl::item ( unsigned long index ) const
01682 {
01683     unsigned int pos = 0;
01684     NodeImpl *n = refNode->firstChild();
01685 
01686     while( n != 0 && pos < index )
01687     {
01688         n = n->nextSibling();
01689         pos++;
01690     }
01691 
01692     return n;
01693 }
01694 
01695 bool ChildNodeListImpl::nodeMatches( NodeImpl */*testNode*/ ) const
01696 {
01697     return true;
01698 }
01699 
01700 TagNodeListImpl::TagNodeListImpl(NodeImpl *n, NodeImpl::Id _id, NodeImpl::Id _idMask )
01701     : refNode(n), m_id(_id & _idMask), m_idMask(_idMask)
01702 {
01703     refNode->ref();
01704 }
01705 
01706 TagNodeListImpl::~TagNodeListImpl()
01707 {
01708     refNode->deref();
01709 }
01710 
01711 unsigned long TagNodeListImpl::length() const
01712 {
01713     return recursiveLength( refNode );
01714 }
01715 
01716 NodeImpl *TagNodeListImpl::item ( unsigned long index ) const
01717 {
01718     return recursiveItem( refNode, index );
01719 }
01720 
01721 bool TagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01722 {
01723     return ( testNode->isElementNode() && m_id &&
01724              (testNode->id() & m_idMask) == m_id);
01725 }
01726 
01727 NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
01728   : nodeName(t)
01729 {
01730     refNode= n;
01731     refNode->ref();
01732 }
01733 
01734 NameNodeListImpl::~NameNodeListImpl()
01735 {
01736     refNode->deref();
01737 }
01738 
01739 unsigned long NameNodeListImpl::length() const
01740 {
01741     return recursiveLength( refNode );
01742 }
01743 
01744 NodeImpl *NameNodeListImpl::item ( unsigned long index ) const
01745 {
01746     return recursiveItem( refNode, index );
01747 }
01748 
01749 bool NameNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01750 {
01751     return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
01752 }
01753 
01754 NamedTagNodeListImpl::NamedTagNodeListImpl( NodeImpl *n, NodeImpl::Id tagId, const DOMString& name, NodeImpl::Id tagIdMask )
01755     : TagNodeListImpl( n, tagId, tagIdMask ), nodeName( name )
01756 {
01757 }
01758 
01759 bool NamedTagNodeListImpl::nodeMatches( NodeImpl *testNode ) const
01760 {
01761     return TagNodeListImpl::nodeMatches( testNode )
01762         && static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
01763 }
01764 
01765 
01766 // ---------------------------------------------------------------------------
01767 
01768 NamedNodeMapImpl::NamedNodeMapImpl()
01769 {
01770 }
01771 
01772 NamedNodeMapImpl::~NamedNodeMapImpl()
01773 {
01774 }
01775 
01776 // ----------------------------------------------------------------------------
01777 
01778 // ### unused
01779 #if 0
01780 GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc)
01781     : NamedNodeMapImpl()
01782 {
01783     m_doc = doc->document();
01784     m_contents = new QPtrList<NodeImpl>;
01785 }
01786 
01787 GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
01788 {
01789     while (m_contents->count() > 0)
01790         m_contents->take(0)->deref();
01791 
01792     delete m_contents;
01793 }
01794 
01795 NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( const DOMString &name, int &/*exceptioncode*/ ) const
01796 {
01797     QPtrListIterator<NodeImpl> it(*m_contents);
01798     for (; it.current(); ++it)
01799         if (it.current()->nodeName() == name)
01800             return it.current();
01801     return 0;
01802 }
01803 
01804 Node GenericRONamedNodeMapImpl::setNamedItem ( const Node &/*arg*/, int &exceptioncode )
01805 {
01806     // can't modify this list through standard DOM functions
01807     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01808     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01809     return 0;
01810 }
01811 
01812 Node GenericRONamedNodeMapImpl::removeNamedItem ( const DOMString &/*name*/, int &exceptioncode )
01813 {
01814     // can't modify this list through standard DOM functions
01815     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01816     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01817     return 0;
01818 }
01819 
01820 NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
01821 {
01822     // ### check this when calling from javascript using -1 = 2^sizeof(int)-1
01823     // (also for other similar methods)
01824     if (index >= m_contents->count())
01825         return 0;
01826 
01827     return m_contents->at(index);
01828 }
01829 
01830 unsigned long GenericRONamedNodeMapImpl::length(  ) const
01831 {
01832     return m_contents->count();
01833 }
01834 
01835 NodeImpl *GenericRONamedNodeMapImpl::getNamedItemNS( const DOMString &namespaceURI,
01836                                                      const DOMString &localName,
01837                                                      int &/*exceptioncode*/ ) const
01838 {
01839     NodeImpl::Id searchId = m_doc->tagId(namespaceURI.implementation(),
01840                                                    localName.implementation(), true);
01841 
01842     QPtrListIterator<NodeImpl> it(*m_contents);
01843     for (; it.current(); ++it)
01844         if (it.current()->id() == searchId)
01845             return it.current();
01846 
01847     return 0;
01848 }
01849 
01850 NodeImpl *GenericRONamedNodeMapImpl::setNamedItemNS( NodeImpl */*arg*/, int &exceptioncode )
01851 {
01852     // can't modify this list through standard DOM functions
01853     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
01854     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01855     return 0;
01856 }
01857 
01858 NodeImpl *GenericRONamedNodeMapImpl::removeNamedItemNS( const DOMString &/*namespaceURI*/,
01859                                                         const DOMString &/*localName*/,
01860                                                         int &exceptioncode )
01861 {
01862     // can't modify this list through standard DOM functions
01863     exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
01864     return 0;
01865 }
01866 
01867 void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
01868 {
01869     // The spec says that in the case of duplicates we only keep the first one
01870     int exceptioncode = 0;
01871     if (getNamedItem(n->nodeName(),exceptioncode))
01872         return;
01873 
01874     n->ref();
01875     m_contents->append(n);
01876 }
01877 
01878 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:22:36 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001