Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / editing / Editor.cpp
index 0dc1f6d..a91f9e2 100644 (file)
@@ -117,7 +117,7 @@ VisibleSelection Editor::selectionForCommand(Event* event)
     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
     HTMLTextFormControlElement* textFromControlOfTarget = isHTMLTextFormControlElement(*event->target()->toNode()) ? toHTMLTextFormControlElement(event->target()->toNode()) : 0;
     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
-        if (RefPtr<Range> range = textFromControlOfTarget->selection())
+        if (RefPtrWillBeRawPtr<Range> range = textFromControlOfTarget->selection())
             return VisibleSelection(range.get(), DOWNSTREAM, selection.isDirectional());
     }
     return selection;
@@ -258,7 +258,7 @@ bool Editor::canDeleteRange(Range* range) const
     if (!startContainer->rendererIsEditable() || !endContainer->rendererIsEditable())
         return false;
 
-    if (range->collapsed(IGNORE_EXCEPTION)) {
+    if (range->collapsed()) {
         VisiblePosition start(range->startPosition(), DOWNSTREAM);
         VisiblePosition previous = start.previous();
         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
@@ -387,7 +387,7 @@ void Editor::pasteAsPlainTextWithPasteboard(Pasteboard* pasteboard)
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard)
 {
-    RefPtr<Range> range = selectedRange();
+    RefPtrWillBeRawPtr<Range> range = selectedRange();
     RefPtr<DocumentFragment> fragment;
     bool chosePlainText = false;
 
@@ -464,7 +464,7 @@ bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPoli
             ? DataObject::create()
             : DataObject::createFromPasteboard(pasteMode));
 
-    RefPtr<Event> evt = ClipboardEvent::create(eventType, true, true, clipboard);
+    RefPtrWillBeRawPtr<Event> evt = ClipboardEvent::create(eventType, true, true, clipboard);
     target->dispatchEvent(evt, IGNORE_EXCEPTION);
     bool noDefaultProcessing = evt->defaultPrevented();
     if (noDefaultProcessing && policy == ClipboardWritable) {
@@ -509,14 +509,14 @@ void Editor::replaceSelectionWithText(const String& text, bool selectReplacement
     replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), text), selectReplacement, smartReplace, true);
 }
 
-PassRefPtr<Range> Editor::selectedRange()
+PassRefPtrWillBeRawPtr<Range> Editor::selectedRange()
 {
     return m_frame.selection().toNormalizedRange();
 }
 
 bool Editor::shouldDeleteRange(Range* range) const
 {
-    if (!range || range->collapsed(IGNORE_EXCEPTION))
+    if (!range || range->collapsed())
         return false;
 
     return canDeleteRange(range);
@@ -784,7 +784,6 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
     VisibleSelection selection = selectionForCommand(triggeringEvent);
     if (!selection.isContentEditable())
         return false;
-    RefPtr<Range> range = selection.toNormalizedRange();
 
     spellChecker().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
 
@@ -805,7 +804,7 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
             // Reveal the current selection
             if (LocalFrame* editedFrame = document->frame()) {
                 if (Page* page = editedFrame->page())
-                    page->focusController().focusedOrMainFrame()->selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
+                    toLocalFrame(page->focusController().focusedOrMainFrame())->selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
             }
         }
     }
@@ -850,7 +849,7 @@ void Editor::cut()
         return; // DHTML did the whole operation
     if (!canCut())
         return;
