| 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 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 } | 695 } |
| 696 } | 696 } |
| 697 | 697 |
| 698 void SpellChecker::updateMarkersForWordsAffectedByEditing( | 698 void SpellChecker::updateMarkersForWordsAffectedByEditing( |
| 699 bool doNotRemoveIfSelectionAtWordBoundary) { | 699 bool doNotRemoveIfSelectionAtWordBoundary) { |
| 700 DCHECK(frame().selection().isAvailable()); | 700 DCHECK(frame().selection().isAvailable()); |
| 701 TRACE_EVENT0("blink", "SpellChecker::updateMarkersForWordsAffectedByEditing"); | 701 TRACE_EVENT0("blink", "SpellChecker::updateMarkersForWordsAffectedByEditing"); |
| 702 if (!isSpellCheckingEnabledFor(frame().selection().selection())) | 702 if (!isSpellCheckingEnabledFor(frame().selection().selection())) |
| 703 return; | 703 return; |
| 704 | 704 |
| 705 Document* document = frame().document(); | 705 frame().document()->markers().removeMarkersForWordsAffectedByEditing( |
| 706 DCHECK(document); | 706 DocumentMarker::MisspellingMarkers(), |
| 707 | 707 doNotRemoveIfSelectionAtWordBoundary); |
| 708 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | |
| 709 // needs to be audited. See http://crbug.com/590369 for more details. | |
| 710 document->updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 711 | |
| 712 // We want to remove the markers from a word if an editing command will change | |
| 713 // the word. This can happen in one of several scenarios: | |
| 714 // 1. Insert in the middle of a word. | |
| 715 // 2. Appending non whitespace at the beginning of word. | |
| 716 // 3. Appending non whitespace at the end of word. | |
| 717 // Note that, appending only whitespaces at the beginning or end of word won't | |
| 718 // change the word, so we don't need to remove the markers on that word. Of | |
| 719 // course, if current selection is a range, we potentially will edit two words | |
| 720 // that fall on the boundaries of selection, and remove words between the | |
| 721 // selection boundaries. | |
| 722 VisiblePosition startOfSelection = | |
| 723 frame().selection().selection().visibleStart(); | |
| 724 VisiblePosition endOfSelection = frame().selection().selection().visibleEnd(); | |
| 725 if (startOfSelection.isNull()) | |
| 726 return; | |
| 727 // First word is the word that ends after or on the start of selection. | |
| 728 VisiblePosition startOfFirstWord = | |
| 729 startOfWord(startOfSelection, LeftWordIfOnBoundary); | |
| 730 VisiblePosition endOfFirstWord = | |
| 731 endOfWord(startOfSelection, LeftWordIfOnBoundary); | |
| 732 // Last word is the word that begins before or on the end of selection | |
| 733 VisiblePosition startOfLastWord = | |
| 734 startOfWord(endOfSelection, RightWordIfOnBoundary); | |
| 735 VisiblePosition endOfLastWord = | |
| 736 endOfWord(endOfSelection, RightWordIfOnBoundary); | |
| 737 | |
| 738 if (startOfFirstWord.isNull()) { | |
| 739 startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary); | |
| 740 endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary); | |
| 741 } | |
| 742 | |
| 743 if (endOfLastWord.isNull()) { | |
| 744 startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary); | |
| 745 endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary); | |
| 746 } | |
| 747 | |
| 748 // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the | |
| 749 // start of selection, we choose next word as the first word. | |
| 750 if (doNotRemoveIfSelectionAtWordBoundary && | |
| 751 endOfFirstWord.deepEquivalent() == startOfSelection.deepEquivalent()) { | |
| 752 startOfFirstWord = nextWordPosition(startOfFirstWord); | |
| 753 endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary); | |
| 754 if (startOfFirstWord.deepEquivalent() == endOfSelection.deepEquivalent()) | |
| 755 return; | |
| 756 } | |
| 757 | |
| 758 // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at | |
| 759 // the end of selection, we choose previous word as the last word. | |
| 760 if (doNotRemoveIfSelectionAtWordBoundary && | |
| 761 startOfLastWord.deepEquivalent() == endOfSelection.deepEquivalent()) { | |
| 762 startOfLastWord = previousWordPosition(startOfLastWord); | |
| 763 endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary); | |
| 764 if (endOfLastWord.deepEquivalent() == startOfSelection.deepEquivalent()) | |
| 765 return; | |
| 766 } | |
| 767 | |
| 768 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || | |
| 769 startOfLastWord.isNull() || endOfLastWord.isNull()) | |
| 770 return; | |
| 771 | |
| 772 const Position& removeMarkerStart = startOfFirstWord.deepEquivalent(); | |
| 773 const Position& removeMarkerEnd = endOfLastWord.deepEquivalent(); | |
| 774 if (removeMarkerStart > removeMarkerEnd) { | |
| 775 // editing/inserting/insert-br-008.html and more reach here. | |
| 776 // TODO(yosin): To avoid |DCHECK(removeMarkerStart <= removeMarkerEnd)| | |
| 777 // in |EphemeralRange| constructor, we have this if-statement. Once we | |
| 778 // fix |startOfWord()| and |endOfWord()|, we should remove this | |
| 779 // if-statement. | |
| 780 return; | |
| 781 } | |
| 782 | |
| 783 // Now we remove markers on everything between startOfFirstWord and | |
| 784 // endOfLastWord. However, if an autocorrection change a single word to | |
| 785 // multiple words, we want to remove correction mark from all the resulted | |
| 786 // words even we only edit one of them. For example, assuming autocorrection | |
| 787 // changes "avantgarde" to "avant garde", we will have CorrectionIndicator | |
| 788 // marker on both words and on the whitespace between them. If we then edit | |
| 789 // garde, we would like to remove the marker from word "avant" and whitespace | |
| 790 // as well. So we need to get the continous range of of marker that contains | |
| 791 // the word in question, and remove marker on that whole range. | |
| 792 const EphemeralRange wordRange(removeMarkerStart, removeMarkerEnd); | |
| 793 document->markers().removeMarkers( | |
| 794 wordRange, DocumentMarker::MisspellingMarkers(), | |
| 795 DocumentMarkerController::RemovePartiallyOverlappingMarker); | |
| 796 } | 708 } |
| 797 | 709 |
| 798 void SpellChecker::didEndEditingOnTextField(Element* e) { | 710 void SpellChecker::didEndEditingOnTextField(Element* e) { |
| 799 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); | 711 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); |
| 800 | 712 |
| 801 // Remove markers when deactivating a selection in an <input type="text"/>. | 713 // Remove markers when deactivating a selection in an <input type="text"/>. |
| 802 // Prevent new ones from appearing too. | 714 // Prevent new ones from appearing too. |
| 803 if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) | 715 if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled()) |
| 804 m_spellCheckRequester->cancelCheck(); | 716 m_spellCheckRequester->cancelCheck(); |
| 805 TextControlElement* textControlElement = toTextControlElement(e); | 717 TextControlElement* textControlElement = toTextControlElement(e); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 startOfNextParagraph(createVisiblePosition(paragraphEnd)); | 1081 startOfNextParagraph(createVisiblePosition(paragraphEnd)); |
| 1170 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | 1082 paragraphStart = newParagraphStart.toParentAnchoredPosition(); |
| 1171 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPosition(); | 1083 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPosition(); |
| 1172 firstIteration = false; | 1084 firstIteration = false; |
| 1173 totalLengthProcessed += currentLength; | 1085 totalLengthProcessed += currentLength; |
| 1174 } | 1086 } |
| 1175 return std::make_pair(firstFoundItem, firstFoundOffset); | 1087 return std::make_pair(firstFoundItem, firstFoundOffset); |
| 1176 } | 1088 } |
| 1177 | 1089 |
| 1178 } // namespace blink | 1090 } // namespace blink |
| OLD | NEW |