Bug 804799. Make sure we keep advancing our current find point through the document even in cases when we optimize by moving it to the first visible range, so we don't get stuck in an infinite loop. r=masayuki
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 24 Oct 2012 16:10:49 -0400
changeset 111418 fdb09cf360f303b2011f9c6102efcd1c28a4b2d7
parent 111417 44b335425300654fa8d1cd5d78ce0dba40307c1b
child 111419 92ebd9011e11ca2ede27d40ef2d6b03ec4b631ea
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersmasayuki
bugs804799
milestone19.0a1
Bug 804799. Make sure we keep advancing our current find point through the document even in cases when we optimize by moving it to the first visible range, so we don't get stuck in an infinite loop. r=masayuki
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -385,20 +385,52 @@ nsTypeAheadFind::FindItNow(nsIPresShell 
       bool usesIndependentSelection;
       if (!IsRangeVisible(presShell, presContext, returnRange,
                           aIsFirstVisiblePreferred, false,
                           getter_AddRefs(mStartPointRange), 
                           &usesIndependentSelection) ||
           (aIsLinksOnly && !isInsideLink) ||
           (mStartLinksOnlyPref && aIsLinksOnly && !isStartingLink)) {
         // ------ Failure ------
-        // mStartPointRange got updated to the right thing already,
-        // but we stil need to collapse it to the right end.
-        mStartPointRange->Collapse(aFindPrev);
-
+        // At this point mStartPointRange got updated to the first
+        // visible range in the viewport.  We _may_ be able to just
+        // start there, if it's not taking us in the wrong direction.
+        if (aFindPrev) {
+          // We can continue at the end of mStartPointRange if its end is before
+          // the start of returnRange or coincides with it.  Otherwise, we need
+          // to continue at the start of returnRange.
+          int16_t compareResult;
+          nsresult rv =
+            mStartPointRange->CompareBoundaryPoints(nsIDOMRange::START_TO_END,
+                                                    returnRange, &compareResult);
+          if (NS_SUCCEEDED(rv) && compareResult <= 0) {
+            // OK to start at the end of mStartPointRange
+            mStartPointRange->Collapse(false);
+          } else {
+            // Start at the beginning of returnRange
+            returnRange->CloneRange(getter_AddRefs(mStartPointRange));
+            mStartPointRange->Collapse(true);
+          }
+        } else {
+          // We can continue at the start of mStartPointRange if its start is
+          // after the end of returnRange or coincides with it.  Otherwise, we
+          // need to continue at the end of returnRange.
+          int16_t compareResult;
+          nsresult rv =
+            mStartPointRange->CompareBoundaryPoints(nsIDOMRange::END_TO_START,
+                                                    returnRange, &compareResult);
+          if (NS_SUCCEEDED(rv) && compareResult >= 0) {
+            // OK to start at the start of mStartPointRange
+            mStartPointRange->Collapse(true);
+          } else {
+            // Start at the end of returnRange
+            returnRange->CloneRange(getter_AddRefs(mStartPointRange));
+            mStartPointRange->Collapse(false);
+          }
+        }
         continue;
       }
 
       // ------ Success! -------
       // Hide old selection (new one may be on a different controller)
       if (selection) {
         selection->CollapseToStart();
         SetSelectionModeAndRepaint(nsISelectionController::SELECTION_ON);
@@ -1141,19 +1173,19 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
                                       minDistance);
     }
   }
 
   if (frame) {
     nsCOMPtr<nsIDOMNode> firstVisibleNode = do_QueryInterface(frame->GetContent());
 
     if (firstVisibleNode) {
-      (*aFirstVisibleRange)->SelectNode(firstVisibleNode);
       frame->GetOffsets(startFrameOffset, endFrameOffset);
       (*aFirstVisibleRange)->SetStart(firstVisibleNode, startFrameOffset);
+      (*aFirstVisibleRange)->SetEnd(firstVisibleNode, endFrameOffset);
     }
   }
 
   return false;
 }
 
 already_AddRefed<nsIPresShell>
 nsTypeAheadFind::GetPresShell()