LCOV - code coverage report
Current view: top level - editor/txtsvc - nsFilteredContentIterator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 195 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/mozalloc.h"
       7             : #include "nsComponentManagerUtils.h"
       8             : #include "nsContentUtils.h"
       9             : #include "nsDebug.h"
      10             : #include "nsError.h"
      11             : #include "nsFilteredContentIterator.h"
      12             : #include "nsIAtom.h"
      13             : #include "nsIContent.h"
      14             : #include "nsIContentIterator.h"
      15             : #include "nsIDOMNode.h"
      16             : #include "nsINode.h"
      17             : #include "nsISupportsBase.h"
      18             : #include "nsISupportsUtils.h"
      19             : #include "nsITextServicesFilter.h"
      20             : #include "nsRange.h"
      21             : 
      22             : //------------------------------------------------------------
      23           0 : nsFilteredContentIterator::nsFilteredContentIterator(nsITextServicesFilter* aFilter) :
      24             :   mFilter(aFilter),
      25             :   mDidSkip(false),
      26             :   mIsOutOfRange(false),
      27           0 :   mDirection(eDirNotSet)
      28             : {
      29           0 :   mIterator = do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
      30           0 :   mPreIterator = do_CreateInstance("@mozilla.org/content/pre-content-iterator;1");
      31           0 : }
      32             : 
      33             : //------------------------------------------------------------
      34           0 : nsFilteredContentIterator::~nsFilteredContentIterator()
      35             : {
      36           0 : }
      37             : 
      38             : //------------------------------------------------------------
      39           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFilteredContentIterator)
      40           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFilteredContentIterator)
      41             : 
      42           0 : NS_INTERFACE_MAP_BEGIN(nsFilteredContentIterator)
      43           0 :   NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
      44           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
      45           0 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsFilteredContentIterator)
      46           0 : NS_INTERFACE_MAP_END
      47             : 
      48           0 : NS_IMPL_CYCLE_COLLECTION(nsFilteredContentIterator,
      49             :                          mCurrentIterator,
      50             :                          mIterator,
      51             :                          mPreIterator,
      52             :                          mFilter,
      53             :                          mRange)
      54             : 
      55             : //------------------------------------------------------------
      56             : nsresult
      57           0 : nsFilteredContentIterator::Init(nsINode* aRoot)
      58             : {
      59           0 :   NS_ENSURE_ARG_POINTER(aRoot);
      60           0 :   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
      61           0 :   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
      62           0 :   mIsOutOfRange    = false;
      63           0 :   mDirection       = eForward;
      64           0 :   mCurrentIterator = mPreIterator;
      65             : 
      66           0 :   mRange = new nsRange(aRoot);
      67           0 :   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aRoot));
      68           0 :   if (domNode) {
      69           0 :     mRange->SelectNode(domNode);
      70             :   }
      71             : 
      72           0 :   nsresult rv = mPreIterator->Init(mRange);
      73           0 :   NS_ENSURE_SUCCESS(rv, rv);
      74           0 :   return mIterator->Init(mRange);
      75             : }
      76             : 
      77             : //------------------------------------------------------------
      78             : nsresult
      79           0 : nsFilteredContentIterator::Init(nsIDOMRange* aRange)
      80             : {
      81           0 :   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
      82           0 :   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
      83           0 :   NS_ENSURE_ARG_POINTER(aRange);
      84           0 :   mIsOutOfRange    = false;
      85           0 :   mDirection       = eForward;
      86           0 :   mCurrentIterator = mPreIterator;
      87             : 
      88           0 :   mRange = static_cast<nsRange*>(aRange)->CloneRange();
      89             : 
      90           0 :   nsresult rv = mPreIterator->Init(mRange);
      91           0 :   NS_ENSURE_SUCCESS(rv, rv);
      92           0 :   return mIterator->Init(mRange);
      93             : }
      94             : 
      95             : //------------------------------------------------------------
      96             : nsresult
      97           0 : nsFilteredContentIterator::SwitchDirections(bool aChangeToForward)
      98             : {
      99           0 :   nsINode *node = mCurrentIterator->GetCurrentNode();
     100             : 
     101           0 :   if (aChangeToForward) {
     102           0 :     mCurrentIterator = mPreIterator;
     103           0 :     mDirection       = eForward;
     104             :   } else {
     105           0 :     mCurrentIterator = mIterator;
     106           0 :     mDirection       = eBackward;
     107             :   }
     108             : 
     109           0 :   if (node) {
     110           0 :     nsresult rv = mCurrentIterator->PositionAt(node);
     111           0 :     if (NS_FAILED(rv)) {
     112           0 :       mIsOutOfRange = true;
     113           0 :       return rv;
     114             :     }
     115             :   }
     116           0 :   return NS_OK;
     117             : }
     118             : 
     119             : //------------------------------------------------------------
     120             : void
     121           0 : nsFilteredContentIterator::First()
     122             : {
     123           0 :   if (!mCurrentIterator) {
     124           0 :     NS_ERROR("Missing iterator!");
     125             : 
     126           0 :     return;
     127             :   }
     128             : 
     129             :   // If we are switching directions then
     130             :   // we need to switch how we process the nodes
     131           0 :   if (mDirection != eForward) {
     132           0 :     mCurrentIterator = mPreIterator;
     133           0 :     mDirection       = eForward;
     134           0 :     mIsOutOfRange    = false;
     135             :   }
     136             : 
     137           0 :   mCurrentIterator->First();
     138             : 
     139           0 :   if (mCurrentIterator->IsDone()) {
     140           0 :     return;
     141             :   }
     142             : 
     143           0 :   nsINode *currentNode = mCurrentIterator->GetCurrentNode();
     144           0 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
     145             : 
     146             :   bool didCross;
     147           0 :   CheckAdvNode(node, didCross, eForward);
     148             : }
     149             : 
     150             : //------------------------------------------------------------
     151             : void
     152           0 : nsFilteredContentIterator::Last()
     153             : {
     154           0 :   if (!mCurrentIterator) {
     155           0 :     NS_ERROR("Missing iterator!");
     156             : 
     157           0 :     return;
     158             :   }
     159             : 
     160             :   // If we are switching directions then
     161             :   // we need to switch how we process the nodes
     162           0 :   if (mDirection != eBackward) {
     163           0 :     mCurrentIterator = mIterator;
     164           0 :     mDirection       = eBackward;
     165           0 :     mIsOutOfRange    = false;
     166             :   }
     167             : 
     168           0 :   mCurrentIterator->Last();
     169             : 
     170           0 :   if (mCurrentIterator->IsDone()) {
     171           0 :     return;
     172             :   }
     173             : 
     174           0 :   nsINode *currentNode = mCurrentIterator->GetCurrentNode();
     175           0 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
     176             : 
     177             :   bool didCross;
     178           0 :   CheckAdvNode(node, didCross, eBackward);
     179             : }
     180             : 
     181             : ///////////////////////////////////////////////////////////////////////////
     182             : // ContentToParentOffset: returns the content node's parent and offset.
     183             : //
     184             : static void
     185           0 : ContentToParentOffset(nsIContent *aContent, nsIDOMNode **aParent,
     186             :                       int32_t *aOffset)
     187             : {
     188           0 :   if (!aParent || !aOffset)
     189           0 :     return;
     190             : 
     191           0 :   *aParent = nullptr;
     192           0 :   *aOffset  = 0;
     193             : 
     194           0 :   if (!aContent)
     195           0 :     return;
     196             : 
     197           0 :   nsIContent* parent = aContent->GetParent();
     198             : 
     199           0 :   if (!parent)
     200           0 :     return;
     201             : 
     202           0 :   *aOffset = parent->IndexOf(aContent);
     203             : 
     204           0 :   CallQueryInterface(parent, aParent);
     205             : }
     206             : 
     207             : ///////////////////////////////////////////////////////////////////////////
     208             : // ContentIsInTraversalRange: returns true if content is visited during
     209             : // the traversal of the range in the specified mode.
     210             : //
     211             : static bool
     212           0 : ContentIsInTraversalRange(nsIContent *aContent,   bool aIsPreMode,
     213             :                           nsIDOMNode *aStartContainer, int32_t aStartOffset,
     214             :                           nsIDOMNode *aEndContainer, int32_t aEndOffset)
     215             : {
     216           0 :   NS_ENSURE_TRUE(aStartContainer && aEndContainer && aContent, false);
     217             : 
     218           0 :   nsCOMPtr<nsIDOMNode> parentNode;
     219           0 :   int32_t indx = 0;
     220             : 
     221           0 :   ContentToParentOffset(aContent, getter_AddRefs(parentNode), &indx);
     222             : 
     223           0 :   NS_ENSURE_TRUE(parentNode, false);
     224             : 
     225           0 :   if (!aIsPreMode)
     226           0 :     ++indx;
     227             : 
     228             :   int32_t startRes =
     229           0 :     nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
     230           0 :                                   parentNode, indx);
     231           0 :   int32_t endRes = nsContentUtils::ComparePoints(aEndContainer, aEndOffset,
     232           0 :                                                  parentNode, indx);
     233           0 :   return (startRes <= 0) && (endRes >= 0);
     234             : }
     235             : 
     236             : static bool
     237           0 : ContentIsInTraversalRange(nsRange* aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
     238             : {
     239           0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
     240           0 :   NS_ENSURE_TRUE(content && aRange, false);
     241             : 
     242           0 :   nsCOMPtr<nsIDOMNode> sNode;
     243           0 :   nsCOMPtr<nsIDOMNode> eNode;
     244             :   int32_t sOffset;
     245             :   int32_t eOffset;
     246           0 :   aRange->GetStartContainer(getter_AddRefs(sNode));
     247           0 :   aRange->GetStartOffset(&sOffset);
     248           0 :   aRange->GetEndContainer(getter_AddRefs(eNode));
     249           0 :   aRange->GetEndOffset(&eOffset);
     250           0 :   return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
     251             : }
     252             : 
     253             : //------------------------------------------------------------
     254             : // Helper function to advance to the next or previous node
     255             : nsresult
     256           0 : nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
     257             : {
     258           0 :   nsCOMPtr<nsIDOMNode> nextNode;
     259           0 :   if (aDir == eForward) {
     260           0 :     aNode->GetNextSibling(getter_AddRefs(nextNode));
     261             :   } else {
     262           0 :     aNode->GetPreviousSibling(getter_AddRefs(nextNode));
     263             :   }
     264             : 
     265           0 :   if (nextNode) {
     266             :     // If we got here, that means we found the nxt/prv node
     267             :     // make sure it is in our DOMRange
     268           0 :     bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
     269           0 :     if (intersects) {
     270           0 :       aNewNode = nextNode;
     271           0 :       NS_ADDREF(aNewNode);
     272           0 :       return NS_OK;
     273             :     }
     274             :   } else {
     275             :     // The next node was null so we need to walk up the parent(s)
     276           0 :     nsCOMPtr<nsIDOMNode> parent;
     277           0 :     aNode->GetParentNode(getter_AddRefs(parent));
     278           0 :     NS_ASSERTION(parent, "parent can't be nullptr");
     279             : 
     280             :     // Make sure the parent is in the DOMRange before going further
     281           0 :     bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
     282           0 :     if (intersects) {
     283             :       // Now find the nxt/prv node after/before this node
     284           0 :       nsresult rv = AdvanceNode(parent, aNewNode, aDir);
     285           0 :       if (NS_SUCCEEDED(rv) && aNewNode) {
     286           0 :         return NS_OK;
     287             :       }
     288             :     }
     289             :   }
     290             : 
     291             :   // if we get here it pretty much means
     292             :   // we went out of the DOM Range
     293           0 :   mIsOutOfRange = true;
     294             : 
     295           0 :   return NS_ERROR_FAILURE;
     296             : }
     297             : 
     298             : //------------------------------------------------------------
     299             : // Helper function to see if the next/prev node should be skipped
     300             : void
     301           0 : nsFilteredContentIterator::CheckAdvNode(nsIDOMNode* aNode, bool& aDidSkip, eDirectionType aDir)
     302             : {
     303           0 :   aDidSkip      = false;
     304           0 :   mIsOutOfRange = false;
     305             : 
     306           0 :   if (aNode && mFilter) {
     307           0 :     nsCOMPtr<nsIDOMNode> currentNode = aNode;
     308             :     bool skipIt;
     309             :     while (1) {
     310           0 :       nsresult rv = mFilter->Skip(aNode, &skipIt);
     311           0 :       if (NS_SUCCEEDED(rv) && skipIt) {
     312           0 :         aDidSkip = true;
     313             :         // Get the next/prev node and then
     314             :         // see if we should skip that
     315           0 :         nsCOMPtr<nsIDOMNode> advNode;
     316           0 :         rv = AdvanceNode(aNode, *getter_AddRefs(advNode), aDir);
     317           0 :         if (NS_SUCCEEDED(rv) && advNode) {
     318           0 :           aNode = advNode;
     319             :         } else {
     320           0 :           return; // fell out of range
     321             :         }
     322             :       } else {
     323           0 :         if (aNode != currentNode) {
     324           0 :           nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
     325           0 :           mCurrentIterator->PositionAt(content);
     326             :         }
     327           0 :         return; // found something
     328             :       }
     329           0 :     }
     330             :   }
     331             : }
     332             : 
     333             : void
     334           0 : nsFilteredContentIterator::Next()
     335             : {
     336           0 :   if (mIsOutOfRange || !mCurrentIterator) {
     337           0 :     NS_ASSERTION(mCurrentIterator, "Missing iterator!");
     338             : 
     339           0 :     return;
     340             :   }
     341             : 
     342             :   // If we are switching directions then
     343             :   // we need to switch how we process the nodes
     344           0 :   if (mDirection != eForward) {
     345           0 :     nsresult rv = SwitchDirections(true);
     346           0 :     if (NS_FAILED(rv)) {
     347           0 :       return;
     348             :     }
     349             :   }
     350             : 
     351           0 :   mCurrentIterator->Next();
     352             : 
     353           0 :   if (mCurrentIterator->IsDone()) {
     354           0 :     return;
     355             :   }
     356             : 
     357             :   // If we can't get the current node then
     358             :   // don't check to see if we can skip it
     359           0 :   nsINode *currentNode = mCurrentIterator->GetCurrentNode();
     360             : 
     361           0 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
     362           0 :   CheckAdvNode(node, mDidSkip, eForward);
     363             : }
     364             : 
     365             : void
     366           0 : nsFilteredContentIterator::Prev()
     367             : {
     368           0 :   if (mIsOutOfRange || !mCurrentIterator) {
     369           0 :     NS_ASSERTION(mCurrentIterator, "Missing iterator!");
     370             : 
     371           0 :     return;
     372             :   }
     373             : 
     374             :   // If we are switching directions then
     375             :   // we need to switch how we process the nodes
     376           0 :   if (mDirection != eBackward) {
     377           0 :     nsresult rv = SwitchDirections(false);
     378           0 :     if (NS_FAILED(rv)) {
     379           0 :       return;
     380             :     }
     381             :   }
     382             : 
     383           0 :   mCurrentIterator->Prev();
     384             : 
     385           0 :   if (mCurrentIterator->IsDone()) {
     386           0 :     return;
     387             :   }
     388             : 
     389             :   // If we can't get the current node then
     390             :   // don't check to see if we can skip it
     391           0 :   nsINode *currentNode = mCurrentIterator->GetCurrentNode();
     392             : 
     393           0 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
     394           0 :   CheckAdvNode(node, mDidSkip, eBackward);
     395             : }
     396             : 
     397             : nsINode *
     398           0 : nsFilteredContentIterator::GetCurrentNode()
     399             : {
     400           0 :   if (mIsOutOfRange || !mCurrentIterator) {
     401           0 :     return nullptr;
     402             :   }
     403             : 
     404           0 :   return mCurrentIterator->GetCurrentNode();
     405             : }
     406             : 
     407             : bool
     408           0 : nsFilteredContentIterator::IsDone()
     409             : {
     410           0 :   if (mIsOutOfRange || !mCurrentIterator) {
     411           0 :     return true;
     412             :   }
     413             : 
     414           0 :   return mCurrentIterator->IsDone();
     415             : }
     416             : 
     417             : nsresult
     418           0 : nsFilteredContentIterator::PositionAt(nsINode* aCurNode)
     419             : {
     420           0 :   NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
     421           0 :   mIsOutOfRange = false;
     422           0 :   return mCurrentIterator->PositionAt(aCurNode);
     423             : }

Generated by: LCOV version 1.13