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 |