Index: third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
index 902073e0dd73acc496431ce33711eb029351e7f4..46e0c7f130cd5f3384113508bfe8e8e856c2aa6d 100644 |
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
@@ -43,6 +43,7 @@ |
#include "core/editing/commands/TypingCommand.h" |
#include "core/editing/iterators/CharacterIterator.h" |
#include "core/editing/markers/DocumentMarkerController.h" |
+#include "core/editing/markers/SpellCheckMarker.h" |
#include "core/editing/spellcheck/IdleSpellCheckCallback.h" |
#include "core/editing/spellcheck/SpellCheckRequester.h" |
#include "core/editing/spellcheck/SpellCheckerClient.h" |
@@ -811,51 +812,93 @@ void SpellChecker::RemoveSpellingAndGrammarMarkers(const HTMLElement& element, |
} |
} |
yosin_UTC9
2017/06/08 01:50:09
Could you move spell checker changes into another
|
-void SpellChecker::ReplaceMisspelledRange(const String& text) { |
- EphemeralRange caret_range = GetFrame() |
- .Selection() |
- .ComputeVisibleSelectionInDOMTree() |
- .ToNormalizedEphemeralRange(); |
- if (caret_range.IsNull()) |
- return; |
+namespace { |
- Node* const caret_start_container = |
- caret_range.StartPosition().ComputeContainerNode(); |
- Node* const caret_end_container = |
- caret_range.EndPosition().ComputeContainerNode(); |
+EphemeralRange ExpandSelectionRangeIfNecessary( |
+ const VisibleSelection& selection) { |
+ DCHECK(!selection.IsNone()); |
- // We don't currently support the case where a misspelling spans multiple |
- // nodes |
- if (caret_start_container != caret_end_container) |
- return; |
+ // If some text is actually selected, we can use the selection range as-is to |
+ // check for a marker. If no text is selected (we just have a caret |
+ // somewhere), we need to expand one character on either side so we can find |
+ // a spelling marker immediately before or after the caret. |
- const unsigned caret_start_offset = |
- caret_range.StartPosition().ComputeOffsetInContainerNode(); |
- const unsigned caret_end_offset = |
- caret_range.EndPosition().ComputeOffsetInContainerNode(); |
- |
- const DocumentMarkerVector& markers_in_node = |
- GetFrame().GetDocument()->Markers().MarkersFor( |
- caret_start_container, DocumentMarker::MisspellingMarkers()); |
- |
- const auto marker_it = |
- std::find_if(markers_in_node.begin(), markers_in_node.end(), |
- [=](const DocumentMarker* marker) { |
- return marker->StartOffset() < caret_end_offset && |
- marker->EndOffset() > caret_start_offset; |
- }); |
- if (marker_it == markers_in_node.end()) |
- return; |
+ // (The spelling markers on these words may be anchored to a different node |
+ // than the collapsed selection's Position is, but once we expand the |
+ // selection, if we're next to a marker, either the start or end point should |
+ // now be anchored relative to the same text node as that marker.) |
+ |
+ // Some text is actually selected |
+ if (selection.IsRange()) |
+ return EphemeralRange(selection.Start(), selection.End()); |
+ |
+ // No text is actually selected, need to expand the selection range |
+ const VisiblePosition& caret_pos = selection.VisibleStart(); |
+ |
+ Position range_to_check_start = |
+ PreviousPositionOf(caret_pos).DeepEquivalent(); |
+ if (range_to_check_start.IsNull()) |
+ range_to_check_start = caret_pos.DeepEquivalent(); |
+ |
+ Position range_to_check_end = NextPositionOf(caret_pos).DeepEquivalent(); |
+ if (range_to_check_end.IsNull()) |
+ range_to_check_end = caret_pos.DeepEquivalent(); |
+ |
+ return EphemeralRange(range_to_check_start, range_to_check_end); |
+} |
+ |
+} // namespace |
- const DocumentMarker* found_marker = *marker_it; |
- EphemeralRange marker_range = EphemeralRange( |
- Position(caret_start_container, found_marker->StartOffset()), |
- Position(caret_start_container, found_marker->EndOffset())); |
- if (marker_range.IsNull()) |
+Optional<std::pair<Node*, SpellCheckMarker*>> |
+SpellChecker::GetSpellCheckMarkerTouchingSelection() { |
+ const VisibleSelection& selection = |
+ GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); |
+ if (selection.IsNone()) |
+ return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
+ |
+ const EphemeralRange& range_to_check = |
+ ExpandSelectionRangeIfNecessary(selection); |
+ |
+ Node* start_container = range_to_check.StartPosition().ComputeContainerNode(); |
+ const unsigned start_offset = |
+ range_to_check.StartPosition().ComputeOffsetInContainerNode(); |
+ Node* end_container = range_to_check.EndPosition().ComputeContainerNode(); |
+ const unsigned end_offset = |
+ range_to_check.EndPosition().ComputeOffsetInContainerNode(); |
+ |
+ for (Node& node : range_to_check.Nodes()) { |
+ const DocumentMarkerVector& markers_in_node = |
+ GetFrame().GetDocument()->Markers().MarkersFor( |
+ &node, DocumentMarker::MisspellingMarkers()); |
+ for (DocumentMarker* marker : markers_in_node) { |
+ if (node == start_container && marker->EndOffset() <= start_offset) |
+ continue; |
+ if (node == end_container && marker->StartOffset() >= end_offset) |
+ continue; |
+ |
+ return std::make_pair(&node, &ToSpellCheckMarker(*marker)); |
+ } |
+ } |
+ |
+ // No marker found |
+ return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
+} |
+ |
+void SpellChecker::ReplaceMisspelledRange(const String& text) { |
+ const Optional<std::pair<Node*, SpellCheckMarker*>>& node_and_marker = |
+ GetSpellCheckMarkerTouchingSelection(); |
+ if (!node_and_marker) |
return; |
+ Node* const container_node = node_and_marker.value().first; |
+ const SpellCheckMarker* const marker = node_and_marker.value().second; |
+ |
+ const EphemeralRange misspelled_range( |
+ Position(container_node, marker->StartOffset()), |
+ Position(container_node, marker->EndOffset())); |
+ |
GetFrame().Selection().SetSelection( |
- SelectionInDOMTree::Builder().SetBaseAndExtent(marker_range).Build()); |
+ SelectionInDOMTree::Builder().SetBaseAndExtent(misspelled_range).Build()); |
Document& current_document = *GetFrame().GetDocument(); |