2011-04-06 Jia Pu <jpu@apple.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Apr 2011 16:09:28 +0000 (16:09 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Apr 2011 16:09:28 +0000 (16:09 +0000)
        Reviewed by Darin Adler.

        [Mac] WebCore need to notify AppKit spell checker after user has modified autocorrected text.
        https://bugs.webkit.org/show_bug.cgi?id=57665
        <rdar://problem/7350477>

        We need to track how user modified an autocorrected word. If he changed it back to original
        text, we want to record AutocorrectionReverted response. And if he changed it to something
        else, we want to record AutocorrectionEdited response.

        To achieve this, we need to distringuish between text replacement caused by autocorrection
        from that due to other causes, such as reversion, text substitution, etc. So we added a new
        marker type "Autocorrected". We also need to be able to check for correction, even when we
        don't intend to actually carry out replacement. For this, we introduced a new TextCheckingOption
        value, "CheckForCorrection".

        We also added DocumentMarkerController::markersInRange() to retrieve a vector of markers in
        specified range, and of specified type.

        * dom/DocumentMarker.h:
        * dom/DocumentMarkerController.cpp:
        (WebCore::DocumentMarkerController::markersInRange):
        (WebCore::DocumentMarkerController::hasMarkers):
        * dom/DocumentMarkerController.h:
        * editing/Editor.cpp:
        (WebCore::markerTypesForAutocorrection):
        (WebCore::markersHaveIdenticalDescription):
        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
        (WebCore::Editor::recordSpellcheckerResponseForModifiedCorrection):
        (WebCore::Editor::changeBackToReplacedString):
        (WebCore::Editor::markMisspellingsAndBadGrammar):
        (WebCore::Editor::applyCorrectionPanelInfo):
        (WebCore::Editor::unappliedSpellCorrection):
        (WebCore::Editor::textCheckingTypeMaskFor):
        * editing/Editor.h:
        * editing/SpellingCorrectionCommand.cpp:
        (WebCore::SpellingCorrectionCommand::doApply):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83060 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/dom/DocumentMarker.h
Source/WebCore/dom/DocumentMarkerController.cpp
Source/WebCore/dom/DocumentMarkerController.h
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/SpellingCorrectionCommand.cpp

index a342383..f2ea64f 100644 (file)
@@ -1,3 +1,43 @@
+2011-04-06  Jia Pu  <jpu@apple.com>
+
+        Reviewed by Darin Adler.
+
+        [Mac] WebCore need to notify AppKit spell checker after user has modified autocorrected text.
+        https://bugs.webkit.org/show_bug.cgi?id=57665
+        <rdar://problem/7350477>
+
+        We need to track how user modified an autocorrected word. If he changed it back to original
+        text, we want to record AutocorrectionReverted response. And if he changed it to something
+        else, we want to record AutocorrectionEdited response.
+
+        To achieve this, we need to distringuish between text replacement caused by autocorrection
+        from that due to other causes, such as reversion, text substitution, etc. So we added a new
+        marker type "Autocorrected". We also need to be able to check for correction, even when we
+        don't intend to actually carry out replacement. For this, we introduced a new TextCheckingOption
+        value, "CheckForCorrection".
+
+        We also added DocumentMarkerController::markersInRange() to retrieve a vector of markers in
+        specified range, and of specified type.
+
+        * dom/DocumentMarker.h:
+        * dom/DocumentMarkerController.cpp:
+        (WebCore::DocumentMarkerController::markersInRange):
+        (WebCore::DocumentMarkerController::hasMarkers):
+        * dom/DocumentMarkerController.h:
+        * editing/Editor.cpp:
+        (WebCore::markerTypesForAutocorrection):
+        (WebCore::markersHaveIdenticalDescription):
+        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
+        (WebCore::Editor::recordSpellcheckerResponseForModifiedCorrection):
+        (WebCore::Editor::changeBackToReplacedString):
+        (WebCore::Editor::markMisspellingsAndBadGrammar):
+        (WebCore::Editor::applyCorrectionPanelInfo):
+        (WebCore::Editor::unappliedSpellCorrection):
+        (WebCore::Editor::textCheckingTypeMaskFor):
+        * editing/Editor.h:
+        * editing/SpellingCorrectionCommand.cpp:
+        (WebCore::SpellingCorrectionCommand::doApply):
+
 2011-04-06  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r83045.
index 81112bf..29290c3 100644 (file)
@@ -37,9 +37,9 @@ struct DocumentMarker {
         Spelling = 1 << 0,
         Grammar = 1 << 1,
         TextMatch = 1 << 2,
-        // Text has been modified by spell correction. On some platforms, this prevents the text
-        // to be autocorrected again. On post Snow Leopard Mac OS X, if a Replacement marker contains
-        // non-empty description, a reversion UI will be shown.
+        // Text has been modified by spell correction, reversion of spell correction or other type of substitution. 
+        // On some platforms, this prevents the text from being autocorrected again. On post Snow Leopard Mac OS X, 
+        // if a Replacement marker contains non-empty description, a reversion UI will be shown.
         Replacement = 1 << 3,
         // Renderer needs to add underline indicating that the text has been modified by spell
         // correction. Text with Replacement marker doesn't necessarily has CorrectionIndicator
@@ -49,9 +49,11 @@ struct DocumentMarker {
         CorrectionIndicator = 1 << 4,
         // Correction suggestion has been offered, but got rejected by user.
         RejectedCorrection = 1 << 5,
-        // On some platforms, this prevents the text to be spellchecked again.
-        SpellCheckingExemption = 1 << 6,
-        AllMarkers = Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | SpellCheckingExemption
+        // Text has been modified by autocorrection. The description of this marker is the original text before autocorrection.
+        Autocorrected = 1 << 6,
+        // On some platforms, this prevents the text from being spellchecked again.
+        SpellCheckingExemption = 1 << 7,
+        AllMarkers = Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | Autocorrected | SpellCheckingExemption
     };
     MarkerType type;
     typedef unsigned MarkerTypes;
index f646f3c..6c9324a 100644 (file)
@@ -317,6 +317,35 @@ Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node)
     return Vector<DocumentMarker>();
 }
 
