// Helper function to advance to the next or previous node
nsresult FilteredContentIterator::AdvanceNode(nsINode* aNode,
                                              nsINode*& aNewNode,
                                              eDirectionType aDir) {
  nsCOMPtr<nsIContent> nextNode;
  if (aDir == eForward) {
    nextNode = aNode->GetNextSibling();
  } else {
    nextNode = aNode->GetPreviousSibling();
  }

  if (nextNode) {
    // If we got here, that means we found the nxt/prv node
    // make sure it is in our DOMRange
    bool intersects =
        ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
    if (intersects) {
      aNewNode = nextNode;
      NS_ADDREF(aNewNode);
      return NS_OK;
    }
  } else {
    // The next node was null so we need to walk up the parent(s)
    nsCOMPtr<nsINode> parent = aNode->GetParentNode();
    NS_ASSERTION(parent, "parent can't be nullptr");

    // Make sure the parent is in the DOMRange before going further
    // XXXbz why are we passing nextNode, not the parent???  If this gets fixed,
    // then ContentIsInTraversalRange can stop null-checking its second arg.
    bool intersects =
        ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
    if (intersects) {
      // Now find the nxt/prv node after/before this node
      nsresult rv = AdvanceNode(parent, aNewNode, aDir);
      if (NS_SUCCEEDED(rv) && aNewNode) {
        return NS_OK;
      }
    }
  }

  // if we get here it pretty much means
  // we went out of the DOM Range
  mIsOutOfRange = true;

  return NS_ERROR_FAILURE;
}
//------------------------------------------------------------
// Helper function to advance to the next or previous node
nsresult 
nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
{
  nsCOMPtr<nsIDOMNode> nextNode;
  if (aDir == eForward) {
    aNode->GetNextSibling(getter_AddRefs(nextNode));
  } else {
    aNode->GetPreviousSibling(getter_AddRefs(nextNode));
  }

  if (nextNode) {
    // If we got here, that means we found the nxt/prv node
    // make sure it is in our DOMRange
    bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
    if (intersects) {
      aNewNode = nextNode;
      NS_ADDREF(aNewNode);
      return NS_OK;
    }
  } else {
    // The next node was null so we need to walk up the parent(s)
    nsCOMPtr<nsIDOMNode> parent;
    aNode->GetParentNode(getter_AddRefs(parent));
    NS_ASSERTION(parent, "parent can't be NULL");

    // Make sure the parent is in the DOMRange before going further
    bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
    if (intersects) {
      // Now find the nxt/prv node after/before this node
      nsresult rv = AdvanceNode(parent, aNewNode, aDir);
      if (NS_SUCCEEDED(rv) && aNewNode) {
        return NS_OK;
      }
    }
  }

  // if we get here it pretty much means 
  // we went out of the DOM Range
  mIsOutOfRange = true;

  return NS_ERROR_FAILURE;
}
static bool ContentIsInTraversalRange(nsRange* aRange, nsIContent* aNextContent,
                                      bool aIsPreMode) {
  // XXXbz we have a caller below (in AdvanceNode) who passes null for
  // aNextContent!
  NS_ENSURE_TRUE(aNextContent && aRange, false);

  return ContentIsInTraversalRange(
      aNextContent, aIsPreMode, aRange->GetStartContainer(),
      static_cast<int32_t>(aRange->StartOffset()), aRange->GetEndContainer(),
      static_cast<int32_t>(aRange->EndOffset()));
}
static bool
ContentIsInTraversalRange(nsIDOMRange *aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
{
  nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
  NS_ENSURE_TRUE(content && aRange, false);

  nsCOMPtr<nsIDOMNode> sNode;
  nsCOMPtr<nsIDOMNode> eNode;
  PRInt32 sOffset;
  PRInt32 eOffset;
  aRange->GetStartContainer(getter_AddRefs(sNode));
  aRange->GetStartOffset(&sOffset);
  aRange->GetEndContainer(getter_AddRefs(eNode));
  aRange->GetEndOffset(&eOffset);
  return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
}
static PRBool
ContentIsInTraversalRange(nsIDOMNSRange *aRange, nsIDOMNode* aNextNode, PRBool aIsPreMode)
{
  nsCOMPtr<nsIContent>  content(do_QueryInterface(aNextNode));
  nsCOMPtr<nsIDOMRange> range(do_QueryInterface(aRange));
  if (!content || !range)
    return PR_FALSE;



  nsCOMPtr<nsIDOMNode> sNode;
  nsCOMPtr<nsIDOMNode> eNode;
  PRInt32 sOffset;
  PRInt32 eOffset;
  range->GetStartContainer(getter_AddRefs(sNode));
  range->GetStartOffset(&sOffset);
  range->GetEndContainer(getter_AddRefs(eNode));
  range->GetEndOffset(&eOffset);
  return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
}