| 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 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 DCHECK(frame().selection().isAvailable()); | 663 DCHECK(frame().selection().isAvailable()); |
| 664 TRACE_EVENT0("blink", "SpellChecker::updateMarkersForWordsAffectedByEditing"); | 664 TRACE_EVENT0("blink", "SpellChecker::updateMarkersForWordsAffectedByEditing"); |
| 665 // TODO(editing-dev): We should hoist | 665 // TODO(editing-dev): We should hoist |
| 666 // updateStyleAndLayoutIgnorePendingStylesheets to caller. See | 666 // updateStyleAndLayoutIgnorePendingStylesheets to caller. See |
| 667 // http://crbug.com/590369 for more details. | 667 // http://crbug.com/590369 for more details. |
| 668 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 668 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 669 if (!isSpellCheckingEnabledFor( | 669 if (!isSpellCheckingEnabledFor( |
| 670 frame().selection().computeVisibleSelectionInDOMTree())) | 670 frame().selection().computeVisibleSelectionInDOMTree())) |
| 671 return; | 671 return; |
| 672 | 672 |
| 673 Document* document = frame().document(); | 673 frame().document()->markers().removeMarkersForWordsAffectedByEditing( |
| 674 DCHECK(document); | 674 DocumentMarker::MisspellingMarkers(), |
| 675 | 675 doNotRemoveIfSelectionAtWordBoundary); |
| 676 // We want to remove the markers from a word if an editing command will change | |
| 677 // the word. This can happen in one of several scenarios: | |
| 678 // 1. Insert in the middle of a word. | |
| 679 // 2. Appending non whitespace at the beginning of word. | |
| 680 // 3. Appending non whitespace at the end of word. | |
| 681 // Note that, appending only whitespaces at the beginning or end of word won't | |
| 682 // change the word, so we don't need to remove the markers on that word. Of | |
| 683 // course, if current selection is a range, we potentially will edit two words | |
| 684 // that fall on the boundaries of selection, and remove words between the | |
| 685 // selection boundaries. | |
| 686 VisiblePosition startOfSelection = | |
| 687 frame().selection().computeVisibleSelectionInDOMTree().visibleStart(); | |
| 688 VisiblePosition endOfSelection = | |
| 689 frame().selection().computeVisibleSelectionInDOMTree().visibleEnd(); | |
| 690 if (startOfSelection.isNull()) | |
| 691 return; | |
| 692 // First word is the word that ends after or on the start of selection. | |
| 693 VisiblePosition startOfFirstWord = | |
| 694 startOfWord(startOfSelection, LeftWordIfOnBoundary); | |
| 695 VisiblePosition endOfFirstWord = | |
| 696 endOfWord(startOfSelection, LeftWordIfOnBoundary); | |
| 697 // Last word is the word that begins before or on the end of selection | |
| 698 VisiblePosition startOfLastWord = | |
| 699 startOfWord(endOfSelection, RightWordIfOnBoundary); | |
| 700 VisiblePosition endOfLastWord = | |
| 701 endOfWord(endOfSelection, RightWordIfOnBoundary); | |
| 702 | |
| 703 if (startOfFirstWord.isNull()) { | |
| 704 startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary); | |
| 705 endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary); | |
| 706 } | |
| 707 | |
| 708 if (endOfLastWord.isNull()) { | |
| 709 startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary); | |
| 710 endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary); | |
| 711 } | |
| 712 | |
| 713 // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the | |
| 714 // start of selection, we choose next word as the first word. | |
| 715 if (doNotRemoveIfSelectionAtWordBoundary && | |
| 716 endOfFirstWord.deepEquivalent() == startOfSelection.deepEquivalent()) { | |
| 717 startOfFirstWord = nextWordPosition(startOfFirstWord); | |
| 718 endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary); | |
| 719 if (startOfFirstWord.deepEquivalent() == endOfSelection.deepEquivalent()) | |
| 720 return; | |
| 721 } | |
| 722 | |
| 723 // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at | |
| 724 // the end of selection, we choose previous word as the last word. | |
| 725 if (doNotRemoveIfSelectionAtWordBoundary && | |
| 726 startOfLastWord.deepEquivalent() == endOfSelection.deepEquivalent()) { | |
| 727 startOfLastWord = previousWordPosition(startOfLastWord); | |
| 728 endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary); | |
| 729 if (endOfLastWord.deepEquivalent() == startOfSelection.deepEquivalent()) | |
| 730 return; | |
| 731 } | |
| 732 | |
| 733 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || | |
| 734 startOfLastWord.isNull() || endOfLastWord.isNull()) | |
| 735 return; | |
| 736 | |
| 737 const Position& removeMarkerStart = startOfFirstWord.deepEquivalent(); | |
| 738 const Position& removeMarkerEnd = endOfLastWord.deepEquivalent(); | |
| 739 if (removeMarkerStart > removeMarkerEnd) { | |
| 740 // editing/inserting/insert-br-008.html and more reach here. | |
| 741 // TODO(yosin): To avoid |DCHECK(removeMarkerStart <= removeMarkerEnd)| | |
| 742 // in |EphemeralRange| constructor, we have this if-statement. Once we | |
| 743 // fix |startOfWord()| and |endOfWord()|, we should remove this | |
| 744 // if-statement. | |
| 745 return; | |
| 746 } | |
| 747 | |
| 748 // Now we remove markers on everything between startOfFirstWord and | |
| 749 // endOfLastWord. However, if an autocorrection change a single word to | |
| 750 // multiple words, we want to remove correction mark from all the resulted | |
| 751 // words even we only edit one of them. For example, assuming autocorrection | |
| 752 // changes "avantgarde" to "avant garde", we will have CorrectionIndicator | |
| 753 // marker on both words and on the whitespace between them. If we then edit | |
| 754 // garde, we would like to remove the marker from word "avant" and whitespace | |
| 755 // as well. So we need to get the continous range of of marker that contains | |
| 756 // the word in question, and remove marker on that whole range. | |
| 757 const EphemeralRange wordRange(removeMarkerStart, removeMarkerEnd); | |
| 758 document->markers().removeMarkers( | |
| 759 wordRange, DocumentMarker::MisspellingMarkers(), | |
| 760 DocumentMarkerController::RemovePartiallyOverlappingMarker); | |
| 761 } | 676 } |
| 762 | 677 |
| 763 void SpellChecker::didEndEditingOnTextField(Element* e) { | 678 void SpellChecker::didEndEditingOnTextField(Element* e) { |
| 764 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); | 679 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); |
| 765 | 680 |
| 766 // Remove markers when deactivating a selection in an <input type="text"/>. | 681 // Remove markers when deactivating a selection in an <input type="text"/>. |
| 767 // Prevent new ones from appearing too. | 682 // Prevent new ones from appearing too. |
| 768 if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) | 683 if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) |
| 769 m_spellCheckRequester->cancelCheck(); | 684 m_spellCheckRequester->cancelCheck(); |
| 770 TextControlElement* textControlElement = toTextControlElement(e); | 685 TextControlElement* textControlElement = toTextControlElement(e); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 if (!input.isFocusedElementInDocument()) | 1095 if (!input.isFocusedElementInDocument()) |
| 1181 return false; | 1096 return false; |
| 1182 } | 1097 } |
| 1183 } | 1098 } |
| 1184 HTMLElement* element = | 1099 HTMLElement* element = |
| 1185 Traversal<HTMLElement>::firstAncestorOrSelf(*position.anchorNode()); | 1100 Traversal<HTMLElement>::firstAncestorOrSelf(*position.anchorNode()); |
| 1186 return element && element->isSpellCheckingEnabled(); | 1101 return element && element->isSpellCheckingEnabled(); |
| 1187 } | 1102 } |
| 1188 | 1103 |
| 1189 } // namespace blink | 1104 } // namespace blink |
| OLD | NEW |