+Vector<DocumentMarker> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerType markerType)
+{
+    if (!possiblyHasMarkers(markerType))
+        return Vector<DocumentMarker>();
+
+    Vector<DocumentMarker> foundMarkers;
+
+    Node* startContainer = range->startContainer();
+    ASSERT(startContainer);
+    Node* endContainer = range->endContainer();
+    ASSERT(endContainer);
+
+    Node* pastLastNode = range->pastLastNode();
+    for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
+        Vector<DocumentMarker> markers = markersForNode(node);
+        Vector<DocumentMarker>::const_iterator end = markers.end();
+        for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
+            if (!(markerType & it->type))
+                continue;
+            if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
+                continue;
+            if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
+                continue;
+            foundMarkers.append(*it);
+        }
+    }
+    return foundMarkers;
+}
+
 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
 {
     Vector<IntRect> result;
@@ -602,20 +631,11 @@ bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy
         for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
             if (!(markerTypes & it->type))
                 continue;
-            if (node == startContainer && node == endContainer) {
-                // The range spans only one node.
-                if (it->endOffset > static_cast<unsigned>(range->startOffset()) && it->startOffset < static_cast<unsigned>(range->endOffset()))
-                    return true;
-            } else {
-                if (node == startContainer) {
-                    if (it->endOffset > static_cast<unsigned>(range->startOffset()))
-                        return true;
-                } else if (node == endContainer) {
-                    if (it->startOffset < static_cast<unsigned>(range->endOffset()))
-                        return true;
-                } else
-                    return true;
-            }
+            if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
+                continue;
+            if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
+                continue;
+            return true;
         }
     }
     return false;
index 6fa060a..3d55a5b 100644 (file)
@@ -68,6 +68,7 @@ public:
 
     DocumentMarker* markerContainingPoint(const IntPoint&, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
     Vector<DocumentMarker> markersForNode(Node*);
+    Vector<DocumentMarker> markersInRange(Range*, DocumentMarker::MarkerType);
     Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
     void clearDescriptionOnMarkersIntersectingRange(Range*, DocumentMarker::MarkerTypes);
 
index d8ad42f..90eb825 100644 (file)
@@ -108,6 +108,7 @@ static const Vector<DocumentMarker::MarkerType>& markerTypesForAutocorrection()
         markerTypesForAutoCorrection.append(DocumentMarker::Replacement);
         markerTypesForAutoCorrection.append(DocumentMarker::CorrectionIndicator);
         markerTypesForAutoCorrection.append(DocumentMarker::SpellCheckingExemption);
+        markerTypesForAutoCorrection.append(DocumentMarker::Autocorrected);
     }
     return markerTypesForAutoCorrection;
 }
