khtml Library API Documentation

dom2_traversalimpl.cpp

00001 
00024 #include "dom/dom_exception.h"
00025 #include "xml/dom_docimpl.h"
00026 
00027 using namespace DOM;
00028 
00029 NodeIteratorImpl::NodeIteratorImpl(NodeImpl *_root, unsigned long _whatToShow,
00030                    NodeFilter _filter, bool _entityReferenceExpansion)
00031 {
00032     m_root = _root;
00033     m_whatToShow = _whatToShow;
00034     m_filter = _filter;
00035     m_expandEntityReferences = _entityReferenceExpansion;
00036 
00037     m_referenceNode = _root;
00038     m_inFront = false;
00039 
00040     m_doc = m_root->getDocument();
00041     m_doc->attachNodeIterator(this);
00042     m_doc->ref();
00043 
00044     m_detached = false;
00045 }
00046 
00047 NodeIteratorImpl::~NodeIteratorImpl()
00048 {
00049     m_doc->detachNodeIterator(this);
00050     m_doc->deref();
00051 }
00052 
00053 NodeImpl *NodeIteratorImpl::root()
00054 {
00055     return m_root;
00056 }
00057 
00058 unsigned long NodeIteratorImpl::whatToShow()
00059 {
00060     return m_whatToShow;
00061 }
00062 
00063 NodeFilter NodeIteratorImpl::filter()
00064 {
00065     return m_filter;
00066 }
00067 
00068 bool NodeIteratorImpl::expandEntityReferences()
00069 {
00070     return m_expandEntityReferences;
00071 }
00072 
00073 NodeImpl *NodeIteratorImpl::nextNode( int &exceptioncode )
00074 {
00075     if (m_detached) {
00076     exceptioncode = DOMException::INVALID_STATE_ERR;
00077     return 0;
00078     }
00079 
00080     if (!m_referenceNode) {
00081     m_inFront = true;
00082     return 0;
00083     }
00084 
00085     if (!m_inFront) {
00086     m_inFront = true;
00087     if (isAccepted(m_referenceNode) == NodeFilter::FILTER_ACCEPT)
00088         return m_referenceNode;
00089     }
00090 
00091     NodeImpl *_tempCurrent = getNextNode(m_referenceNode);
00092     while( _tempCurrent ) {
00093     m_referenceNode = _tempCurrent;
00094     if(isAccepted(_tempCurrent) == NodeFilter::FILTER_ACCEPT)
00095         return m_referenceNode;
00096       _tempCurrent = getNextNode(_tempCurrent);
00097     }
00098 
00099     return 0;
00100 }
00101 
00102 NodeImpl *NodeIteratorImpl::getNextNode(NodeImpl *n)
00103 {
00104   /*  1. my first child
00105    *  2. my next sibling
00106    *  3. my parents sibling, or their parents sibling (loop)
00107    *  4. not found
00108    */
00109 
00110   if( !n )
00111     return 0;
00112 
00113   if( n->hasChildNodes() )
00114     return n->firstChild();
00115 
00116   if( n->nextSibling() )
00117     return n->nextSibling();
00118 
00119   if( m_root == n)
00120      return 0;
00121 
00122   NodeImpl *parent = n->parentNode();
00123   while( parent )
00124     {
00125       n = parent->nextSibling();
00126       if( n )
00127         return n;
00128 
00129       if( m_root == parent )
00130         return 0;
00131 
00132       parent = parent->parentNode();
00133     }
00134   return 0;
00135 }
00136 
00137 NodeImpl *NodeIteratorImpl::previousNode( int &exceptioncode )
00138 {
00139     if (m_detached) {
00140     exceptioncode = DOMException::INVALID_STATE_ERR;
00141     return 0;
00142     }
00143 
00144     if (!m_referenceNode) {
00145     m_inFront = false;
00146     return 0;
00147     }
00148 
00149     if (m_inFront) {
00150     m_inFront = false;
00151     if (isAccepted(m_referenceNode) == NodeFilter::FILTER_ACCEPT)
00152         return m_referenceNode;
00153     }
00154 
00155     NodeImpl *_tempCurrent = getPreviousNode(m_referenceNode);
00156     while( _tempCurrent ) {
00157     m_referenceNode = _tempCurrent;
00158     if(isAccepted(_tempCurrent) == NodeFilter::FILTER_ACCEPT)
00159         return m_referenceNode;
00160     _tempCurrent = getPreviousNode(_tempCurrent);
00161     }
00162 
00163     return 0;
00164 }
00165 
00166 NodeImpl *NodeIteratorImpl::getPreviousNode(NodeImpl *n)
00167 {
00168 /* 1. my previous sibling.lastchild
00169  * 2. my previous sibling
00170  * 3. my parent
00171  */
00172   NodeImpl *_tempCurrent;
00173 
00174   if( !n )
00175     return 0;
00176 
00177   _tempCurrent = n->previousSibling();
00178   if( _tempCurrent )
00179     {
00180       if( _tempCurrent->lastChild() )
00181         {
00182           while( _tempCurrent->lastChild() )
00183             _tempCurrent = _tempCurrent->lastChild();
00184           return _tempCurrent;
00185         }
00186       else
00187         return _tempCurrent;
00188     }
00189 
00190 
00191   if(n == m_root)
00192     return 0;
00193 
00194   return n->parentNode();
00195 
00196 
00197 }
00198 
00199 void NodeIteratorImpl::detach(int &/*exceptioncode*/)
00200 {
00201     m_doc->detachNodeIterator(this);
00202     m_detached = true;
00203 }
00204 
00205 
00206 void NodeIteratorImpl::notifyBeforeNodeRemoval(NodeImpl *removed)
00207 {
00208     // make sure the deleted node is with the root (but not the root itself)
00209     if (removed == m_root)
00210     return;
00211 
00212     NodeImpl *maybeRoot = removed->parentNode();
00213     while (maybeRoot && maybeRoot != m_root)
00214     maybeRoot = maybeRoot->parentNode();
00215     if (!maybeRoot)
00216     return;
00217 
00218     // did I get deleted, or one of my parents?
00219     NodeImpl *_tempDeleted = m_referenceNode;
00220     while( _tempDeleted && _tempDeleted != removed)
00221         _tempDeleted = _tempDeleted->parentNode();
00222 
00223     if( !_tempDeleted )  // someone that didn't consern me got deleted
00224         return;
00225 
00226     if( !m_inFront)
00227     {
00228         NodeImpl *_next = getNextNode(_tempDeleted);
00229         if( _next )
00230             m_referenceNode = _next;
00231         else
00232         {
00233         // deleted node was at end of list
00234             m_inFront = true;
00235             m_referenceNode = getPreviousNode(_tempDeleted);
00236         }
00237     }
00238     else {
00239     NodeImpl *_prev = getPreviousNode(_tempDeleted);
00240     if ( _prev )
00241         m_referenceNode = _prev;
00242     else
00243     {
00244         // deleted node was at start of list
00245         m_inFront = false;
00246         m_referenceNode = getNextNode(_tempDeleted);
00247     }
00248     }
00249 
00250 }
00251 
00252 short NodeIteratorImpl::isAccepted(NodeImpl *n)
00253 {
00254   // if XML is implemented we have to check expandEntityRerefences in this function
00255   if( ( ( 1 << n->nodeType()-1) & m_whatToShow) != 0 )
00256     {
00257         if(!m_filter.isNull())
00258             return m_filter.acceptNode(n);
00259         else
00260         return NodeFilter::FILTER_ACCEPT;
00261     }
00262     return NodeFilter::FILTER_SKIP;
00263 }
00264 
00265 // --------------------------------------------------------------
00266 
00267 
00268 NodeFilterImpl::NodeFilterImpl()
00269 {
00270     m_customNodeFilter = 0;
00271 }
00272 
00273 NodeFilterImpl::~NodeFilterImpl()
00274 {
00275     if (m_customNodeFilter)
00276     m_customNodeFilter->deref();
00277 }
00278 
00279 short NodeFilterImpl::acceptNode(const Node &n)
00280 {
00281     if (m_customNodeFilter)
00282     return m_customNodeFilter->acceptNode(n);
00283     else
00284     return NodeFilter::FILTER_ACCEPT;
00285 }
00286 
00287 void NodeFilterImpl::setCustomNodeFilter(CustomNodeFilter *custom)
00288 {
00289     m_customNodeFilter = custom;
00290     if (m_customNodeFilter)
00291     m_customNodeFilter->ref();
00292 }
00293 
00294 CustomNodeFilter *NodeFilterImpl::customNodeFilter()
00295 {
00296     return m_customNodeFilter;
00297 }
00298 
00299 // --------------------------------------------------------------
00300 
00301 TreeWalkerImpl::TreeWalkerImpl()
00302 {
00303     m_filter = 0;
00304     m_whatToShow = 0x0000FFFF;
00305     m_expandEntityReferences = true;
00306 }
00307 
00308 TreeWalkerImpl::TreeWalkerImpl(const TreeWalkerImpl &other)
00309     : khtml::Shared<TreeWalkerImpl>()
00310 {
00311     m_expandEntityReferences = other.m_expandEntityReferences;
00312     m_filter = other.m_filter;
00313     m_whatToShow = other.m_whatToShow;
00314     m_currentNode = other.m_currentNode;
00315     m_rootNode = other.m_rootNode;
00316 }
00317 
00318 TreeWalkerImpl::TreeWalkerImpl(Node n, NodeFilter *f)
00319 {
00320   m_currentNode = n;
00321   m_rootNode = n;
00322   m_whatToShow = 0x0000FFFF;
00323   m_filter = f;
00324 }
00325 
00326 TreeWalkerImpl::TreeWalkerImpl(Node n, long _whatToShow, NodeFilter *f)
00327 {
00328   m_currentNode = n;
00329   m_rootNode = n;
00330   m_whatToShow = _whatToShow;
00331   m_filter = f;
00332 }
00333 
00334 TreeWalkerImpl &TreeWalkerImpl::operator = (const TreeWalkerImpl &other)
00335 {
00336   m_expandEntityReferences = other.m_expandEntityReferences;
00337   m_filter = other.m_filter;
00338   m_whatToShow = other.m_whatToShow;
00339   m_currentNode = other.m_currentNode;
00340   return *this;
00341 }
00342 
00343 TreeWalkerImpl::~TreeWalkerImpl()
00344 {
00345     if(m_filter)
00346       {
00347         delete m_filter;
00348         m_filter = 0;
00349       }
00350 }
00351 
00352 
00353 
00354 
00355 
00356 Node TreeWalkerImpl::getRoot()
00357 {
00358     // ###
00359     return 0;
00360 }
00361 
00362 unsigned long TreeWalkerImpl::getWhatToShow()
00363 {
00364     // ###
00365     return 0;
00366 }
00367 
00368 NodeFilter TreeWalkerImpl::getFilter()
00369 {
00370     // ###
00371     return 0;
00372 }
00373 
00374 bool TreeWalkerImpl::getExpandEntityReferences()
00375 {
00376     // ###
00377     return 0;
00378 }
00379 
00380 Node TreeWalkerImpl::getCurrentNode()
00381 {
00382     return m_currentNode;
00383 }
00384 
00385 void TreeWalkerImpl::setWhatToShow(long _whatToShow)
00386 {
00387   // do some testing wether this is an accepted value
00388   m_whatToShow = _whatToShow;
00389 }
00390 
00391 void TreeWalkerImpl::setFilter(NodeFilter *_filter)
00392 {
00393   // ### allow setting of filter to 0?
00394   if(_filter)
00395     m_filter = _filter;
00396 }
00397 
00398 void TreeWalkerImpl::setExpandEntityReferences(bool value)
00399 {
00400   m_expandEntityReferences = value;
00401 }
00402 
00403 void TreeWalkerImpl::setCurrentNode( const Node n )
00404 {
00405     if( !n.isNull() )
00406     {
00407         m_rootNode = n;
00408         m_currentNode = n;
00409     }
00410 //     else
00411 //         throw( DOMException::NOT_SUPPORTED_ERR );
00412 }
00413 
00414 Node TreeWalkerImpl::parentNode(  )
00415 {
00416     Node n = getParentNode(m_currentNode);
00417     if( !n.isNull() )
00418         m_currentNode = n;
00419     return n;
00420 }
00421 
00422 
00423 Node TreeWalkerImpl::firstChild(  )
00424 {
00425     Node n = getFirstChild(m_currentNode);
00426     if( !n.isNull() )
00427         m_currentNode = n;
00428     return n;
00429 }
00430 
00431 
00432 Node TreeWalkerImpl::lastChild(  )
00433 {
00434     Node n = getLastChild(m_currentNode);
00435     if( !n.isNull() )
00436         m_currentNode = n;
00437     return n;
00438 }
00439 
00440 Node TreeWalkerImpl::previousSibling(  )
00441 {
00442     Node n = getPreviousSibling(m_currentNode);
00443     if( !n.isNull() )
00444         m_currentNode = n;
00445     return n;
00446 }
00447 
00448 Node TreeWalkerImpl::nextSibling(  )
00449 {
00450     Node n = getNextSibling(m_currentNode);
00451     if( !n.isNull() )
00452         m_currentNode = n;
00453     return n;
00454 }
00455 
00456 Node TreeWalkerImpl::previousNode(  )
00457 {
00458 /* 1. my previous sibling.lastchild
00459  * 2. my previous sibling
00460  * 3. my parent
00461  */
00462 
00463     Node n = getPreviousSibling(m_currentNode);
00464     if( n.isNull() )
00465     {
00466         n = getParentNode(m_currentNode);
00467         if( !n.isNull() )      //parent
00468         {
00469             m_currentNode = n;
00470             return m_currentNode;
00471         }
00472         else                  // parent failed.. no previous node
00473             return Node();
00474     }
00475 
00476     Node child = getLastChild(n);
00477     if( !child.isNull() )     // previous siblings last child
00478     {
00479         m_currentNode = child;
00480         return m_currentNode;
00481     }
00482     else                      // previous sibling
00483     {
00484         m_currentNode = n;
00485         return m_currentNode;
00486     }
00487     return Node();            // should never get here!
00488 }
00489 
00490 Node TreeWalkerImpl::nextNode(  )
00491 {
00492 /*  1. my first child
00493  *  2. my next sibling
00494  *  3. my parents sibling, or their parents sibling (loop)
00495  *  4. not found
00496  */
00497 
00498     Node n = getFirstChild(m_currentNode);
00499     if( !n.isNull()  ) // my first child
00500     {
00501         m_currentNode = n;
00502         return n;
00503     }
00504 
00505     n = getNextSibling(m_currentNode); // my next sibling
00506     if( !n.isNull() )
00507     {
00508         m_currentNode = n;
00509         return m_currentNode;
00510     }
00511     Node parent = getParentNode(m_currentNode);
00512     while( !parent.isNull() ) // parents sibling
00513     {
00514         n = getNextSibling(parent);
00515         if( !n.isNull() )
00516         {
00517           m_currentNode = n;
00518           return m_currentNode;
00519         }
00520         else
00521             parent = getParentNode(parent);
00522     }
00523     return Node();
00524 }
00525 
00526 short TreeWalkerImpl::isAccepted(Node n)
00527 {
00528     // if XML is implemented we have to check expandEntityRerefences in this function
00529   if( ( ( 1 << n.nodeType()-1 ) & m_whatToShow) != 0 )
00530     {
00531       if(m_filter)
00532         return m_filter->acceptNode(n);
00533       else
00534         return NodeFilter::FILTER_ACCEPT;
00535     }
00536   return NodeFilter::FILTER_SKIP;
00537 }
00538 
00539 Node TreeWalkerImpl::getParentNode(Node n)
00540 {
00541      short _result = NodeFilter::FILTER_ACCEPT;
00542 
00543     if( n == m_rootNode /*|| n.isNull()*/ )
00544       return Node();
00545 
00546     Node _tempCurrent = n.parentNode();
00547 
00548     if( _tempCurrent.isNull() )
00549       return Node();
00550 
00551     _result = isAccepted(_tempCurrent );
00552     if(_result == NodeFilter::FILTER_ACCEPT)
00553       return _tempCurrent;       // match found
00554 
00555     return getParentNode(_tempCurrent);
00556 }
00557 
00558 Node TreeWalkerImpl::getFirstChild(Node n)
00559 {
00560     short _result;
00561 
00562     if( n.isNull() || n.firstChild().isNull() )
00563         return Node();
00564     n = n.firstChild();
00565 
00566     _result = isAccepted(n);
00567 
00568     switch(_result)
00569     {
00570          case NodeFilter::FILTER_ACCEPT:
00571            return n;
00572            break;
00573         case NodeFilter::FILTER_SKIP:
00574           if( n.hasChildNodes() )
00575                 return getFirstChild(n);
00576             else
00577                 return getNextSibling(n);
00578             break;
00579 
00580         case NodeFilter::FILTER_REJECT:
00581             return getNextSibling(n);
00582             break;
00583     }
00584     return Node();      // should never get here!
00585 }
00586 
00587 Node TreeWalkerImpl::getLastChild(Node n)
00588 {
00589     short _result;
00590 
00591     if( n.isNull() || n.lastChild().isNull() )
00592         return Node();
00593     n = n.lastChild();
00594     _result = isAccepted(n);
00595     switch(_result)
00596     {
00597         case NodeFilter::FILTER_ACCEPT:
00598             return n;
00599             break;
00600 
00601         case NodeFilter::FILTER_SKIP:
00602             if( n.hasChildNodes() )
00603                 return getLastChild(n);
00604             else
00605                 return getPreviousSibling(n);
00606             break;
00607 
00608         case NodeFilter::FILTER_REJECT:
00609             return getPreviousSibling(n);
00610             break;
00611     }
00612     return Node();
00613 }
00614 
00615 Node TreeWalkerImpl::getPreviousSibling(Node n)
00616 {
00617     short _result;
00618     Node _tempCurrent;
00619 
00620     if( n.isNull() )
00621         return Node();
00622     //first the cases if we have a previousSibling
00623     _tempCurrent = n.previousSibling();
00624     if( !_tempCurrent.isNull() )
00625     {
00626         _result = isAccepted(_tempCurrent);
00627         switch(_result)
00628         {
00629             case NodeFilter::FILTER_ACCEPT:
00630                 return _tempCurrent;
00631                 break;
00632 
00633             case NodeFilter::FILTER_SKIP:
00634             {
00635                 Node nskip = getLastChild(_tempCurrent);
00636                 if( !nskip.isNull() )
00637                     return nskip;
00638                 return getPreviousSibling(_tempCurrent);
00639                 break;
00640             }
00641 
00642             case NodeFilter::FILTER_REJECT:
00643                 return getPreviousSibling(_tempCurrent);
00644                 break;
00645         }
00646     }
00647     // now the case if we don't have previous sibling
00648     else
00649     {
00650         _tempCurrent = _tempCurrent.parentNode();
00651         if(_tempCurrent.isNull() || _tempCurrent == m_rootNode)
00652             return Node();
00653         _result = isAccepted(_tempCurrent);
00654         if(_result == NodeFilter::FILTER_SKIP)
00655             return getPreviousSibling(_tempCurrent);
00656 
00657         return Node();
00658 
00659     }
00660     return Node();  // should never get here!
00661 }
00662 
00663 Node TreeWalkerImpl::getNextSibling(Node n)
00664 {
00665     Node _tempCurrent;
00666     short _result;
00667 
00668     if( n.isNull() || _tempCurrent == m_rootNode)
00669         return Node();
00670 
00671     _tempCurrent = n.nextSibling();
00672     if( !_tempCurrent.isNull() )
00673     {
00674         _result = isAccepted(_tempCurrent);
00675         switch(_result)
00676         {
00677             case NodeFilter::FILTER_ACCEPT:
00678                 return _tempCurrent;
00679                 break;
00680 
00681             case NodeFilter::FILTER_SKIP:
00682             {
00683                 Node nskip = getFirstChild(_tempCurrent);
00684                 if( !nskip.isNull() )
00685                     return nskip;
00686                 return getNextSibling(_tempCurrent);
00687                 break;
00688             }
00689 
00690             case NodeFilter::FILTER_REJECT:
00691                 return getNextSibling(_tempCurrent);
00692                 break;
00693         }
00694     }
00695     else
00696     {
00697         _tempCurrent = _tempCurrent.parentNode();
00698         if(_tempCurrent.isNull() || _tempCurrent == m_rootNode)
00699             return Node();
00700         _result = isAccepted(_tempCurrent);
00701         if(_result == NodeFilter::FILTER_SKIP)
00702             return getNextSibling(_tempCurrent);
00703 
00704         return Node();
00705     }
00706     return Node();
00707 }
00708 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:32 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001