-    RefPtr<Range> selection = selectedRange();
+    RefPtrWillBeRawPtr<Range> selection = selectedRange();
     if (shouldDeleteRange(selection.get())) {
         spellChecker().updateMarkersForWordsAffectedByEditing(true);
         String plainText = m_frame.selectedTextForClipboard();
@@ -994,7 +993,7 @@ void Editor::transpose()
     previous = previous.previous();
     if (!inSameParagraph(next, previous))
         return;
-    RefPtr<Range> range = makeRange(previous, next);
+    RefPtrWillBeRawPtr<Range> range = makeRange(previous, next);
     if (!range)
         return;
     VisibleSelection newSelection(range.get(), DOWNSTREAM);
@@ -1115,7 +1114,7 @@ bool Editor::findString(const String& target, FindOptions options)
 {
     VisibleSelection selection = m_frame.selection().selection();
 
-    RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
+    RefPtrWillBeRawPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
 
     if (!resultRange)
         return false;
@@ -1125,9 +1124,9 @@ bool Editor::findString(const String& target, FindOptions options)
     return true;
 }
 
-PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
+PassRefPtrWillBeRawPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
 {
-    RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
+    RefPtrWillBeRawPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
     if (!nextMatch)
         return nullptr;
 
@@ -1137,75 +1136,76 @@ PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Ran
     return nextMatch.release();
 }
 
-PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
+static PassRefPtrWillBeRawPtr<Range> findStringBetweenPositions(const String& target, const Position& start, const Position& end, FindOptions options)
+{
+    Position searchStart(start);
+    Position searchEnd(end);
+
+    bool forward = !(options & Backwards);
+
+    while (true) {
+        Position resultStart;
+        Position resultEnd;
+        findPlainText(searchStart, searchEnd, target, options, resultStart, resultEnd);
+        if (resultStart == resultEnd)
+            return nullptr;
+
+        RefPtrWillBeRawPtr<Range> resultRange = Range::create(*resultStart.document(), resultStart, resultEnd);
+        if (!resultRange->collapsed())
+            return resultRange.release();
+
+        // Found text spans over multiple TreeScopes. Since it's impossible to return such section as a Range,
+        // we skip this match and seek for the next occurrence.
+        // FIXME: Handle this case.
+        if (forward)
+            searchStart = resultStart.next();
+        else
+            searchEnd = resultEnd.previous();
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+PassRefPtrWillBeRawPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
 {
     if (target.isEmpty())
         return nullptr;
 
-    // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
-    // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
-    RefPtr<Range> searchRange(rangeOfContents(m_frame.document()));
+    // Start from an edge of the reference range. Which edge is used depends on whether we're searching forward or
+    // backward, and whether startInSelection is set.
+    Position searchStart = firstPositionInNode(m_frame.document());
+    Position searchEnd = lastPositionInNode(m_frame.document());
 
     bool forward = !(options & Backwards);
     bool startInReferenceRange = referenceRange && (options & StartInSelection);
     if (referenceRange) {
         if (forward)
-            searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
+            searchStart = startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition();
         else
-            searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
+            searchEnd = startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition();
     }
 
-    RefPtr<Node> shadowTreeRoot = referenceRange && referenceRange->startContainer() ? referenceRange->startContainer()->nonBoundaryShadowTreeRootNode() : 0;
-    if (shadowTreeRoot) {
-        if (forward)
-            searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->countChildren());
-        else
-            searchRange->setStart(shadowTreeRoot.get(), 0);
-    }
+    RefPtrWillBeRawPtr<Range> resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
 
-    RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, options));
     // If we started in the reference range and the found range exactly matches the reference range, find again.
     // Build a selection with the found range to remove collapsed whitespace.
     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
-    if (startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
-        searchRange = rangeOfContents(m_frame.document());
+    if (resultRange && startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
         if (forward)
-            searchRange->setStart(referenceRange->endPosition());
+            searchStart = resultRange->endPosition();
         else
-            searchRange->setEnd(referenceRange->startPosition());
-
-        if (shadowTreeRoot) {
-            if (forward)
-                searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->countChildren());
-            else
-                searchRange->setStart(shadowTreeRoot.get(), 0);
-        }
-
-        resultRange = findPlainText(searchRange.get(), target, options);
-    }
-
-    // If nothing was found in the shadow tree, search in main content following the shadow tree.
-    if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && shadowTreeRoot) {
-        searchRange = rangeOfContents(m_frame.document());
-        if (forward)
-            searchRange->setStartAfter(shadowTreeRoot->shadowHost());
-        else
-            searchRange->setEndBefore(shadowTreeRoot->shadowHost());
-
-        resultRange = findPlainText(searchRange.get(), target, options);
+            searchEnd = resultRange->startPosition();
+        resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
     }
 
-    // If we didn't find anything and we're wrapping, search again in the entire document (this will
-    // redundantly re-search the area already searched in some cases).
-    if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && options & WrapAround) {
-        searchRange = rangeOfContents(m_frame.document());
-        resultRange = findPlainText(searchRange.get(), target, options);
-        // We used to return false here if we ended up with the same range that we started with
-        // (e.g., the reference range was already the only instance of this text). But we decided that
-        // this should be a success case instead, so we'll just fall through in that case.
+    if (!resultRange && options & WrapAround) {
+        searchStart = firstPositionInNode(m_frame.document());
+        searchEnd = lastPositionInNode(m_frame.document());
+        resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
     }
 
-    return resultRange->collapsed(ASSERT_NO_EXCEPTION) ? nullptr : resultRange.release();
+    return resultRange.release();
 }
 
 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)