Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 #include "core/dom/Range.h" | 36 #include "core/dom/Range.h" |
| 37 #include "core/editing/EditingUtilities.h" | 37 #include "core/editing/EditingUtilities.h" |
| 38 #include "core/editing/Editor.h" | 38 #include "core/editing/Editor.h" |
| 39 #include "core/editing/EphemeralRange.h" | 39 #include "core/editing/EphemeralRange.h" |
| 40 #include "core/editing/VisibleUnits.h" | 40 #include "core/editing/VisibleUnits.h" |
| 41 #include "core/editing/commands/CompositeEditCommand.h" | 41 #include "core/editing/commands/CompositeEditCommand.h" |
| 42 #include "core/editing/commands/ReplaceSelectionCommand.h" | 42 #include "core/editing/commands/ReplaceSelectionCommand.h" |
| 43 #include "core/editing/commands/TypingCommand.h" | 43 #include "core/editing/commands/TypingCommand.h" |
| 44 #include "core/editing/iterators/CharacterIterator.h" | 44 #include "core/editing/iterators/CharacterIterator.h" |
| 45 #include "core/editing/markers/DocumentMarkerController.h" | 45 #include "core/editing/markers/DocumentMarkerController.h" |
| 46 #include "core/editing/markers/SpellCheckMarker.h" | |
| 46 #include "core/editing/spellcheck/IdleSpellCheckCallback.h" | 47 #include "core/editing/spellcheck/IdleSpellCheckCallback.h" |
| 47 #include "core/editing/spellcheck/SpellCheckRequester.h" | 48 #include "core/editing/spellcheck/SpellCheckRequester.h" |
| 48 #include "core/editing/spellcheck/SpellCheckerClient.h" | 49 #include "core/editing/spellcheck/SpellCheckerClient.h" |
| 49 #include "core/editing/spellcheck/TextCheckingParagraph.h" | 50 #include "core/editing/spellcheck/TextCheckingParagraph.h" |
| 50 #include "core/frame/LocalFrame.h" | 51 #include "core/frame/LocalFrame.h" |
| 51 #include "core/frame/Settings.h" | 52 #include "core/frame/Settings.h" |
| 52 #include "core/html/HTMLInputElement.h" | 53 #include "core/html/HTMLInputElement.h" |
| 53 #include "core/layout/LayoutTextControl.h" | 54 #include "core/layout/LayoutTextControl.h" |
| 54 #include "core/loader/EmptyClients.h" | 55 #include "core/loader/EmptyClients.h" |
| 55 #include "core/page/Page.h" | 56 #include "core/page/Page.h" |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 // TODO(xiaochengh): The following comment does not match the current behavior | 607 // TODO(xiaochengh): The following comment does not match the current behavior |
| 607 // and should be rewritten. | 608 // and should be rewritten. |
| 608 // Expand the range to encompass entire paragraphs, since text checking needs | 609 // Expand the range to encompass entire paragraphs, since text checking needs |
| 609 // that much context. | 610 // that much context. |
| 610 int ambiguous_boundary_offset = -1; | 611 int ambiguous_boundary_offset = -1; |
| 611 | 612 |
| 612 if (GetFrame().Selection().ComputeVisibleSelectionInDOMTree().IsCaret()) { | 613 if (GetFrame().Selection().ComputeVisibleSelectionInDOMTree().IsCaret()) { |
| 613 // TODO(xiaochengh): The following comment does not match the current | 614 // TODO(xiaochengh): The following comment does not match the current |
| 614 // behavior and should be rewritten. | 615 // behavior and should be rewritten. |
| 615 // Attempt to save the caret position so we can restore it later if needed | 616 // Attempt to save the caret position so we can restore it later if needed |
| 616 const Position& caret_position = | 617 const Position& caret_positionition = |
|
Xiaocheng
2017/06/09 04:17:26
Irrelevant change.
| |
| 617 GetFrame().Selection().ComputeVisibleSelectionInDOMTree().End(); | 618 GetFrame().Selection().ComputeVisibleSelectionInDOMTree().End(); |
| 618 const Position& paragraph_start = checking_range.StartPosition(); | 619 const Position& paragraph_start = checking_range.StartPosition(); |
| 619 const int selection_offset = | 620 const int selection_offset = |
| 620 paragraph_start < caret_position | 621 paragraph_start < caret_positionition |
| 621 ? TextIterator::RangeLength(paragraph_start, caret_position) | 622 ? TextIterator::RangeLength(paragraph_start, caret_positionition) |
| 622 : 0; | 623 : 0; |
| 623 if (selection_offset > 0 && | 624 if (selection_offset > 0 && |
| 624 static_cast<unsigned>(selection_offset) <= | 625 static_cast<unsigned>(selection_offset) <= |
| 625 paragraph.GetText().length() && | 626 paragraph.GetText().length() && |
| 626 IsAmbiguousBoundaryCharacter( | 627 IsAmbiguousBoundaryCharacter( |
| 627 paragraph.TextCharAt(selection_offset - 1))) { | 628 paragraph.TextCharAt(selection_offset - 1))) { |
| 628 ambiguous_boundary_offset = selection_offset - 1; | 629 ambiguous_boundary_offset = selection_offset - 1; |
| 629 } | 630 } |
| 630 } | 631 } |
| 631 | 632 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 DocumentMarker::MarkerTypes marker_types(DocumentMarker::kSpelling); | 805 DocumentMarker::MarkerTypes marker_types(DocumentMarker::kSpelling); |
| 805 marker_types.Add(DocumentMarker::kGrammar); | 806 marker_types.Add(DocumentMarker::kGrammar); |
| 806 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) { | 807 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) { |
| 807 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) { | 808 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) { |
| 808 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node, | 809 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node, |
| 809 marker_types); | 810 marker_types); |
| 810 } | 811 } |
| 811 } | 812 } |
| 812 } | 813 } |
| 813 | 814 |
| 815 namespace { | |
|
Xiaocheng
2017/06/09 04:17:26
We already have an anonymous namespace at the begi
| |
| 816 | |
| 817 EphemeralRange ExpandSelectionRangeIfNecessary( | |
| 818 const VisibleSelection& selection) { | |
| 819 DCHECK(!selection.IsNone()); | |
| 820 | |
| 821 // If some text is actually selected, we can use the selection range as-is to | |
| 822 // check for a marker. If no text is selected (we just have a caret | |
| 823 // somewhere), we need to expand one character on either side so we can find | |
| 824 // a spelling marker immediately before or after the caret. | |
| 825 | |
| 826 // (The spelling markers on these words may be anchored to a different node | |
| 827 // than the collapsed selection's Position is, but once we expand the | |
| 828 // selection, if we're next to a marker, either the start or end point should | |
| 829 // now be anchored relative to the same text node as that marker.) | |
| 830 | |
| 831 // Some text is actually selected | |
| 832 if (selection.IsRange()) | |
| 833 return EphemeralRange(selection.Start(), selection.End()); | |
| 834 | |
| 835 // No text is actually selected, need to expand the selection range | |
| 836 const VisiblePosition& caret_position = selection.VisibleStart(); | |
|
yosin_UTC9
2017/06/09 03:28:15
Could you add an example, your provided in reply?
| |
| 837 | |
| 838 const Position& previous_position = | |
| 839 PreviousPositionOf(caret_position).DeepEquivalent(); | |
| 840 | |
| 841 const Position& next_position = | |
| 842 NextPositionOf(caret_position).DeepEquivalent(); | |
| 843 | |
| 844 return EphemeralRange( | |
| 845 previous_position.IsNull() ? caret_position.DeepEquivalent() | |
| 846 : previous_position, | |
| 847 next_position.IsNull() ? caret_position.DeepEquivalent() : next_position); | |
| 848 } | |
| 849 | |
| 850 } // namespace | |
| 851 | |
| 852 Optional<std::pair<Node*, SpellCheckMarker*>> | |
| 853 SpellChecker::GetSpellCheckMarkerTouchingSelection() { | |
| 854 const VisibleSelection& selection = | |
| 855 GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); | |
| 856 if (selection.IsNone()) | |
| 857 return Optional<std::pair<Node*, SpellCheckMarker*>>(); | |
| 858 | |
| 859 const EphemeralRange& range_to_check = | |
| 860 ExpandSelectionRangeIfNecessary(selection); | |
| 861 | |
| 862 Node* const start_container = | |
| 863 range_to_check.StartPosition().ComputeContainerNode(); | |
| 864 const unsigned start_offset = | |
| 865 range_to_check.StartPosition().ComputeOffsetInContainerNode(); | |
| 866 Node* const end_container = | |
| 867 range_to_check.EndPosition().ComputeContainerNode(); | |
| 868 const unsigned end_offset = | |
| 869 range_to_check.EndPosition().ComputeOffsetInContainerNode(); | |
| 870 | |
| 871 for (Node& node : range_to_check.Nodes()) { | |
| 872 const DocumentMarkerVector& markers_in_node = | |
| 873 GetFrame().GetDocument()->Markers().MarkersFor( | |
| 874 &node, DocumentMarker::MisspellingMarkers()); | |
| 875 for (DocumentMarker* marker : markers_in_node) { | |
| 876 if (node == start_container && marker->EndOffset() <= start_offset) | |
| 877 continue; | |
| 878 if (node == end_container && marker->StartOffset() >= end_offset) | |
| 879 continue; | |
| 880 | |
| 881 return std::make_pair(&node, &ToSpellCheckMarker(*marker)); | |
| 882 } | |
| 883 } | |
| 884 | |
| 885 // No marker found | |
| 886 return Optional<std::pair<Node*, SpellCheckMarker*>>(); | |
| 887 } | |
| 888 | |
| 814 void SpellChecker::ReplaceMisspelledRange(const String& text) { | 889 void SpellChecker::ReplaceMisspelledRange(const String& text) { |
| 815 EphemeralRange caret_range = GetFrame() | 890 const Optional<std::pair<Node*, SpellCheckMarker*>>& node_and_marker = |
| 816 .Selection() | 891 GetSpellCheckMarkerTouchingSelection(); |
| 817 .ComputeVisibleSelectionInDOMTree() | 892 if (!node_and_marker) |
| 818 .ToNormalizedEphemeralRange(); | |
| 819 if (caret_range.IsNull()) | |
| 820 return; | 893 return; |
| 821 | 894 |
| 822 Node* const caret_start_container = | 895 Node* const container_node = node_and_marker.value().first; |
| 823 caret_range.StartPosition().ComputeContainerNode(); | 896 const SpellCheckMarker* const marker = node_and_marker.value().second; |
| 824 Node* const caret_end_container = | |
| 825 caret_range.EndPosition().ComputeContainerNode(); | |
| 826 | |
| 827 // We don't currently support the case where a misspelling spans multiple | |
| 828 // nodes | |
| 829 if (caret_start_container != caret_end_container) | |
| 830 return; | |
| 831 | |
| 832 const unsigned caret_start_offset = | |
| 833 caret_range.StartPosition().ComputeOffsetInContainerNode(); | |
| 834 const unsigned caret_end_offset = | |
| 835 caret_range.EndPosition().ComputeOffsetInContainerNode(); | |
| 836 | |
| 837 const DocumentMarkerVector& markers_in_node = | |
| 838 GetFrame().GetDocument()->Markers().MarkersFor( | |
| 839 caret_start_container, DocumentMarker::MisspellingMarkers()); | |
| 840 | |
| 841 const auto marker_it = | |
| 842 std::find_if(markers_in_node.begin(), markers_in_node.end(), | |
| 843 [=](const DocumentMarker* marker) { | |
| 844 return marker->StartOffset() < caret_end_offset && | |
| 845 marker->EndOffset() > caret_start_offset; | |
| 846 }); | |
| 847 if (marker_it == markers_in_node.end()) | |
| 848 return; | |
| 849 | |
| 850 const DocumentMarker* found_marker = *marker_it; | |
| 851 EphemeralRange marker_range = EphemeralRange( | |
| 852 Position(caret_start_container, found_marker->StartOffset()), | |
| 853 Position(caret_start_container, found_marker->EndOffset())); | |
| 854 if (marker_range.IsNull()) | |
| 855 return; | |
| 856 | 897 |
| 857 GetFrame().Selection().SetSelection( | 898 GetFrame().Selection().SetSelection( |
| 858 SelectionInDOMTree::Builder().SetBaseAndExtent(marker_range).Build()); | 899 SelectionInDOMTree::Builder() |
| 900 .Collapse(Position(container_node, marker->StartOffset())) | |
| 901 .Extend(Position(container_node, marker->EndOffset())) | |
| 902 .Build()); | |
| 859 | 903 |
| 860 Document& current_document = *GetFrame().GetDocument(); | 904 Document& current_document = *GetFrame().GetDocument(); |
| 861 | 905 |
| 862 // Dispatch 'beforeinput'. | 906 // Dispatch 'beforeinput'. |
| 863 Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection(); | 907 Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection(); |
| 864 DataTransfer* const data_transfer = DataTransfer::Create( | 908 DataTransfer* const data_transfer = DataTransfer::Create( |
| 865 DataTransfer::DataTransferType::kInsertReplacementText, | 909 DataTransfer::DataTransferType::kInsertReplacementText, |
| 866 DataTransferAccessPolicy::kDataTransferReadable, | 910 DataTransferAccessPolicy::kDataTransferReadable, |
| 867 DataObject::CreateFromString(text)); | 911 DataObject::CreateFromString(text)); |
| 868 | 912 |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1239 if (!input.IsFocusedElementInDocument()) | 1283 if (!input.IsFocusedElementInDocument()) |
| 1240 return false; | 1284 return false; |
| 1241 } | 1285 } |
| 1242 } | 1286 } |
| 1243 HTMLElement* element = | 1287 HTMLElement* element = |
| 1244 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode()); | 1288 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode()); |
| 1245 return element && element->IsSpellCheckingEnabled(); | 1289 return element && element->IsSpellCheckingEnabled(); |
| 1246 } | 1290 } |
| 1247 | 1291 |
| 1248 } // namespace blink | 1292 } // namespace blink |
| OLD | NEW |