Chromium Code Reviews| 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 ba21d975ac05a24dba58647b0799d65f5bd65221..37423339387a8ee510c810aa4666dcaacbea140b 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,78 @@ void SpellChecker::RemoveSpellingAndGrammarMarkers(const HTMLElement& element, |
| } |
| } |
| -void SpellChecker::ReplaceMisspelledRange(const String& text) { |
| - EphemeralRange caret_range = GetFrame() |
| - .Selection() |
| - .ComputeVisibleSelectionInDOMTree() |
| - .ToNormalizedEphemeralRange(); |
| - if (caret_range.IsNull()) |
| - return; |
| +Optional<std::pair<Node*, SpellCheckMarker*>> |
| +SpellChecker::GetSpellCheckMarkerTouchingSelection() { |
| + const VisibleSelection& selection = |
| + GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); |
| + if (selection.IsNone()) |
| + return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
| + |
| + EphemeralRange range_to_check(selection.Start(), selection.End()); |
|
yosin_UTC9
2017/06/07 01:34:15
Could you move calculation of |range_to_check| in
|
| + // 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. |
| + |
| + // (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.) |
| + if (range_to_check.IsCollapsed()) { |
| + 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(); |
| + |
| + range_to_check = EphemeralRange(range_to_check_start, range_to_check_end); |
| + } |
| - Node* const caret_start_container = |
| - caret_range.StartPosition().ComputeContainerNode(); |
| - Node* const caret_end_container = |
| - caret_range.EndPosition().ComputeContainerNode(); |
| + Node* start_container = range_to_check.StartPosition().ComputeContainerNode(); |
|
yosin_UTC9
2017/06/07 01:34:16
nit: s/Node*/Node* const/
|
| + const unsigned start_offset = |
| + range_to_check.StartPosition().ComputeOffsetInContainerNode(); |
| + Node* end_container = range_to_check.EndPosition().ComputeContainerNode(); |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/Node*/Node* const/
|
| + 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) |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/&node/node/
There is |bool operator==(const
|
| + continue; |
| + if (&node == end_container && marker->StartOffset() >= end_offset) |
|
yosin_UTC9
2017/06/07 01:34:16
nit: s/&node/node/
There is |bool operator==(const
|
| + continue; |
| - // We don't currently support the case where a misspelling spans multiple |
| - // nodes |
| - if (caret_start_container != caret_end_container) |
| - return; |
| + return std::make_pair(&node, &ToSpellCheckMarker(*marker)); |
| + } |
| + } |
| - 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; |
| + // No marker found |
| + return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
| +} |
| - 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()) |
| +void SpellChecker::ReplaceMisspelledRange(const String& text) { |
| + Optional<std::pair<Node*, SpellCheckMarker*>> node_and_marker = |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/Optional<std::pair<Node*, SpellCheckMarker*
|
| + GetSpellCheckMarkerTouchingSelection(); |
| + if (!node_and_marker) |
| return; |
| + Node* container_node = node_and_marker.value().first; |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/Node*/Node* const/
|
| + SpellCheckMarker* marker = node_and_marker.value().second; |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/SpellCheckMakrer*/SpellCheckMakrer* const/
|
| + |
| + EphemeralRange misspelled_range( |
|
yosin_UTC9
2017/06/07 01:34:15
nit: s/EphemeralRange/const EphemeralRange/
|
| + 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(); |