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 |