nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                                nsINode* aNode,
                                                PRInt32 aNodeOffset,
                                                PRUint32* aNativeOffset)
{
  NS_ASSERTION(aNativeOffset, "param is invalid");

  nsCOMPtr<nsIRange> prev = new nsRange();
  NS_ENSURE_TRUE(prev, NS_ERROR_OUT_OF_MEMORY);
  nsCOMPtr<nsIDOMRange> domPrev(do_QueryInterface(prev));
  NS_ASSERTION(domPrev, "nsRange doesn't have nsIDOMRange??");
  nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
  domPrev->SetStart(rootDOMNode, 0);

  nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
  NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
  domPrev->SetEnd(startDOMNode, aNodeOffset);

  nsAutoString prevStr;
  nsresult rv = GenerateFlatTextContent(prev, prevStr);
  NS_ENSURE_SUCCESS(rv, rv);
  *aNativeOffset = prevStr.Length();
  return NS_OK;
}
nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                                nsINode* aNode,
                                                PRInt32 aNodeOffset,
                                                PRUint32* aNativeOffset)
{
  NS_ASSERTION(aNativeOffset, "param is invalid");

  nsCOMPtr<nsIRange> prev = new nsRange();
  NS_ENSURE_TRUE(prev, NS_ERROR_OUT_OF_MEMORY);
  nsCOMPtr<nsIDOMRange> domPrev(do_QueryInterface(prev));
  NS_ASSERTION(domPrev, "nsRange doesn't have nsIDOMRange??");
  nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
  domPrev->SetStart(rootDOMNode, 0);

  nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
  NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
  domPrev->SetEnd(startDOMNode, aNodeOffset);

  nsCOMPtr<nsIContentIterator> iter;
  nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
  iter->Init(domPrev);

  nsCOMPtr<nsINode> startNode = do_QueryInterface(startDOMNode);
  nsINode* endNode = aNode;

  *aNativeOffset = 0;
  for (; !iter->IsDone(); iter->Next()) {
    nsINode* node = iter->GetCurrentNode();
    if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
      continue;
    nsIContent* content = static_cast<nsIContent*>(node);

    if (node->IsNodeOfType(nsINode::eTEXT)) {
      // Note: our range always starts from offset 0
      if (node == endNode)
        *aNativeOffset += GetNativeTextLength(content, aNodeOffset);
      else
        *aNativeOffset += GetNativeTextLength(content);
    } else if (IsContentBR(content)) {
#if defined(XP_WIN)
      // On Windows, the length of the newline is 2.
      *aNativeOffset += 2;
#else
      // On other platforms, the length of the newline is 1.
      *aNativeOffset += 1;
#endif
    }
  }
  return NS_OK;
}
nsresult
nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
                                                nsINode* aNode,
                                                PRInt32 aNodeOffset,
                                                PRUint32* aNativeOffset)
{
  NS_ASSERTION(aNativeOffset, "param is invalid");

  nsRefPtr<nsRange> prev = new nsRange();
  nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
  prev->SetStart(rootDOMNode, 0);

  nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
  NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
  prev->SetEnd(startDOMNode, aNodeOffset);

  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
  iter->Init(prev);

  nsCOMPtr<nsINode> startNode = do_QueryInterface(startDOMNode);
  nsINode* endNode = aNode;

  *aNativeOffset = 0;
  for (; !iter->IsDone(); iter->Next()) {
    nsINode* node = iter->GetCurrentNode();
    if (!node)
      break;
    if (!node->IsNodeOfType(nsINode::eCONTENT))
      continue;
    nsIContent* content = static_cast<nsIContent*>(node);

    if (node->IsNodeOfType(nsINode::eTEXT)) {
      // Note: our range always starts from offset 0
      if (node == endNode)
        *aNativeOffset += GetNativeTextLength(content, aNodeOffset);
      else
        *aNativeOffset += GetNativeTextLength(content);
    } else if (IsContentBR(content)) {
#if defined(XP_WIN)
      // On Windows, the length of the newline is 2.
      *aNativeOffset += 2;
#else
      // On other platforms, the length of the newline is 1.
      *aNativeOffset += 1;
#endif
    }
  }
  return NS_OK;
}