# khtml Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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

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