| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 // TODO(yosin): We should fix |startOfWord()| and |endOfWord()| not to return | 88 // TODO(yosin): We should fix |startOfWord()| and |endOfWord()| not to return |
| 89 // null position. | 89 // null position. |
| 90 const VisiblePosition& start = StartOfWord(position, kLeftWordIfOnBoundary); | 90 const VisiblePosition& start = StartOfWord(position, kLeftWordIfOnBoundary); |
| 91 const VisiblePosition& end = EndOfWord(position, kRightWordIfOnBoundary); | 91 const VisiblePosition& end = EndOfWord(position, kRightWordIfOnBoundary); |
| 92 return SelectionInDOMTree::Builder() | 92 return SelectionInDOMTree::Builder() |
| 93 .SetBaseAndExtentDeprecated(start.DeepEquivalent(), end.DeepEquivalent()) | 93 .SetBaseAndExtentDeprecated(start.DeepEquivalent(), end.DeepEquivalent()) |
| 94 .SetAffinity(start.Affinity()) | 94 .SetAffinity(start.Affinity()) |
| 95 .Build(); | 95 .Build(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 EphemeralRange ExpandSelectionRangeIfNecessary( | |
| 99 const VisibleSelection& selection) { | |
| 100 DCHECK(!selection.IsNone()); | |
| 101 | |
| 102 // If some text is actually selected, we can use the selection range as-is to | |
| 103 // check for a marker. If no text is selected (we just have a caret | |
| 104 // somewhere), we need to expand one character on either side so we can find | |
| 105 // a spelling marker immediately before or after the caret. | |
| 106 | |
| 107 // (The spelling markers on these words may be anchored to a different node | |
| 108 // than the collapsed selection's Position is, but once we expand the | |
| 109 // selection, if we're next to a marker, either the start or end point should | |
| 110 // now be anchored relative to the same text node as that marker.) | |
| 111 | |
| 112 // Some text is actually selected | |
| 113 if (selection.IsRange()) | |
| 114 return EphemeralRange(selection.Start(), selection.End()); | |
| 115 | |
| 116 // No text is actually selected, need to expand the selection range. This is | |
| 117 // to make sure we can find a marker touching the caret. E.g. if we have: | |
| 118 // <span>word1 <b>word2</b></span> | |
| 119 // with a caret selection immediately before "word2", there's one text node | |
| 120 // immediately before the caret ("word1 ") and one immediately after | |
| 121 // ("word2"). Expanding the selection by one character on either side ensures | |
| 122 // we get a range that intersects both neighboring text nodes (if they exist). | |
| 123 const VisiblePosition& caret_position = selection.VisibleStart(); | |
| 124 | |
| 125 const Position& previous_position = | |
| 126 PreviousPositionOf(caret_position).DeepEquivalent(); | |
| 127 | |
| 128 const Position& next_position = | |
| 129 NextPositionOf(caret_position).DeepEquivalent(); | |
| 130 | |
| 131 return EphemeralRange( | |
| 132 previous_position.IsNull() ? caret_position.DeepEquivalent() | |
| 133 : previous_position, | |
| 134 next_position.IsNull() ? caret_position.DeepEquivalent() : next_position); | |
| 135 } | |
| 136 | |
| 137 } // namespace | 98 } // namespace |
| 138 | 99 |
| 139 SpellChecker* SpellChecker::Create(LocalFrame& frame) { | 100 SpellChecker* SpellChecker::Create(LocalFrame& frame) { |
| 140 return new SpellChecker(frame); | 101 return new SpellChecker(frame); |
| 141 } | 102 } |
| 142 | 103 |
| 143 static SpellCheckerClient& GetEmptySpellCheckerClient() { | 104 static SpellCheckerClient& GetEmptySpellCheckerClient() { |
| 144 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); | 105 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); |
| 145 return client; | 106 return client; |
| 146 } | 107 } |
| (...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 marker_types.Add(DocumentMarker::kGrammar); | 823 marker_types.Add(DocumentMarker::kGrammar); |
| 863 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) { | 824 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) { |
| 864 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) { | 825 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) { |
| 865 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node, | 826 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node, |
| 866 marker_types); | 827 marker_types); |
| 867 } | 828 } |
| 868 } | 829 } |
| 869 } | 830 } |
| 870 | 831 |
| 871 Optional<std::pair<Node*, SpellCheckMarker*>> | 832 Optional<std::pair<Node*, SpellCheckMarker*>> |
| 872 SpellChecker::GetSpellCheckMarkerTouchingSelection() { | 833 SpellChecker::GetSpellCheckMarkerUnderSelection() { |
| 873 const VisibleSelection& selection = | 834 const VisibleSelection& selection = |
| 874 GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); | 835 GetFrame().Selection().ComputeVisibleSelectionInDOMTree(); |
| 875 if (selection.IsNone()) | 836 if (selection.IsNone()) |
| 876 return Optional<std::pair<Node*, SpellCheckMarker*>>(); | 837 return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
| 877 | 838 |
| 878 const EphemeralRange& range_to_check = | 839 const EphemeralRange& range_to_check = FirstEphemeralRangeOf(selection); |
| 879 ExpandSelectionRangeIfNecessary(selection); | |
| 880 | 840 |
| 881 Node* const start_container = | 841 Node* const start_container = |
| 882 range_to_check.StartPosition().ComputeContainerNode(); | 842 range_to_check.StartPosition().ComputeContainerNode(); |
| 883 const unsigned start_offset = | 843 const unsigned start_offset = |
| 884 range_to_check.StartPosition().ComputeOffsetInContainerNode(); | 844 range_to_check.StartPosition().ComputeOffsetInContainerNode(); |
| 885 Node* const end_container = | 845 Node* const end_container = |
| 886 range_to_check.EndPosition().ComputeContainerNode(); | 846 range_to_check.EndPosition().ComputeContainerNode(); |
| 887 const unsigned end_offset = | 847 const unsigned end_offset = |
| 888 range_to_check.EndPosition().ComputeOffsetInContainerNode(); | 848 range_to_check.EndPosition().ComputeOffsetInContainerNode(); |
| 889 | 849 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 900 return std::make_pair(&node, &ToSpellCheckMarker(*marker)); | 860 return std::make_pair(&node, &ToSpellCheckMarker(*marker)); |
| 901 } | 861 } |
| 902 } | 862 } |
| 903 | 863 |
| 904 // No marker found | 864 // No marker found |
| 905 return Optional<std::pair<Node*, SpellCheckMarker*>>(); | 865 return Optional<std::pair<Node*, SpellCheckMarker*>>(); |
| 906 } | 866 } |
| 907 | 867 |
| 908 void SpellChecker::ReplaceMisspelledRange(const String& text) { | 868 void SpellChecker::ReplaceMisspelledRange(const String& text) { |
| 909 const Optional<std::pair<Node*, SpellCheckMarker*>>& node_and_marker = | 869 const Optional<std::pair<Node*, SpellCheckMarker*>>& node_and_marker = |
| 910 GetSpellCheckMarkerTouchingSelection(); | 870 GetSpellCheckMarkerUnderSelection(); |
| 911 if (!node_and_marker) | 871 if (!node_and_marker) |
| 912 return; | 872 return; |
| 913 | 873 |
| 914 Node* const container_node = node_and_marker.value().first; | 874 Node* const container_node = node_and_marker.value().first; |
| 915 const SpellCheckMarker* const marker = node_and_marker.value().second; | 875 const SpellCheckMarker* const marker = node_and_marker.value().second; |
| 916 | 876 |
| 917 GetFrame().Selection().SetSelection( | 877 GetFrame().Selection().SetSelection( |
| 918 SelectionInDOMTree::Builder() | 878 SelectionInDOMTree::Builder() |
| 919 .Collapse(Position(container_node, marker->StartOffset())) | 879 .Collapse(Position(container_node, marker->StartOffset())) |
| 920 .Extend(Position(container_node, marker->EndOffset())) | 880 .Extend(Position(container_node, marker->EndOffset())) |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 if (!input.IsFocusedElementInDocument()) | 1262 if (!input.IsFocusedElementInDocument()) |
| 1303 return false; | 1263 return false; |
| 1304 } | 1264 } |
| 1305 } | 1265 } |
| 1306 HTMLElement* element = | 1266 HTMLElement* element = |
| 1307 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode()); | 1267 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode()); |
| 1308 return element && element->IsSpellCheckingEnabled(); | 1268 return element && element->IsSpellCheckingEnabled(); |
| 1309 } | 1269 } |
| 1310 | 1270 |
| 1311 } // namespace blink | 1271 } // namespace blink |
| OLD | NEW |