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
nsQueryContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
{
    nsresult rv = Init(aEvent);
    if (NS_FAILED(rv))
        return rv;

    NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
                 "The reply string must be empty");

    rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &aEvent->mReply.mOffset);
    NS_ENSURE_SUCCESS(rv, rv);

    PRBool isCollapsed;
    rv = mSelection->GetIsCollapsed(&isCollapsed);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!isCollapsed) {
        nsCOMPtr<nsIDOMRange> domRange;
        rv = mSelection->GetRangeAt(0, getter_AddRefs(domRange));
        NS_ENSURE_SUCCESS(rv, rv);
        NS_ASSERTION(domRange, "GetRangeAt succeeded, but the result is null");

        nsCOMPtr<nsIRange> range(do_QueryInterface(domRange));
        NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
        rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
        NS_ENSURE_SUCCESS(rv, rv);
    }

    aEvent->mSucceeded = PR_TRUE;
    return NS_OK;
}
nsresult
nsContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
{
  nsresult rv = Init(aEvent);
  if (NS_FAILED(rv))
    return rv;

  NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
               "The reply string must be empty");

  rv = GetFlatTextOffsetOfRange(mRootContent,
                                mFirstSelectedRange, &aEvent->mReply.mOffset);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIDOMNode> anchorDomNode, focusDomNode;
  rv = mSelection->GetAnchorNode(getter_AddRefs(anchorDomNode));
  NS_ENSURE_TRUE(anchorDomNode, NS_ERROR_FAILURE);
  rv = mSelection->GetFocusNode(getter_AddRefs(focusDomNode));
  NS_ENSURE_TRUE(focusDomNode, NS_ERROR_FAILURE);

  PRInt32 anchorOffset, focusOffset;
  rv = mSelection->GetAnchorOffset(&anchorOffset);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mSelection->GetFocusOffset(&focusOffset);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsINode> anchorNode(do_QueryInterface(anchorDomNode));
  nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDomNode));
  NS_ENSURE_TRUE(anchorNode && focusNode, NS_ERROR_UNEXPECTED);

  PRInt16 compare = nsContentUtils::ComparePoints(anchorNode, anchorOffset,
                                                  focusNode, focusOffset);
  aEvent->mReply.mReversed = compare > 0;

  if (compare) {
    nsCOMPtr<nsIRange> range = mFirstSelectedRange;
    rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  aEvent->mSucceeded = PR_TRUE;
  return NS_OK;
}
nsresult
nsContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent)
{
  nsresult rv = Init(aEvent);
  if (NS_FAILED(rv))
    return rv;

  NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
               "The reply string must be empty");

  nsRefPtr<nsRange> range = new nsRange();
  rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
                                  aEvent->mInput.mLength, false);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
  NS_ENSURE_SUCCESS(rv, rv);

  aEvent->mSucceeded = true;

  return NS_OK;
}