@@ -122,6 +123,21 @@ static const Vector<DocumentMarker::MarkerType>& markerTypesForReplacement()
     return markerTypesForReplacement;
 }
 
+#if SUPPORT_AUTOCORRECTION_PANEL
+static bool markersHaveIdenticalDescription(const Vector<DocumentMarker>& markers)
+{
+    if (markers.isEmpty())
+        return true;
+
+    const String& description = markers[0].description;
+    for (size_t i = 1; i < markers.size(); ++i) {
+        if (description != markers[i].description)
+            return false;
+    }
+    return true;
+}
+#endif
+
 // When an event handler has moved the selection outside of a text control
 // we should use the target control's selection for this editing operation.
 VisibleSelection Editor::selectionForCommand(Event* event)
@@ -2212,6 +2228,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
     bool shouldMarkGrammar = textCheckingOptions & MarkGrammar;
     bool shouldPerformReplacement = textCheckingOptions & PerformReplacement;
     bool shouldShowCorrectionPanel = textCheckingOptions & ShowCorrectionPanel;
+    bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & CheckForCorrection);
 
     // This function is called with selections already expanded to word boundaries.
     ExceptionCode ec = 0;
@@ -2239,7 +2256,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
     if (shouldMarkGrammar ? (spellingParagraph.isRangeEmpty() && grammarParagraph.isEmpty()) : spellingParagraph.isEmpty())
         return;
 
-    if (shouldPerformReplacement || shouldMarkSpelling) {
+    if (shouldPerformReplacement || shouldMarkSpelling || shouldCheckForCorrection) {
         if (m_frame->selection()->selectionType() == VisibleSelection::CaretSelection) {
             // Attempt to save the caret position so we can restore it later if needed
             Position caretPosition = m_frame->selection()->end();
@@ -2302,7 +2319,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
                     grammarRange->startContainer(ec)->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription);
                 }
             }
-        } else if ((shouldPerformReplacement || shouldShowCorrectionPanel) && resultLocation + resultLength <= spellingRangeEndOffset && resultLocation + resultLength >= spellingParagraph.checkingStart()
+        } else if (resultLocation + resultLength <= spellingRangeEndOffset && resultLocation + resultLength >= spellingParagraph.checkingStart()
                     && (result->type == TextCheckingTypeLink
                     || result->type == TextCheckingTypeQuote
                     || result->type == TextCheckingTypeDash
@@ -2328,25 +2345,20 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
             if (result->type == TextCheckingTypeLink && selectionOffset > resultLocation + resultLength + 1)
                 continue;
 
+            String replacedString;
+
             // Don't correct spelling in an already-corrected word.
             if (result->type == TextCheckingTypeCorrection) {
-                Node* node = rangeToReplace->startContainer();
-                int startOffset = rangeToReplace->startOffset();
-                int endOffset = startOffset + replacementLength;
-                Vector<DocumentMarker> markers = node->document()->markers()->markersForNode(node);
-                size_t markerCount = markers.size();
-                for (size_t i = 0; i < markerCount; ++i) {
-                    const DocumentMarker& marker = markers[i];
-                    if ((marker.type == DocumentMarker::Replacement || marker.type == DocumentMarker::RejectedCorrection) && static_cast<int>(marker.startOffset) < endOffset && static_cast<int>(marker.endOffset) > startOffset) {
-                        doReplacement = false;
-                        break;
-                    }
-                    if (static_cast<int>(marker.startOffset) >= endOffset)
-                        break;
-                }
+                replacedString = plainText(rangeToReplace.get());
+                DocumentMarkerController* markers = m_frame->document()->markers();
+                if (markers->hasMarkers(rangeToReplace.get(), DocumentMarker::Replacement)) {
+                    doReplacement = false;
+                    recordSpellcheckerResponseForModifiedCorrection(rangeToReplace.get(), replacedString, result->replacement);
+                } else if (markers->hasMarkers(rangeToReplace.get(), DocumentMarker::RejectedCorrection))
+                    doReplacement = false;
             }
 
-            if (!doReplacement)
+            if (!(shouldPerformReplacement || shouldShowCorrectionPanel) || !doReplacement)
                 continue;
 
 #if SUPPORT_AUTOCORRECTION_PANEL
@@ -2380,10 +2392,6 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
                 if (canEditRichly())
                     applyCommand(CreateLinkCommand::create(m_frame->document(), result->replacement));
             } else if (canEdit() && shouldInsertText(result->replacement, rangeToReplace.get(), EditorInsertActionTyped)) {
-                String replacedString;
-                if (result->type == TextCheckingTypeCorrection)
-                    replacedString = plainText(rangeToReplace.get());
-
                 bool useSpellingCorrectionCommand = false;
 #if SUPPORT_AUTOCORRECTION_PANEL
                 if (result->type == TextCheckingTypeCorrection)
@@ -2412,9 +2420,15 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
                 if (result->type == TextCheckingTypeCorrection) {
                     // Add a marker so that corrections can easily be undone and won't be re-corrected.
                     RefPtr<Range> replacedRange = spellingParagraph.subrange(resultLocation, replacementLength);
-                    replacedRange->startContainer()->document()->markers()->addMarker(replacedRange.get(), DocumentMarker::Replacement, replacedString);
-                    replacedRange->startContainer()->document()->markers()->addMarker(replacedRange.get(), DocumentMarker::CorrectionIndicator);
-                    replacedRange->startContainer()->document()->markers()->addMarker(replacedRange.get(), DocumentMarker::SpellCheckingExemption);
+                    Vector<DocumentMarker::MarkerType> markerTypesToAdd = markerTypesForAutocorrection();
+                    DocumentMarkerController* markers = replacedRange->startContainer()->document()->markers();
+                    for (size_t i = 0; i < markerTypesToAdd.size(); ++i) {
+                        DocumentMarker::MarkerType markerType = markerTypesToAdd[i];
+                        if (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected)
+                            markers->addMarker(replacedRange.get(), markerType, replacedString);
+                        else
+                            markers->addMarker(replacedRange.get(), markerType);
+                    }
                 }
             }
         }
