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;
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.
void Editor::pasteWithPasteboard(Pasteboard* pasteboard)
{
- RefPtr<Range> range = selectedRange();
+ RefPtrWillBeRawPtr<Range> range = selectedRange();
RefPtr<DocumentFragment> fragment;
bool chosePlainText = false;
? 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) {
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);
VisibleSelection selection = selectionForCommand(triggeringEvent);
if (!selection.isContentEditable())
return false;
- RefPtr<Range> range = selection.toNormalizedRange();
spellChecker().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
// 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);
}
}
}
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();
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);
{
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;
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;
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)