mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Don't try to use ranges to represent chunks of the flattened tree, becauseranges can't have endpoints that are anonymous wrt the other endpoint. Bug374873, r+sr=rbs
This commit is contained in:
parent
ff22fdf79c
commit
f792615997
@ -106,12 +106,9 @@ class nsFindContentIterator : public nsIContentIterator
|
||||
{
|
||||
public:
|
||||
nsFindContentIterator(PRBool aFindBackward)
|
||||
: mOuterIterator(nsnull)
|
||||
, mInnerIterator(nsnull)
|
||||
, mRange(nsnull)
|
||||
, mStartOuterNode(nsnull)
|
||||
, mEndOuterNode(nsnull)
|
||||
, mFindBackward(aFindBackward)
|
||||
: mStartOffset(0),
|
||||
mEndOffset(0),
|
||||
mFindBackward(aFindBackward)
|
||||
{
|
||||
}
|
||||
|
||||
@ -128,7 +125,14 @@ public:
|
||||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
virtual nsresult Init(nsIDOMRange* aRange);
|
||||
virtual nsresult Init(nsIDOMRange* aRange)
|
||||
{
|
||||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
// Not a range because one of the endpoints may be anonymous.
|
||||
nsresult Init(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset);
|
||||
virtual void First();
|
||||
virtual void Last();
|
||||
virtual void Next();
|
||||
@ -140,7 +144,13 @@ public:
|
||||
private:
|
||||
nsCOMPtr<nsIContentIterator> mOuterIterator;
|
||||
nsCOMPtr<nsIContentIterator> mInnerIterator;
|
||||
nsCOMPtr<nsIDOMRange> mRange;
|
||||
// Can't use a range here, since we want to represent part of the
|
||||
// flattened tree, including native anonymous content.
|
||||
nsCOMPtr<nsIDOMNode> mStartNode;
|
||||
PRInt32 mStartOffset;
|
||||
nsCOMPtr<nsIDOMNode> mEndNode;
|
||||
PRInt32 mEndOffset;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> mStartOuterNode;
|
||||
nsCOMPtr<nsIDOMNode> mEndOuterNode;
|
||||
PRBool mFindBackward;
|
||||
@ -153,7 +163,8 @@ private:
|
||||
NS_IMPL_ISUPPORTS1(nsFindContentIterator, nsIContentIterator)
|
||||
|
||||
nsresult
|
||||
nsFindContentIterator::Init(nsIDOMRange* aRange)
|
||||
nsFindContentIterator::Init(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset)
|
||||
{
|
||||
if (!mOuterIterator) {
|
||||
if (mFindBackward) {
|
||||
@ -171,8 +182,13 @@ nsFindContentIterator::Init(nsIDOMRange* aRange)
|
||||
NS_ENSURE_ARG_POINTER(mOuterIterator);
|
||||
}
|
||||
|
||||
// mRange is the search range that we will examine
|
||||
return aRange->CloneRange(getter_AddRefs(mRange));
|
||||
// Set up the search "range" that we will examine
|
||||
mStartNode = aStartNode;
|
||||
mStartOffset = aStartOffset;
|
||||
mEndNode = aEndNode;
|
||||
mEndOffset = aEndOffset;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -263,31 +279,37 @@ nsFindContentIterator::Reset()
|
||||
// initialized with a selection inside a <textarea> or a text <input>.
|
||||
|
||||
// see if the start node is an anonymous text node inside a text control
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
mRange->GetStartContainer(getter_AddRefs(startNode));
|
||||
nsCOMPtr<nsIContent> startContent(do_QueryInterface(startNode));
|
||||
nsCOMPtr<nsIContent> startContent(do_QueryInterface(mStartNode));
|
||||
for ( ; startContent; startContent = startContent->GetParent()) {
|
||||
if (!startContent->IsNativeAnonymous()) {
|
||||
if (!startContent->IsNativeAnonymous() &&
|
||||
(!startContent->GetBindingParent() ||
|
||||
!startContent->GetBindingParent()->IsNativeAnonymous())) {
|
||||
mStartOuterNode = do_QueryInterface(startContent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// see if the end node is an anonymous text node inside a text control
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
mRange->GetEndContainer(getter_AddRefs(endNode));
|
||||
nsCOMPtr<nsIContent> endContent(do_QueryInterface(endNode));
|
||||
nsCOMPtr<nsIContent> endContent(do_QueryInterface(mEndNode));
|
||||
for ( ; endContent; endContent = endContent->GetParent()) {
|
||||
if (!endContent->IsNativeAnonymous()) {
|
||||
if (!endContent->IsNativeAnonymous() &&
|
||||
(!endContent->GetBindingParent() ||
|
||||
!endContent->GetBindingParent()->IsNativeAnonymous())) {
|
||||
mEndOuterNode = do_QueryInterface(endContent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mOuterIterator->Init(mRange);
|
||||
// Note: OK to just set up the outer iterator here; if our range has an
|
||||
// anonymous endpoint we'll end up setting up an inner iterator, and
|
||||
// reset the outer one in the process.
|
||||
nsCOMPtr<nsIDOMRange> range (do_CreateInstance(kRangeCID));
|
||||
range->SetStart(mStartNode, mStartOffset);
|
||||
range->SetEnd(mEndNode, mEndOffset);
|
||||
mOuterIterator->Init(range);
|
||||
|
||||
if (!mFindBackward) {
|
||||
if (mStartOuterNode != startNode) {
|
||||
if (mStartOuterNode != mStartNode) {
|
||||
// the start node was an anonymous text node
|
||||
SetupInnerIterator(startContent);
|
||||
if (mInnerIterator)
|
||||
@ -296,7 +318,7 @@ nsFindContentIterator::Reset()
|
||||
mOuterIterator->First();
|
||||
}
|
||||
else {
|
||||
if (mEndOuterNode != endNode) {
|
||||
if (mEndOuterNode != mEndNode) {
|
||||
// the end node was an anonymous text node
|
||||
SetupInnerIterator(endContent);
|
||||
if (mInnerIterator)
|
||||
@ -378,53 +400,57 @@ nsFindContentIterator::SetupInnerIterator(nsIContent* aContent)
|
||||
editor->GetRootElement(getter_AddRefs(rootElement));
|
||||
nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElement));
|
||||
|
||||
nsCOMPtr<nsIDOMRange> innerRange(do_CreateInstance(kRangeCID));
|
||||
nsCOMPtr<nsIDOMRange> outerRange(do_CreateInstance(kRangeCID));
|
||||
if (!innerRange || !outerRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
// now create the inner-iterator
|
||||
mInnerIterator = do_CreateInstance(kCPreContentIteratorCID);
|
||||
|
||||
if (mInnerIterator) {
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(rootContent));
|
||||
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID));
|
||||
range->SelectNodeContents(node);
|
||||
innerRange->SelectNodeContents(node);
|
||||
}
|
||||
|
||||
// fix up the inner bounds, we may have to only lookup a portion
|
||||
// of the text control if the current node is a boundary point
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> outerNode(do_QueryInterface(aContent));
|
||||
if (outerNode == mStartOuterNode) {
|
||||
mRange->GetStartOffset(&offset);
|
||||
mRange->GetStartContainer(getter_AddRefs(node));
|
||||
range->SetStart(node, offset);
|
||||
innerRange->SetStart(mStartNode, mStartOffset);
|
||||
}
|
||||
if (outerNode == mEndOuterNode) {
|
||||
mRange->GetEndOffset(&offset);
|
||||
mRange->GetEndContainer(getter_AddRefs(node));
|
||||
range->SetEnd(node, offset);
|
||||
innerRange->SetEnd(mEndNode, mEndOffset);
|
||||
}
|
||||
// Note: we just init here. We do First() or Last() later.
|
||||
mInnerIterator->Init(range);
|
||||
mInnerIterator->Init(innerRange);
|
||||
|
||||
// make sure to place the outer-iterator outside
|
||||
// the text control so that we don't go there again.
|
||||
nsresult res;
|
||||
mRange->CloneRange(getter_AddRefs(range));
|
||||
if (!mFindBackward) { // find forward
|
||||
// cut the outer-iterator after the current node
|
||||
res = range->SetStartAfter(outerNode);
|
||||
res = outerRange->SetEnd(mEndNode, mEndOffset);
|
||||
res |= outerRange->SetStartAfter(outerNode);
|
||||
}
|
||||
else { // find backward
|
||||
// cut the outer-iterator before the current node
|
||||
res = range->SetEndBefore(outerNode);
|
||||
res = outerRange->SetStart(mStartNode, mStartOffset);
|
||||
res |= outerRange->SetEndBefore(outerNode);
|
||||
}
|
||||
if (NS_FAILED(res)) {
|
||||
// we are done with the outer-iterator, the
|
||||
// inner-iterator will traverse what we want
|
||||
range->Collapse(PR_TRUE);
|
||||
outerRange->Collapse(PR_TRUE);
|
||||
}
|
||||
// Note: we just re-init here, using the segment of mRange that is
|
||||
// yet to be visited. Thus when we later do mOuterIterator->First()
|
||||
// [or mOuterIterator->Last()], we will effectively be on the next
|
||||
// node [or the previous node] _with respect to_ mRange.
|
||||
mOuterIterator->Init(range);
|
||||
|
||||
// Note: we just re-init here, using the segment of our search range that
|
||||
// is yet to be visited. Thus when we later do mOuterIterator->First() [or
|
||||
// mOuterIterator->Last()], we will effectively be on the next node [or
|
||||
// the previous node] _with respect to_ the search range.
|
||||
mOuterIterator->Init(outerRange);
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,23 +558,24 @@ static void DumpRange(nsIDOMRange* aRange)
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsFind::InitIterator(nsIDOMRange* aSearchRange)
|
||||
nsFind::InitIterator(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mIterator)
|
||||
{
|
||||
rv = NS_NewFindContentIterator(mFindBackward, getter_AddRefs(mIterator));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_ARG_POINTER(mIterator);
|
||||
mIterator = new nsFindContentIterator(mFindBackward);
|
||||
NS_ENSURE_TRUE(mIterator, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aSearchRange);
|
||||
NS_ENSURE_ARG_POINTER(aStartNode);
|
||||
NS_ENSURE_ARG_POINTER(aEndNode);
|
||||
|
||||
#ifdef DEBUG_FIND
|
||||
printf("InitIterator search range:\n"); DumpRange(aSearchRange);
|
||||
#endif
|
||||
|
||||
rv = mIterator->Init(aSearchRange);
|
||||
nsresult rv =
|
||||
mIterator->Init(aStartNode, aStartOffset, aEndNode, aEndOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mFindBackward) {
|
||||
mIterator->Last();
|
||||
@ -639,15 +666,14 @@ nsFind::NextNode(nsIDOMRange* aSearchRange,
|
||||
// If we are continuing, that means we have a match in progress.
|
||||
// In that case, we want to continue from the end point
|
||||
// (where we are now) to the beginning/end of the search range.
|
||||
nsCOMPtr<nsIDOMRange> newRange (do_CreateInstance(kRangeCID));
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 startOffset, endOffset;
|
||||
if (aContinueOk)
|
||||
{
|
||||
#ifdef DEBUG_FIND
|
||||
printf("Match in progress: continuing past endpoint\n");
|
||||
#endif
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 startOffset, endOffset;
|
||||
if (mFindBackward) {
|
||||
aSearchRange->GetStartContainer(getter_AddRefs(startNode));
|
||||
aSearchRange->GetStartOffset(&startOffset);
|
||||
@ -659,14 +685,9 @@ nsFind::NextNode(nsIDOMRange* aSearchRange,
|
||||
aSearchRange->GetEndContainer(getter_AddRefs(endNode));
|
||||
aSearchRange->GetEndOffset(&endOffset);
|
||||
}
|
||||
newRange->SetStart(startNode, startOffset);
|
||||
newRange->SetEnd(endNode, endOffset);
|
||||
}
|
||||
else // Normal, not continuing
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 startOffset, endOffset;
|
||||
if (mFindBackward) {
|
||||
aSearchRange->GetStartContainer(getter_AddRefs(startNode));
|
||||
aSearchRange->GetStartOffset(&startOffset);
|
||||
@ -685,11 +706,9 @@ nsFind::NextNode(nsIDOMRange* aSearchRange,
|
||||
aEndPoint->GetEndContainer(getter_AddRefs(endNode));
|
||||
aEndPoint->GetEndOffset(&endOffset);
|
||||
}
|
||||
newRange->SetStart(startNode, startOffset);
|
||||
newRange->SetEnd(endNode, endOffset);
|
||||
}
|
||||
|
||||
rv = InitIterator(newRange);
|
||||
rv = InitIterator(startNode, startOffset, endNode, endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!aStartPoint)
|
||||
aStartPoint = aSearchRange;
|
||||
|
@ -56,6 +56,8 @@ class nsIAtom;
|
||||
#define NS_FIND_CID \
|
||||
{0x471f4944, 0x1dd2, 0x11b2, {0x87, 0xac, 0x90, 0xbe, 0x0a, 0x51, 0xd6, 0x09}}
|
||||
|
||||
class nsFindContentIterator;
|
||||
|
||||
class nsFind : public nsIFind
|
||||
{
|
||||
public:
|
||||
@ -109,8 +111,9 @@ protected:
|
||||
void ResetAll();
|
||||
|
||||
// The iterator we use to move through the document:
|
||||
nsresult InitIterator(nsIDOMRange* aSearchRange);
|
||||
nsCOMPtr<nsIContentIterator> mIterator;
|
||||
nsresult InitIterator(nsIDOMNode* aStartNode, PRInt32 aStartOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset);
|
||||
nsCOMPtr<nsFindContentIterator> mIterator;
|
||||
};
|
||||
|
||||
#endif // nsFind_h__
|
||||
|
Loading…
Reference in New Issue
Block a user