@@ -2442,6 +2456,30 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
 #endif // USE(UNIFIED_TEXT_CHECKING)
 }
 
+void Editor::recordSpellcheckerResponseForModifiedCorrection(Range* rangeOfCorrection, const String& corrected, const String& correction)
+{
+#if SUPPORT_AUTOCORRECTION_PANEL
+    if (!rangeOfCorrection)
+        return;
+    DocumentMarkerController* markers = rangeOfCorrection->startContainer()->document()->markers();
+    Vector<DocumentMarker> correctedOnceMarkers = markers->markersInRange(rangeOfCorrection, DocumentMarker::Autocorrected);
+    if (correctedOnceMarkers.isEmpty())
+        return;
+    
+    // Spelling corrected text has been edited. We need to determine whether user has reverted it to original text or
+    // edited it to something else, and notify spellchecker accordingly.
+    if (markersHaveIdenticalDescription(correctedOnceMarkers) && correctedOnceMarkers[0].description == corrected)
+        client()->recordAutocorrectionResponse(EditorClient::AutocorrectionReverted, corrected, correction);
+    else
+        client()->recordAutocorrectionResponse(EditorClient::AutocorrectionEdited, corrected, correction);
+    markers->removeMarkers(rangeOfCorrection, DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
+#else
+    UNUSED_PARAM(rangeOfCorrection);
+    UNUSED_PARAM(corrected);
+    UNUSED_PARAM(correction);
+#endif
+}
+
 void Editor::changeBackToReplacedString(const String& replacedString)
 {
 #if USE(UNIFIED_TEXT_CHECKING)
@@ -2461,6 +2499,7 @@ void Editor::changeBackToReplacedString(const String& replacedString)
     RefPtr<Range> changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
     changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::Replacement, String());
 #if SUPPORT_AUTOCORRECTION_PANEL
+    changedRange->startContainer()->document()->markers()->removeMarkers(changedRange.get(), DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
     changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::SpellCheckingExemption);
 #endif
 #else
@@ -2475,7 +2514,7 @@ void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelec
 #if USE(UNIFIED_TEXT_CHECKING)
     if (!isContinuousSpellCheckingEnabled())
         return;
-    TextCheckingOptions textCheckingOptions = MarkSpelling;
+    TextCheckingOptions textCheckingOptions = MarkSpelling | CheckForCorrection;
     if (markGrammar && isGrammarCheckingEnabled())
         textCheckingOptions |= MarkGrammar;
     markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedRange().get(), grammarSelection.toNormalizedRange().get());
@@ -2732,10 +2771,11 @@ void Editor::applyCorrectionPanelInfo(const Vector<DocumentMarker::MarkerType>&
     DocumentMarkerController* markers = replacementRange->startContainer()->document()->markers();
     size_t size = markerTypesToAdd.size();
     for (size_t i = 0; i < size; ++i) {
-        if (m_correctionPanelInfo.panelType == CorrectionPanelInfo::PanelTypeReversion)
-            markers->addMarker(replacementRange.get(), markerTypesToAdd[i]);
-        else
-            markers->addMarker(replacementRange.get(), markerTypesToAdd[i], m_correctionPanelInfo.replacedString);
+        DocumentMarker::MarkerType markerType = markerTypesToAdd[i];
+        String description;
+        if (m_correctionPanelInfo.panelType != CorrectionPanelInfo::PanelTypeReversion && (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected))
+            description = m_correctionPanelInfo.replacedString;
+        markers->addMarker(replacementRange.get(), markerType, description);
     }
 #else // SUPPORT_AUTOCORRECTION_PANEL
     UNUSED_PARAM(markerTypesToAdd);
@@ -2772,7 +2812,7 @@ void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrect
     RefPtr<Range> range = Range::create(m_frame->document(), m_frame->selection()->selection().start(), m_frame->selection()->selection().end());
 
     DocumentMarkerController* markers = m_frame->document()->markers();
-    markers->removeMarkers(range.get(), DocumentMarker::Spelling);
+    markers->removeMarkers(range.get(), DocumentMarker::Spelling | DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
     markers->addMarker(range.get(), DocumentMarker::Replacement);
     markers->addMarker(range.get(), DocumentMarker::SpellCheckingExemption);
 #else // SUPPORT_AUTOCORRECTION_PANEL
@@ -3594,13 +3634,14 @@ TextCheckingTypeMask Editor::textCheckingTypeMaskFor(TextCheckingOptions textChe
     bool shouldMarkSpelling = textCheckingOptions & MarkSpelling;
     bool shouldMarkGrammar = textCheckingOptions & MarkGrammar;
     bool shouldShowCorrectionPanel = textCheckingOptions & ShowCorrectionPanel;
+    bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & CheckForCorrection);
 
     TextCheckingTypeMask checkingTypes = 0;
     if (shouldMarkSpelling)
         checkingTypes |= TextCheckingTypeSpelling;
     if (shouldMarkGrammar)
         checkingTypes |= TextCheckingTypeGrammar;
-    if (shouldShowCorrectionPanel)
+    if (shouldCheckForCorrection)
         checkingTypes |= TextCheckingTypeCorrection;
 
 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
index 7745351..f9aec40 100644 (file)
@@ -229,6 +229,7 @@ public:
         MarkGrammar = 1 << 1,
         PerformReplacement = 1 << 2,
         ShowCorrectionPanel = 1 << 3,
+        CheckForCorrection = 1 << 4,
     };
     typedef unsigned TextCheckingOptions;
 
@@ -416,6 +417,7 @@ private:
     void revealSelectionAfterEditingOperation();
     void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
     TextCheckingTypeMask textCheckingTypeMaskFor(TextCheckingOptions);
+    void recordSpellcheckerResponseForModifiedCorrection(Range*, const String& corrected, const String& correction);
 
     void selectComposition();
     void confirmComposition(const String&, bool preserveSelection);
index bad4a99..afe74a8 100644 (file)
@@ -94,7 +94,7 @@ void SpellingCorrectionCommand::doApply()
     if (!fragment)
         return;
 
-    applyCommandToComposite(SetSelectionCommand::create(m_selectionToBeCorrected, SelectionController::CloseTyping | SelectionController::ClearTypingStyle));
+    applyCommandToComposite(SetSelectionCommand::create(m_selectionToBeCorrected, SelectionController::SpellCorrectionTriggered | SelectionController::CloseTyping | SelectionController::ClearTypingStyle));
 #if SUPPORT_AUTOCORRECTION_PANEL
     applyCommandToComposite(SpellingCorrectionRecordUndoCommand::create(document(), m_corrected, m_correction));
 #endif