Changeset 83344 in webkit


Ignore:
Timestamp:
Apr 8, 2011 2:21:44 PM (13 years ago)
Author:
morrita@google.com
Message:

2011-04-06 MORITA Hajime <morrita@google.com>

Reviewed by Darin Adler.

[Refactoring] Auto correction panel should be handled by its own class.
https://bugs.webkit.org/show_bug.cgi?id=55571

Extracted code inside SUPPORT_AUTOCORRECTION_PANEL into
SpellingCorrectionController class.
This change also remove some SUPPORT_AUTOCORRECTION_PANEL guard if
code paths inside the never reached without autocorrection support.
Removing guards reduces unintentional build breakage.

No new tests, no behavior chagne.

  • CMakeLists.txt:
  • GNUmakefile.am:
  • WebCore.gypi:
  • WebCore.pro:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • editing/CorrectionPanelInfo.h: Removed.
  • editing/EditingAllInOne.cpp:
  • editing/Editor.cpp: (WebCore::Editor::respondToChangedSelection): (WebCore::Editor::respondToChangedContents): (WebCore::Editor::appliedEditing): (WebCore::Editor::Editor): (WebCore::Editor::~Editor): (WebCore::Editor::insertTextWithoutSendingTextEvent): (WebCore::Editor::insertLineBreak): (WebCore::Editor::insertParagraphSeparator): (WebCore::Editor::cut): (WebCore::Editor::paste): (WebCore::Editor::pasteAsPlainText): (WebCore::Editor::isAutomaticSpellingCorrectionEnabled): (WebCore::Editor::markMisspellingsAfterTypingToWord): (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges): (WebCore::Editor::changeBackToReplacedString): (WebCore::Editor::unappliedSpellCorrection): (WebCore::Editor::updateMarkersForWordsAffectedByEditing): (WebCore::Editor::startCorrectionPanelTimer): (WebCore::Editor::handleCorrectionPanelResult): (WebCore::Editor::dismissCorrectionPanelAsIgnored):
  • editing/Editor.h:
  • editing/SpellingCorrectionCommand.cpp:
  • editing/SpellingCorrectionController.cpp: Added. (WebCore::markerTypesForAutocorrection): (WebCore::markerTypesForReplacement): (WebCore::markersHaveIdenticalDescription): (WebCore::SpellingCorrectionController::SpellingCorrectionController): (WebCore::SpellingCorrectionController::~SpellingCorrectionController): (WebCore::SpellingCorrectionController::startCorrectionPanelTimer): (WebCore::SpellingCorrectionController::stopCorrectionPanelTimer): (WebCore::SpellingCorrectionController::stopPendingCorrection): (WebCore::SpellingCorrectionController::applyPendingCorrection): (WebCore::SpellingCorrectionController::hasPendingCorrection): (WebCore::SpellingCorrectionController::isSpellingMarkerAllowed): (WebCore::SpellingCorrectionController::show): (WebCore::SpellingCorrectionController::handleCancelOperation): (WebCore::SpellingCorrectionController::dismiss): (WebCore::SpellingCorrectionController::dismissSoon): (WebCore::SpellingCorrectionController::applyCorrectionPanelInfo): (WebCore::SpellingCorrectionController::applyAutocorrectionBeforeTypingIfAppropriate): (WebCore::SpellingCorrectionController::respondToUnappliedSpellCorrection): (WebCore::SpellingCorrectionController::correctionPanelTimerFired): (WebCore::SpellingCorrectionController::handleCorrectionPanelResult): (WebCore::SpellingCorrectionController::isAutomaticSpellingCorrectionEnabled): (WebCore::SpellingCorrectionController::windowRectForRange): (WebCore::SpellingCorrectionController::respondToChangedSelection): (WebCore::SpellingCorrectionController::respondToAppliedEditing): (WebCore::SpellingCorrectionController::client): (WebCore::SpellingCorrectionController::textChecker): (WebCore::SpellingCorrectionController::recordAutocorrectionResponseReversed): (WebCore::SpellingCorrectionController::markReversed): (WebCore::SpellingCorrectionController::markCorrection): (WebCore::SpellingCorrectionController::recordSpellcheckerResponseForModifiedCorrection):
  • editing/SpellingCorrectionController.h: Added. (WebCore::SpellingCorrectionController::UNLESS_ENABLED): (WebCore::SpellingCorrectionController::shouldStartTimeFor): (WebCore::SpellingCorrectionController::shouldRemoveMarkersUponEditing):
  • editing/TypingCommand.cpp: (WebCore::TypingCommand::insertText): (WebCore::TypingCommand::markMisspellingsAfterTyping): (WebCore::TypingCommand::deleteKeyPressed): (WebCore::TypingCommand::forwardDeleteKeyPressed):
  • editing/htmlediting.h: (WebCore::isAmbiguousBoundaryCharacter):
  • page/EditorClient.h:
  • page/Frame.cpp: (WebCore::Frame::setPageAndTextZoomFactors):
Location:
trunk/Source
Files:
2 added
1 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/CMakeLists.txt

    r83342 r83344  
    675675    editing/SmartReplace.cpp
    676676    editing/SpellChecker.cpp
     677    editing/SpellingCorrectionController.cpp
    677678    editing/SplitElementCommand.cpp
    678679    editing/SplitTextNodeCommand.cpp
  • trunk/Source/WebCore/ChangeLog

    r83342 r83344  
     12011-04-06  MORITA Hajime  <morrita@google.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        [Refactoring] Auto correction panel should be handled by its own class.
     6        https://bugs.webkit.org/show_bug.cgi?id=55571
     7
     8        Extracted code inside SUPPORT_AUTOCORRECTION_PANEL into
     9        SpellingCorrectionController class.
     10        This change also remove some SUPPORT_AUTOCORRECTION_PANEL guard if
     11        code paths inside the never reached without autocorrection support.
     12        Removing guards reduces unintentional build breakage.
     13
     14        No new tests, no behavior chagne.
     15
     16        * CMakeLists.txt:
     17        * GNUmakefile.am:
     18        * WebCore.gypi:
     19        * WebCore.pro:
     20        * WebCore.vcproj/WebCore.vcproj:
     21        * WebCore.xcodeproj/project.pbxproj:
     22        * editing/CorrectionPanelInfo.h: Removed.
     23        * editing/EditingAllInOne.cpp:
     24        * editing/Editor.cpp:
     25        (WebCore::Editor::respondToChangedSelection):
     26        (WebCore::Editor::respondToChangedContents):
     27        (WebCore::Editor::appliedEditing):
     28        (WebCore::Editor::Editor):
     29        (WebCore::Editor::~Editor):
     30        (WebCore::Editor::insertTextWithoutSendingTextEvent):
     31        (WebCore::Editor::insertLineBreak):
     32        (WebCore::Editor::insertParagraphSeparator):
     33        (WebCore::Editor::cut):
     34        (WebCore::Editor::paste):
     35        (WebCore::Editor::pasteAsPlainText):
     36        (WebCore::Editor::isAutomaticSpellingCorrectionEnabled):
     37        (WebCore::Editor::markMisspellingsAfterTypingToWord):
     38        (WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges):
     39        (WebCore::Editor::changeBackToReplacedString):
     40        (WebCore::Editor::unappliedSpellCorrection):
     41        (WebCore::Editor::updateMarkersForWordsAffectedByEditing):
     42        (WebCore::Editor::startCorrectionPanelTimer):
     43        (WebCore::Editor::handleCorrectionPanelResult):
     44        (WebCore::Editor::dismissCorrectionPanelAsIgnored):
     45        * editing/Editor.h:
     46        * editing/SpellingCorrectionCommand.cpp:
     47        * editing/SpellingCorrectionController.cpp: Added.
     48        (WebCore::markerTypesForAutocorrection):
     49        (WebCore::markerTypesForReplacement):
     50        (WebCore::markersHaveIdenticalDescription):
     51        (WebCore::SpellingCorrectionController::SpellingCorrectionController):
     52        (WebCore::SpellingCorrectionController::~SpellingCorrectionController):
     53        (WebCore::SpellingCorrectionController::startCorrectionPanelTimer):
     54        (WebCore::SpellingCorrectionController::stopCorrectionPanelTimer):
     55        (WebCore::SpellingCorrectionController::stopPendingCorrection):
     56        (WebCore::SpellingCorrectionController::applyPendingCorrection):
     57        (WebCore::SpellingCorrectionController::hasPendingCorrection):
     58        (WebCore::SpellingCorrectionController::isSpellingMarkerAllowed):
     59        (WebCore::SpellingCorrectionController::show):
     60        (WebCore::SpellingCorrectionController::handleCancelOperation):
     61        (WebCore::SpellingCorrectionController::dismiss):
     62        (WebCore::SpellingCorrectionController::dismissSoon):
     63        (WebCore::SpellingCorrectionController::applyCorrectionPanelInfo):
     64        (WebCore::SpellingCorrectionController::applyAutocorrectionBeforeTypingIfAppropriate):
     65        (WebCore::SpellingCorrectionController::respondToUnappliedSpellCorrection):
     66        (WebCore::SpellingCorrectionController::correctionPanelTimerFired):
     67        (WebCore::SpellingCorrectionController::handleCorrectionPanelResult):
     68        (WebCore::SpellingCorrectionController::isAutomaticSpellingCorrectionEnabled):
     69        (WebCore::SpellingCorrectionController::windowRectForRange):
     70        (WebCore::SpellingCorrectionController::respondToChangedSelection):
     71        (WebCore::SpellingCorrectionController::respondToAppliedEditing):
     72        (WebCore::SpellingCorrectionController::client):
     73        (WebCore::SpellingCorrectionController::textChecker):
     74        (WebCore::SpellingCorrectionController::recordAutocorrectionResponseReversed):
     75        (WebCore::SpellingCorrectionController::markReversed):
     76        (WebCore::SpellingCorrectionController::markCorrection):
     77        (WebCore::SpellingCorrectionController::recordSpellcheckerResponseForModifiedCorrection):
     78        * editing/SpellingCorrectionController.h: Added.
     79        (WebCore::SpellingCorrectionController::UNLESS_ENABLED):
     80        (WebCore::SpellingCorrectionController::shouldStartTimeFor):
     81        (WebCore::SpellingCorrectionController::shouldRemoveMarkersUponEditing):       
     82        * editing/TypingCommand.cpp:
     83        (WebCore::TypingCommand::insertText):
     84        (WebCore::TypingCommand::markMisspellingsAfterTyping):
     85        (WebCore::TypingCommand::deleteKeyPressed):
     86        (WebCore::TypingCommand::forwardDeleteKeyPressed):
     87        * editing/htmlediting.h:
     88        (WebCore::isAmbiguousBoundaryCharacter):
     89        * page/EditorClient.h:
     90        * page/Frame.cpp:
     91        (WebCore::Frame::setPageAndTextZoomFactors):
     92
    1932011-04-08  Alpha Lam  <hclam@chromium.org>
    294
  • trunk/Source/WebCore/GNUmakefile.list.am

    r83287 r83344  
    13831383        Source/WebCore/editing/SpellChecker.cpp \
    13841384        Source/WebCore/editing/SpellChecker.h \
     1385        Source/WebCore/editing/SpellingCorrectionController.cpp \
     1386        Source/WebCore/editing/SpellingCorrectionController.h \
    13851387        Source/WebCore/editing/SpellingCorrectionCommand.h \
    13861388        Source/WebCore/editing/SplitElementCommand.cpp \
  • trunk/Source/WebCore/WebCore.gypi

    r83342 r83344  
    26502650            'editing/SmartReplaceICU.cpp',
    26512651            'editing/SpellChecker.cpp',
     2652            'editing/SpellChecker.h',
     2653            'editing/SpellingCorrectionController.cpp',
     2654            'editing/SpellingCorrectionController.h',
    26522655            'editing/SpellingCorrectionCommand.cpp',
    26532656            'editing/SpellingCorrectionCommand.h',
  • trunk/Source/WebCore/WebCore.pro

    r83287 r83344  
    601601    editing/SmartReplaceICU.cpp \
    602602    editing/SpellChecker.cpp \
     603    editing/SpellingCorrectionController.cpp \
    603604    editing/SplitElementCommand.cpp \
    604605    editing/SplitTextNodeCommand.cpp \
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r83296 r83344  
    5047550475                        </File>
    5047650476                        <File
     50477                                RelativePath="..\editing\SpellingCorrectionController.cpp"
     50478                                >
     50479                                <FileConfiguration
     50480                                        Name="Debug|Win32"
     50481                                        ExcludedFromBuild="true"
     50482                                        >
     50483                                        <Tool
     50484                                                Name="VCCLCompilerTool"
     50485                                        />
     50486                                </FileConfiguration>
     50487                                <FileConfiguration
     50488                                        Name="Release|Win32"
     50489                                        ExcludedFromBuild="true"
     50490                                        >
     50491                                        <Tool
     50492                                                Name="VCCLCompilerTool"
     50493                                        />
     50494                                </FileConfiguration>
     50495                                <FileConfiguration
     50496                                        Name="Debug_Cairo_CFLite|Win32"
     50497                                        ExcludedFromBuild="true"
     50498                                        >
     50499                                        <Tool
     50500                                                Name="VCCLCompilerTool"
     50501                                        />
     50502                                </FileConfiguration>
     50503                                <FileConfiguration
     50504                                        Name="Release_Cairo_CFLite|Win32"
     50505                                        ExcludedFromBuild="true"
     50506                                        >
     50507                                        <Tool
     50508                                                Name="VCCLCompilerTool"
     50509                                        />
     50510                                </FileConfiguration>
     50511                                <FileConfiguration
     50512                                        Name="Debug_All|Win32"
     50513                                        ExcludedFromBuild="true"
     50514                                        >
     50515                                        <Tool
     50516                                                Name="VCCLCompilerTool"
     50517                                        />
     50518                                </FileConfiguration>
     50519                                <FileConfiguration
     50520                                        Name="Release_LTCG|Win32"
     50521                                        ExcludedFromBuild="true"
     50522                                        >
     50523                                        <Tool
     50524                                                Name="VCCLCompilerTool"
     50525                                        />
     50526                                </FileConfiguration>
     50527                        </File>
     50528                        <File
     50529                                RelativePath="..\editing\SpellingCorrectionController.h"
     50530                                >
     50531                        </File>
     50532                        <File
    5047750533                                RelativePath="..\editing\SplitElementCommand.cpp"
    5047850534                                >
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r83342 r83344  
    31993199                A6D169621346B49B000EB770 /* ShadowRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6D169611346B49B000EB770 /* ShadowRoot.cpp */; };
    32003200                A6D169641346B4C1000EB770 /* ShadowRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = A6D169631346B4C1000EB770 /* ShadowRoot.h */; settings = {ATTRIBUTES = (Private, ); }; };
     3201                A7005CCC1330C4BA000CC0BA /* SpellingCorrectionController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7005CCA1330C4BA000CC0BA /* SpellingCorrectionController.cpp */; };
     3202                A7005CCD1330C4BA000CC0BA /* SpellingCorrectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = A7005CCB1330C4BA000CC0BA /* SpellingCorrectionController.h */; settings = {ATTRIBUTES = (Private, ); }; };
    32013203                A7151BD812F1558F005A0F64 /* TextCheckerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = A7151BD712F1558F005A0F64 /* TextCheckerClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
    32023204                A715E652134BBBEC00D8E713 /* ProgressShadowElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A715E650134BBBEC00D8E713 /* ProgressShadowElement.cpp */; };
     
    48094811                B885E8D411E06DD2009FFBF4 /* InspectorApplicationCacheAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B885E8D211E06DD2009FFBF4 /* InspectorApplicationCacheAgent.cpp */; };
    48104812                B885E8D511E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = B885E8D311E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h */; settings = {ATTRIBUTES = (); }; };
    4811                 B8A6A6D5127B338D008673BA /* CorrectionPanelInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = B8A6A6D4127B338D008673BA /* CorrectionPanelInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
    48124813                B8DBDB4B130B0F8A00F5CDB1 /* SetSelectionCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8DBDB47130B0F8A00F5CDB1 /* SetSelectionCommand.cpp */; };
    48134814                B8DBDB4C130B0F8A00F5CDB1 /* SetSelectionCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = B8DBDB48130B0F8A00F5CDB1 /* SetSelectionCommand.h */; };
     
    97399740                A6D169611346B49B000EB770 /* ShadowRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowRoot.cpp; sourceTree = "<group>"; };
    97409741                A6D169631346B4C1000EB770 /* ShadowRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowRoot.h; sourceTree = "<group>"; };
     9742                A7005CCA1330C4BA000CC0BA /* SpellingCorrectionController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpellingCorrectionController.cpp; sourceTree = "<group>"; };
     9743                A7005CCB1330C4BA000CC0BA /* SpellingCorrectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpellingCorrectionController.h; sourceTree = "<group>"; };
    97419744                A7151BD712F1558F005A0F64 /* TextCheckerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCheckerClient.h; sourceTree = "<group>"; };
    97429745                A715E650134BBBEC00D8E713 /* ProgressShadowElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProgressShadowElement.cpp; sourceTree = "<group>"; };
     
    1125911262                B885E8D211E06DD2009FFBF4 /* InspectorApplicationCacheAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorApplicationCacheAgent.cpp; sourceTree = "<group>"; };
    1126011263                B885E8D311E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorApplicationCacheAgent.h; sourceTree = "<group>"; };
    11261                 B8A6A6D4127B338D008673BA /* CorrectionPanelInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CorrectionPanelInfo.h; sourceTree = "<group>"; };
    1126211264                B8DBDB47130B0F8A00F5CDB1 /* SetSelectionCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SetSelectionCommand.cpp; sourceTree = "<group>"; };
    1126311265                B8DBDB48130B0F8A00F5CDB1 /* SetSelectionCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetSelectionCommand.h; sourceTree = "<group>"; };
     
    1557515577                                93309D8D099E64910056E581 /* CompositeEditCommand.cpp */,
    1557615578                                93309D8E099E64910056E581 /* CompositeEditCommand.h */,
    15577                                 B8A6A6D4127B338D008673BA /* CorrectionPanelInfo.h */,
    1557815579                                D0B0556709C6700100307E43 /* CreateLinkCommand.cpp */,
    1557915580                                D0B0556609C6700100307E43 /* CreateLinkCommand.h */,
     
    1565715658                                B8DBDB49130B0F8A00F5CDB1 /* SpellingCorrectionCommand.cpp */,
    1565815659                                B8DBDB4A130B0F8A00F5CDB1 /* SpellingCorrectionCommand.h */,
     15660                                A7005CCA1330C4BA000CC0BA /* SpellingCorrectionController.cpp */,
     15661                                A7005CCB1330C4BA000CC0BA /* SpellingCorrectionController.h */,
    1565915662                                93309DC2099E64910056E581 /* SplitElementCommand.cpp */,
    1566015663                                93309DC3099E64910056E581 /* SplitElementCommand.h */,
     
    2001920022                                7EE6846412D26E3800E79415 /* CookieStorageCFNet.h in Headers */,
    2002020023                                FE6FD4880F676E5700092873 /* Coordinates.h in Headers */,
    20021                                 B8A6A6D5127B338D008673BA /* CorrectionPanelInfo.h in Headers */,
    2002220024                                A80E6D040A1989CA007FB8C5 /* Counter.h in Headers */,
    2002320025                                BC5EB9790E82069200B25965 /* CounterContent.h in Headers */,
     
    2234222344                                A78FE13C12366B1000ACE8D0 /* SpellChecker.h in Headers */,
    2234322345                                B8DBDB4E130B0F8A00F5CDB1 /* SpellingCorrectionCommand.h in Headers */,
     22346                                A7005CCD1330C4BA000CC0BA /* SpellingCorrectionController.h in Headers */,
    2234422347                                93309E12099E64920056E581 /* SplitElementCommand.h in Headers */,
    2234522348                                93309E14099E64920056E581 /* SplitTextNodeCommand.h in Headers */,
     
    2516725170                                A78FE13B12366B1000ACE8D0 /* SpellChecker.cpp in Sources */,
    2516825171                                B8DBDB4D130B0F8A00F5CDB1 /* SpellingCorrectionCommand.cpp in Sources */,
     25172                                A7005CCC1330C4BA000CC0BA /* SpellingCorrectionController.cpp in Sources */,
    2516925173                                93309E11099E64920056E581 /* SplitElementCommand.cpp in Sources */,
    2517025174                                93309E13099E64920056E581 /* SplitTextNodeCommand.cpp in Sources */,
  • trunk/Source/WebCore/editing/EditingAllInOne.cpp

    r73888 r83344  
    6464#include <SmartReplace.cpp>
    6565#include <SmartReplaceCF.cpp>
     66#include <SpellingCorrectionController.cpp>
    6667#include <SpellChecker.cpp>
    6768#include <SplitElementCommand.cpp>
  • trunk/Source/WebCore/editing/Editor.cpp

    r83245 r83344  
    3939#include "ClipboardEvent.h"
    4040#include "CompositionEvent.h"
     41#include "SpellingCorrectionController.h"
    4142#include "CreateLinkCommand.h"
    4243#include "DeleteButtonController.h"
     
    9495using namespace Unicode;
    9596
    96 static inline bool isAmbiguousBoundaryCharacter(UChar character)
    97 {
    98     // These are characters that can behave as word boundaries, but can appear within words.
    99     // If they are just typed, i.e. if they are immediately followed by a caret, we want to delay text checking until the next character has been typed.
    100     // FIXME: this is required until 6853027 is fixed and text checking can do this for us.
    101     return character == '\'' || character == rightSingleQuotationMark || character == hebrewPunctuationGershayim;
    102 }
    103 
    104 static const Vector<DocumentMarker::MarkerType>& markerTypesForAutocorrection()
    105 {
    106     DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForAutoCorrection, ());
    107     if (markerTypesForAutoCorrection.isEmpty()) {
    108         markerTypesForAutoCorrection.append(DocumentMarker::Replacement);
    109         markerTypesForAutoCorrection.append(DocumentMarker::CorrectionIndicator);
    110         markerTypesForAutoCorrection.append(DocumentMarker::SpellCheckingExemption);
    111         markerTypesForAutoCorrection.append(DocumentMarker::Autocorrected);
    112     }
    113     return markerTypesForAutoCorrection;
    114 }
    115 
    116 static const Vector<DocumentMarker::MarkerType>& markerTypesForReplacement()
    117 {
    118     DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForReplacement, ());
    119     if (markerTypesForReplacement.isEmpty()) {
    120         markerTypesForReplacement.append(DocumentMarker::Replacement);
    121         markerTypesForReplacement.append(DocumentMarker::SpellCheckingExemption);
    122     }
    123     return markerTypesForReplacement;
    124 }
    125 
    126 #if SUPPORT_AUTOCORRECTION_PANEL
    127 static bool markersHaveIdenticalDescription(const Vector<DocumentMarker>& markers)
    128 {
    129     if (markers.isEmpty())
    130         return true;
    131 
    132     const String& description = markers[0].description;
    133     for (size_t i = 1; i < markers.size(); ++i) {
    134         if (description != markers[i].description)
    135             return false;
    136     }
    137     return true;
    138 }
    139 #endif
    140 
    14197// When an event handler has moved the selection outside of a text control
    14298// we should use the target control's selection for this editing operation.
     
    539495        client()->respondToChangedSelection();
    540496    m_deleteButtonController->respondToChangedSelection(oldSelection);
    541 
    542 #if SUPPORT_AUTOCORRECTION_PANEL
    543     VisibleSelection currentSelection(frame()->selection()->selection());
    544     // When user moves caret to the end of autocorrected word and pauses, we show the panel
    545     // containing the original pre-correction word so that user can quickly revert the
    546     // undesired autocorrection. Here, we start correction panel timer once we confirm that
    547     // the new caret position is at the end of a word.
    548     if (!currentSelection.isCaret() || currentSelection == oldSelection)
    549         return;
    550 
    551     VisiblePosition selectionPosition = currentSelection.start();
    552     VisiblePosition endPositionOfWord = endOfWord(selectionPosition, LeftWordIfOnBoundary);
    553     if (selectionPosition != endPositionOfWord)
    554         return;
    555 
    556     Position position = endPositionOfWord.deepEquivalent();
    557     if (position.anchorType() != Position::PositionIsOffsetInAnchor)
    558         return;
    559 
    560     Node* node = position.containerNode();
    561     int endOffset = position.offsetInContainerNode();
    562     Vector<DocumentMarker> markers = node->document()->markers()->markersForNode(node);
    563     size_t markerCount = markers.size();
    564     for (size_t i = 0; i < markerCount; ++i) {
    565         const DocumentMarker& marker = markers[i];
    566         if (((marker.type == DocumentMarker::Replacement && !marker.description.isNull()) || marker.type == DocumentMarker::Spelling) && static_cast<int>(marker.endOffset) == endOffset) {
    567             RefPtr<Range> wordRange = Range::create(frame()->document(), node, marker.startOffset, node, marker.endOffset);
    568             String currentWord = plainText(wordRange.get());
    569             if (currentWord.length()) {
    570                 m_correctionPanelInfo.rangeToBeReplaced = wordRange;
    571                 m_correctionPanelInfo.replacedString = currentWord;
    572                 if (marker.type == DocumentMarker::Spelling)
    573                     startCorrectionPanelTimer(CorrectionPanelInfo::PanelTypeSpellingSuggestions);
    574                 else {
    575                     m_correctionPanelInfo.replacementString = marker.description;
    576                     startCorrectionPanelTimer(CorrectionPanelInfo::PanelTypeReversion);
    577                 }
    578             }
    579             break;
    580         }
    581     }
    582 #endif // SUPPORT_AUTOCORRECTION_PANEL
     497    m_spellingCorrector->respondToChangedSelection(oldSelection);
    583498}
    584499
     
    591506    }
    592507
    593 #if REMOVE_MARKERS_UPON_EDITING
    594     removeSpellAndCorrectionMarkersFromWordsToBeEdited(true);
    595 #endif
     508    updateMarkersForWordsAffectedByEditing(true);
    596509
    597510    if (client())
     
    1080993    VisibleSelection newSelection(cmd->endingSelection());
    1081994
    1082 #if SUPPORT_AUTOCORRECTION_PANEL
    1083     if (cmd->isTopLevelCommand() && !cmd->shouldRetainAutocorrectionIndicator())
    1084         m_frame->document()->markers()->removeMarkers(DocumentMarker::CorrectionIndicator);
    1085 #endif
     995    m_spellingCorrector->respondToAppliedEditing(cmd.get());
    1086996
    1087997    // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
     
    11421052    , m_shouldStyleWithCSS(false)
    11431053    , m_killRing(adoptPtr(new KillRing))
    1144     , m_spellChecker(new SpellChecker(frame, frame->page() ? frame->page()->editorClient()->textChecker() : 0))
    1145     , m_correctionPanelTimer(this, &Editor::correctionPanelTimerFired)
     1054    , m_spellChecker(adoptPtr(new SpellChecker(frame, frame->page() ? frame->page()->editorClient()->textChecker() : 0)))
     1055    , m_spellingCorrector(adoptPtr(new SpellingCorrectionController(frame)))
    11461056    , m_areMarkedTextMatchesHighlighted(false)
    11471057{
     
    11501060Editor::~Editor()
    11511061{
    1152 #if SUPPORT_AUTOCORRECTION_PANEL
    1153     dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
    1154 #endif
    11551062}
    11561063
     
    11851092        return true;
    11861093
    1187 #if REMOVE_MARKERS_UPON_EDITING
    11881094    if (!text.isEmpty())
    1189         removeSpellAndCorrectionMarkersFromWordsToBeEdited(isSpaceOrNewline(text[0]));
    1190 #endif
     1095        updateMarkersForWordsAffectedByEditing(text[0]);
    11911096
    11921097    bool shouldConsiderApplyingAutocorrection = false;
     
    11971102        shouldConsiderApplyingAutocorrection = true;
    11981103
    1199     bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && applyAutocorrectionBeforeTypingIfAppropriate();
     1104    bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && m_spellingCorrector->applyAutocorrectionBeforeTypingIfAppropriate();
    12001105
    12011106    // Get the selection to use for the event that triggered this insertText.
     
    12331138        return true;
    12341139
    1235     bool autocorrectionIsApplied = applyAutocorrectionBeforeTypingIfAppropriate();
     1140    bool autocorrectionIsApplied = m_spellingCorrector->applyAutocorrectionBeforeTypingIfAppropriate();
    12361141    TypingCommand::insertLineBreak(m_frame->document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
    12371142    revealSelectionAfterEditingOperation();
     
    12511156        return true;
    12521157
    1253     bool autocorrectionIsApplied = applyAutocorrectionBeforeTypingIfAppropriate();
     1158    bool autocorrectionIsApplied = m_spellingCorrector->applyAutocorrectionBeforeTypingIfAppropriate();
    12541159    TypingCommand::insertParagraphSeparator(m_frame->document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
    12551160    revealSelectionAfterEditingOperation();
     
    12681173    RefPtr<Range> selection = selectedRange();
    12691174    if (shouldDeleteRange(selection.get())) {
    1270 #if REMOVE_MARKERS_UPON_EDITING
    1271         removeSpellAndCorrectionMarkersFromWordsToBeEdited(true);
    1272 #endif
     1175        updateMarkersForWordsAffectedByEditing(true);
    12731176        if (isNodeInTextFormControl(m_frame->selection()->start().deprecatedNode()))
    12741177            Pasteboard::generalPasteboard()->writePlainText(selectedText());
     
    13091212    if (!canPaste())
    13101213        return;
    1311 #if REMOVE_MARKERS_UPON_EDITING
    1312     removeSpellAndCorrectionMarkersFromWordsToBeEdited(false);
    1313 #endif
     1214    updateMarkersForWordsAffectedByEditing(false);
    13141215    CachedResourceLoader* loader = m_frame->document()->cachedResourceLoader();
    13151216    loader->setAllowStaleResources(true);
     
    13271228    if (!canPaste())
    13281229        return;
    1329 #if REMOVE_MARKERS_UPON_EDITING
    1330     removeSpellAndCorrectionMarkersFromWordsToBeEdited(false);
    1331 #endif
     1230    updateMarkersForWordsAffectedByEditing(false);
    13321231    pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    13331232}
     
    14821381bool Editor::isAutomaticSpellingCorrectionEnabled()
    14831382{
    1484     return client() && client()->isAutomaticSpellingCorrectionEnabled();
     1383    return m_spellingCorrector->isAutomaticSpellingCorrectionEnabled();
    14851384}
    14861385
     
    20741973{
    20751974#if USE(UNIFIED_TEXT_CHECKING)
    2076 #if SUPPORT_AUTOCORRECTION_PANEL
    2077     // Apply pending autocorrection before next round of spell checking.
    2078     bool doApplyCorrection = true;
    2079     VisiblePosition startOfSelection = selectionAfterTyping.visibleStart();
    2080     VisibleSelection currentWord = VisibleSelection(startOfWord(startOfSelection, LeftWordIfOnBoundary), endOfWord(startOfSelection, RightWordIfOnBoundary));
    2081     if (currentWord.visibleEnd() == startOfSelection) {
    2082         String wordText = plainText(currentWord.toNormalizedRange().get());
    2083         if (wordText.length() > 0 && isAmbiguousBoundaryCharacter(wordText[wordText.length() - 1]))
    2084             doApplyCorrection = false;
    2085     }
    2086     if (doApplyCorrection)
    2087         handleCorrectionPanelResult(dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanelAccepted));
    2088     else
    2089         m_correctionPanelInfo.rangeToBeReplaced.clear();
    2090 #else
    2091     UNUSED_PARAM(selectionAfterTyping);
    2092 #endif
     1975    m_spellingCorrector->applyPendingCorrection(selectionAfterTyping);
     1976
    20931977    TextCheckingOptions textCheckingOptions = 0;
    20941978    if (isContinuousSpellCheckingEnabled())
     
    21192003
    21202004#else
    2121     UNUSED_PARAM(selectionAfterTyping);
    21222005    if (!isContinuousSpellCheckingEnabled())
    21232006        return;
     
    22282111#if USE(UNIFIED_TEXT_CHECKING)
    22292112    // There shouldn't be pending autocorrection at this moment.
    2230     ASSERT(!m_correctionPanelInfo.rangeToBeReplaced);
     2113    ASSERT(!m_spellingCorrector->hasPendingCorrection());
    22312114
    22322115    bool shouldMarkSpelling = textCheckingOptions & MarkSpelling;
     
    22872170       
    22882171
    2289 #if SUPPORT_AUTOCORRECTION_PANEL
    22902172    // If this checking is only for showing correction panel, we shouldn't bother to mark misspellings.
    22912173    if (shouldShowCorrectionPanel)
    22922174        shouldMarkSpelling = false;
    2293 #endif
    22942175
    22952176    int offsetDueToReplacement = 0;
     
    23102191            ASSERT(resultLength > 0 && resultLocation >= 0);
    23112192            RefPtr<Range> misspellingRange = spellingParagraph.subrange(resultLocation, resultLength);
    2312 #if SUPPORT_AUTOCORRECTION_PANEL
    2313             if (m_frame->document()->markers()->hasMarkers(misspellingRange.get(), DocumentMarker::SpellCheckingExemption))
     2193            if (!m_spellingCorrector->isSpellingMarkerAllowed(misspellingRange))
    23142194                continue;
    2315 #endif // SUPPORT_AUTOCORRECTION_PANEL
    23162195            misspellingRange->startContainer(ec)->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
    23172196        } else if (shouldMarkGrammar && result->type == TextCheckingTypeGrammar && grammarParagraph.checkingRangeCovers(resultLocation, resultLength)) {
     
    23592238                if (markers->hasMarkers(rangeToReplace.get(), DocumentMarker::Replacement)) {
    23602239                    doReplacement = false;
    2361                     recordSpellcheckerResponseForModifiedCorrection(rangeToReplace.get(), replacedString, result->replacement);
     2240                    m_spellingCorrector->recordSpellcheckerResponseForModifiedCorrection(rangeToReplace.get(), replacedString, result->replacement);
    23622241                } else if (markers->hasMarkers(rangeToReplace.get(), DocumentMarker::RejectedCorrection))
    23632242                    doReplacement = false;
     
    23672246                continue;
    23682247
    2369 #if SUPPORT_AUTOCORRECTION_PANEL
    23702248            if (shouldShowCorrectionPanel) {
     2249                ASSERT(SUPPORT_AUTOCORRECTION_PANEL);
     2250                // shouldShowCorrectionPanel can be true only when the panel is available.
    23712251                if (resultLocation + resultLength == spellingRangeEndOffset) {
    23722252                    // We only show the correction panel on the last word.
    2373                     FloatRect boundingBox = windowRectForRange(rangeToReplace.get());
    2374                     if (boundingBox.isEmpty())
    2375                         break;
    2376                     m_correctionPanelInfo.rangeToBeReplaced = rangeToReplace;
    2377                     m_correctionPanelInfo.replacedString = plainText(rangeToReplace.get());
    2378                     m_correctionPanelInfo.replacementString = result->replacement;
    2379                     m_correctionPanelInfo.isActive = true;
    2380                     client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, result->replacement, Vector<String>());
     2253                    m_spellingCorrector->show(rangeToReplace, result->replacement);
    23812254                    break;
    23822255                }
     
    23842257                continue;
    23852258            }
    2386 #endif
    23872259
    23882260            if (selectionToReplace != m_frame->selection()->selection()) {
     
    23982270                    applyCommand(CreateLinkCommand::create(m_frame->document(), result->replacement));
    23992271            } else if (canEdit() && shouldInsertText(result->replacement, rangeToReplace.get(), EditorInsertActionTyped)) {
    2400                 bool useSpellingCorrectionCommand = false;
    2401 #if SUPPORT_AUTOCORRECTION_PANEL
    24022272                if (result->type == TextCheckingTypeCorrection)
    2403                     useSpellingCorrectionCommand = true;
    2404 #endif
    2405                 if (useSpellingCorrectionCommand)
    24062273                    applyCommand(SpellingCorrectionCommand::create(rangeToReplace, result->replacement));
    24072274                else {
     
    24232290                }
    24242291
    2425                 if (result->type == TextCheckingTypeCorrection) {
    2426                     // Add a marker so that corrections can easily be undone and won't be re-corrected.
    2427                     RefPtr<Range> replacedRange = spellingParagraph.subrange(resultLocation, replacementLength);
    2428                     Vector<DocumentMarker::MarkerType> markerTypesToAdd = markerTypesForAutocorrection();
    2429                     DocumentMarkerController* markers = replacedRange->startContainer()->document()->markers();
    2430                     for (size_t i = 0; i < markerTypesToAdd.size(); ++i) {
    2431                         DocumentMarker::MarkerType markerType = markerTypesToAdd[i];
    2432                         if (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected)
    2433                             markers->addMarker(replacedRange.get(), markerType, replacedString);
    2434                         else
    2435                             markers->addMarker(replacedRange.get(), markerType);
    2436                     }
    2437                 }
     2292                // Add a marker so that corrections can easily be undone and won't be re-corrected.
     2293                if (result->type == TextCheckingTypeCorrection)
     2294                    m_spellingCorrector->markCorrection(spellingParagraph.subrange(resultLocation, replacementLength), replacedString);
    24382295            }
    24392296        }
     
    24622319}
    24632320
    2464 void Editor::recordSpellcheckerResponseForModifiedCorrection(Range* rangeOfCorrection, const String& corrected, const String& correction)
    2465 {
    2466 #if SUPPORT_AUTOCORRECTION_PANEL
    2467     if (!rangeOfCorrection)
    2468         return;
    2469     DocumentMarkerController* markers = rangeOfCorrection->startContainer()->document()->markers();
    2470     Vector<DocumentMarker> correctedOnceMarkers = markers->markersInRange(rangeOfCorrection, DocumentMarker::Autocorrected);
    2471     if (correctedOnceMarkers.isEmpty())
    2472         return;
    2473    
    2474     // Spelling corrected text has been edited. We need to determine whether user has reverted it to original text or
    2475     // edited it to something else, and notify spellchecker accordingly.
    2476     if (markersHaveIdenticalDescription(correctedOnceMarkers) && correctedOnceMarkers[0].description == corrected)
    2477         client()->recordAutocorrectionResponse(EditorClient::AutocorrectionReverted, corrected, correction);
    2478     else
    2479         client()->recordAutocorrectionResponse(EditorClient::AutocorrectionEdited, corrected, correction);
    2480     markers->removeMarkers(rangeOfCorrection, DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
    2481 #else
    2482     UNUSED_PARAM(rangeOfCorrection);
    2483     UNUSED_PARAM(corrected);
    2484     UNUSED_PARAM(correction);
    2485 #endif
    2486 }
    2487 
    24882321void Editor::changeBackToReplacedString(const String& replacedString)
    24892322{
     
    24962329        return;
    24972330   
    2498 #if SUPPORT_AUTOCORRECTION_PANEL
    2499     String replacement = plainText(selection.get());
    2500     client()->recordAutocorrectionResponse(EditorClient::AutocorrectionReverted, replacedString, replacement);
    2501 #endif
     2331    m_spellingCorrector->recordAutocorrectionResponseReversed(replacedString, selection);
    25022332    TextCheckingParagraph paragraph(selection);
    25032333    replaceSelectionWithText(replacedString, false, false);
    25042334    RefPtr<Range> changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
    25052335    changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::Replacement, String());
    2506 #if SUPPORT_AUTOCORRECTION_PANEL
    2507     changedRange->startContainer()->document()->markers()->removeMarkers(changedRange.get(), DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
    2508     changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::SpellCheckingExemption);
    2509 #endif
     2336    m_spellingCorrector->markReversed(changedRange.get());
    25102337#else
    25112338    ASSERT_NOT_REACHED();
     
    25322359}
    25332360
    2534 void Editor::correctionPanelTimerFired(Timer<Editor>*)
    2535 {
    2536 #if SUPPORT_AUTOCORRECTION_PANEL
    2537     m_correctionPanelIsDismissedByEditor = false;
    2538     switch (m_correctionPanelInfo.panelType) {
    2539     case CorrectionPanelInfo::PanelTypeCorrection: {
    2540         VisibleSelection selection(frame()->selection()->selection());
    2541         VisiblePosition start(selection.start(), selection.affinity());
    2542         VisiblePosition p = startOfWord(start, LeftWordIfOnBoundary);
    2543         VisibleSelection adjacentWords = VisibleSelection(p, start);
    2544         markAllMisspellingsAndBadGrammarInRanges(MarkSpelling | ShowCorrectionPanel, adjacentWords.toNormalizedRange().get(), 0);
    2545     }
    2546         break;
    2547     case CorrectionPanelInfo::PanelTypeReversion: {
    2548         m_correctionPanelInfo.isActive = true;
    2549         m_correctionPanelInfo.replacedString = plainText(m_correctionPanelInfo.rangeToBeReplaced.get());
    2550         FloatRect boundingBox = windowRectForRange(m_correctionPanelInfo.rangeToBeReplaced.get());
    2551         if (!boundingBox.isEmpty())
    2552             client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, m_correctionPanelInfo.replacementString, Vector<String>());
    2553     }
    2554         break;
    2555     case CorrectionPanelInfo::PanelTypeSpellingSuggestions: {
    2556         if (plainText(m_correctionPanelInfo.rangeToBeReplaced.get()) != m_correctionPanelInfo.replacedString)
    2557             break;
    2558         String paragraphText = plainText(TextCheckingParagraph(m_correctionPanelInfo.rangeToBeReplaced).paragraphRange().get());
    2559         Vector<String> suggestions;
    2560         textChecker()->getGuessesForWord(m_correctionPanelInfo.replacedString, paragraphText, suggestions);
    2561         if (suggestions.isEmpty()) {
    2562             m_correctionPanelInfo.rangeToBeReplaced.clear();
    2563             break;
    2564         }
    2565         String topSuggestion = suggestions.first();
    2566         suggestions.remove(0);
    2567         m_correctionPanelInfo.isActive = true;
    2568         FloatRect boundingBox = windowRectForRange(m_correctionPanelInfo.rangeToBeReplaced.get());
    2569         if (!boundingBox.isEmpty())
    2570             client()->showCorrectionPanel(m_correctionPanelInfo.panelType, boundingBox, m_correctionPanelInfo.replacedString, topSuggestion, suggestions);
    2571     }
    2572         break;
    2573     }
    2574 #endif
    2575 }
    2576 
    2577 void Editor::handleCorrectionPanelResult(const String& correction)
    2578 {
    2579     Range* replacedRange = m_correctionPanelInfo.rangeToBeReplaced.get();
    2580     if (!replacedRange || m_frame->document() != replacedRange->ownerDocument())
    2581         return;
    2582 
    2583     String currentWord = plainText(m_correctionPanelInfo.rangeToBeReplaced.get());
    2584     // Check to see if the word we are about to correct has been changed between timer firing and callback being triggered.
    2585     if (currentWord != m_correctionPanelInfo.replacedString)
    2586         return;
    2587 
    2588     m_correctionPanelInfo.isActive = false;
    2589 
    2590     switch (m_correctionPanelInfo.panelType) {
    2591     case CorrectionPanelInfo::PanelTypeCorrection:
    2592         if (correction.length()) {
    2593             m_correctionPanelInfo.replacementString = correction;
    2594             applyCorrectionPanelInfo(markerTypesForAutocorrection());
    2595         } else {
    2596             if (!m_correctionPanelIsDismissedByEditor)
    2597                 replacedRange->startContainer()->document()->markers()->addMarker(replacedRange, DocumentMarker::RejectedCorrection, m_correctionPanelInfo.replacedString);
    2598         }
    2599         break;
    2600     case CorrectionPanelInfo::PanelTypeReversion:
    2601     case CorrectionPanelInfo::PanelTypeSpellingSuggestions:
    2602         if (correction.length()) {
    2603             m_correctionPanelInfo.replacementString = correction;
    2604             applyCorrectionPanelInfo(markerTypesForReplacement());
    2605         }
    2606         break;
    2607     }
    2608 
    2609     m_correctionPanelInfo.rangeToBeReplaced.clear();
    2610 }
    2611 
    2612 void Editor::startCorrectionPanelTimer(CorrectionPanelInfo::PanelType type)
    2613 {
    2614 #if SUPPORT_AUTOCORRECTION_PANEL
    2615     const double correctionPanelTimerInterval = 0.3;
    2616     if (isAutomaticSpellingCorrectionEnabled()) {
    2617         if (type == CorrectionPanelInfo::PanelTypeCorrection)
    2618             // If type is PanelTypeReversion, then the new range has been set. So we shouldn't clear it.
    2619             m_correctionPanelInfo.rangeToBeReplaced.clear();
    2620         m_correctionPanelInfo.panelType = type;
    2621         m_correctionPanelTimer.startOneShot(correctionPanelTimerInterval);
    2622     }
    2623 #else
    2624     UNUSED_PARAM(type);
    2625 #endif
    2626 }
    2627 
    2628 void Editor::stopCorrectionPanelTimer()
    2629 {
    2630 #if SUPPORT_AUTOCORRECTION_PANEL
    2631     m_correctionPanelTimer.stop();
    2632     m_correctionPanelInfo.rangeToBeReplaced.clear();
    2633 #endif
    2634 }
    2635 
    2636 void Editor::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reasonForDismissing)
    2637 {
    2638 #if SUPPORT_AUTOCORRECTION_PANEL
    2639     if (!m_correctionPanelInfo.isActive)
    2640         return;
    2641     m_correctionPanelInfo.isActive = false;
    2642     m_correctionPanelIsDismissedByEditor = true;
    2643     if (client())
    2644         client()->dismissCorrectionPanel(reasonForDismissing);
    2645 #else
    2646     UNUSED_PARAM(reasonForDismissing);
    2647 #endif
    2648 }
    2649 
    2650 String Editor::dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel reasonForDismissing)
    2651 {
    2652 #if SUPPORT_AUTOCORRECTION_PANEL
    2653     if (!m_correctionPanelInfo.isActive)
    2654         return String();
    2655     m_correctionPanelInfo.isActive = false;
    2656     m_correctionPanelIsDismissedByEditor = true;
    2657     if (!client())
    2658         return String();
    2659     return client()->dismissCorrectionPanelSoon(reasonForDismissing);
    2660 #else
    2661     UNUSED_PARAM(reasonForDismissing);
    2662     return String();
    2663 #endif
    2664 }
    2665 
    2666 void Editor::removeSpellAndCorrectionMarkersFromWordsToBeEdited(bool doNotRemoveIfSelectionAtWordBoundary)
    2667 {
     2361void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
     2362{
     2363    m_spellingCorrector->respondToUnappliedSpellCorrection(selectionOfCorrected, corrected, correction);
     2364}
     2365
     2366void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
     2367{
     2368    if (!m_spellingCorrector->shouldRemoveMarkersUponEditing())
     2369        return;
     2370
    26682371    // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
    26692372    // several scenarios:
     
    27312434}
    27322435
    2733 void Editor::applyCorrectionPanelInfo(const Vector<DocumentMarker::MarkerType>& markerTypesToAdd)
    2734 {
    2735 #if SUPPORT_AUTOCORRECTION_PANEL
    2736     if (!m_correctionPanelInfo.rangeToBeReplaced)
    2737         return;
    2738 
    2739     ExceptionCode ec = 0;
    2740     RefPtr<Range> paragraphRangeContainingCorrection = m_correctionPanelInfo.rangeToBeReplaced->cloneRange(ec);
    2741     if (ec)
    2742         return;
    2743 
    2744     setStart(paragraphRangeContainingCorrection.get(), startOfParagraph(m_correctionPanelInfo.rangeToBeReplaced->startPosition()));
    2745     setEnd(paragraphRangeContainingCorrection.get(), endOfParagraph(m_correctionPanelInfo.rangeToBeReplaced->endPosition()));
    2746 
    2747     // After we replace the word at range rangeToBeReplaced, we need to add markers to that range.
    2748     // However, once the replacement took place, the value of rangeToBeReplaced is not valid anymore.
    2749     // So before we carry out the replacement, we need to store the start position of rangeToBeReplaced
    2750     // relative to the start position of the containing paragraph. We use correctionStartOffsetInParagraph
    2751     // to store this value. In order to obtain this offset, we need to first create a range
    2752     // which spans from the start of paragraph to the start position of rangeToBeReplaced.
    2753     RefPtr<Range> correctionStartOffsetInParagraphAsRange = Range::create(paragraphRangeContainingCorrection->startContainer(ec)->document(), paragraphRangeContainingCorrection->startPosition(), paragraphRangeContainingCorrection->startPosition());
    2754     if (ec)
    2755         return;
    2756 
    2757     Position startPositionOfRangeToBeReplaced = m_correctionPanelInfo.rangeToBeReplaced->startPosition();
    2758     correctionStartOffsetInParagraphAsRange->setEnd(startPositionOfRangeToBeReplaced.containerNode(), startPositionOfRangeToBeReplaced.computeOffsetInContainerNode(), ec);
    2759     if (ec)
    2760         return;
    2761 
    2762     // Take note of the location of autocorrection so that we can add marker after the replacement took place.
    2763     int correctionStartOffsetInParagraph = TextIterator::rangeLength(correctionStartOffsetInParagraphAsRange.get());
    2764 
    2765     // Clone the range, since the caller of this method may want to keep the original range around.
    2766     RefPtr<Range> rangeToBeReplaced = m_correctionPanelInfo.rangeToBeReplaced->cloneRange(ec);
    2767     applyCommand(SpellingCorrectionCommand::create(rangeToBeReplaced, m_correctionPanelInfo.replacementString));
    2768     setEnd(paragraphRangeContainingCorrection.get(), m_frame->selection()->selection().start());
    2769     RefPtr<Range> replacementRange = TextIterator::subrange(paragraphRangeContainingCorrection.get(), correctionStartOffsetInParagraph,  m_correctionPanelInfo.replacementString.length());
    2770     String newText = plainText(replacementRange.get());
    2771 
    2772     // Check to see if replacement succeeded.
    2773     if (newText != m_correctionPanelInfo.replacementString)
    2774         return;
    2775 
    2776     DocumentMarkerController* markers = replacementRange->startContainer()->document()->markers();
    2777     size_t size = markerTypesToAdd.size();
    2778     for (size_t i = 0; i < size; ++i) {
    2779         DocumentMarker::MarkerType markerType = markerTypesToAdd[i];
    2780         String description;
    2781         if (m_correctionPanelInfo.panelType != CorrectionPanelInfo::PanelTypeReversion && (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected))
    2782             description = m_correctionPanelInfo.replacedString;
    2783         markers->addMarker(replacementRange.get(), markerType, description);
    2784     }
    2785 #else // SUPPORT_AUTOCORRECTION_PANEL
    2786     UNUSED_PARAM(markerTypesToAdd);
    2787 #endif // SUPPORT_AUTOCORRECTION_PANEL
    2788 }
    2789 
    2790 bool Editor::applyAutocorrectionBeforeTypingIfAppropriate()
    2791 {
    2792     if (!m_correctionPanelInfo.rangeToBeReplaced || !m_correctionPanelInfo.isActive)
    2793         return false;
    2794 
    2795     if (m_correctionPanelInfo.panelType != CorrectionPanelInfo::PanelTypeCorrection)
    2796         return false;
    2797 
    2798     Position caretPosition = m_frame->selection()->selection().start();
    2799 
    2800     if (m_correctionPanelInfo.rangeToBeReplaced->endPosition() == caretPosition) {
    2801         handleCorrectionPanelResult(dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanelAccepted));
    2802         return true;
    2803     }
    2804    
    2805     // Pending correction should always be where caret is. But in case this is not always true, we still want to dismiss the panel without accepting the correction.
    2806     ASSERT(m_correctionPanelInfo.rangeToBeReplaced->endPosition() == caretPosition);
    2807     dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
    2808     return false;
    2809 }
    2810 
    2811 void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
    2812 {
    2813 #if SUPPORT_AUTOCORRECTION_PANEL
    2814     client()->recordAutocorrectionResponse(EditorClient::AutocorrectionReverted, corrected, correction);
    2815     m_frame->document()->updateLayout();
    2816     m_frame->selection()->setSelection(selectionOfCorrected, SelectionController::CloseTyping | SelectionController::ClearTypingStyle | SelectionController::SpellCorrectionTriggered);
    2817     RefPtr<Range> range = Range::create(m_frame->document(), m_frame->selection()->selection().start(), m_frame->selection()->selection().end());
    2818 
    2819     DocumentMarkerController* markers = m_frame->document()->markers();
    2820     markers->removeMarkers(range.get(), DocumentMarker::Spelling | DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker);
    2821     markers->addMarker(range.get(), DocumentMarker::Replacement);
    2822     markers->addMarker(range.get(), DocumentMarker::SpellCheckingExemption);
    2823 #else // SUPPORT_AUTOCORRECTION_PANEL
    2824     UNUSED_PARAM(selectionOfCorrected);
    2825     UNUSED_PARAM(corrected);
    2826     UNUSED_PARAM(correction);
    2827 #endif // SUPPORT_AUTOCORRECTION_PANEL
    2828 }
    2829 
    28302436PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
    28312437{
     
    29482554        killRing()->append(text);
    29492555    m_shouldStartNewKillRingSequence = false;
     2556}
     2557
     2558void Editor::startCorrectionPanelTimer()
     2559{
     2560    m_spellingCorrector->startCorrectionPanelTimer(CorrectionPanelInfo::PanelTypeCorrection);
     2561}
     2562
     2563void Editor::handleCorrectionPanelResult(const String& correction)
     2564{
     2565    m_spellingCorrector->handleCorrectionPanelResult(correction);
     2566}
     2567
     2568
     2569void Editor::dismissCorrectionPanelAsIgnored()
     2570{
     2571    m_spellingCorrector->dismiss(ReasonForDismissingCorrectionPanelIgnored);
    29502572}
    29512573
     
    35223144void Editor::respondToChangedSelection(const VisibleSelection& oldSelection, SelectionController::SetSelectionOptions options)
    35233145{
    3524 #if SUPPORT_AUTOCORRECTION_PANEL
    3525     // Make sure there's no pending autocorrection before we call markMisspellingsAndBadGrammar() below.
    3526     VisibleSelection currentSelection(frame()->selection()->selection());
    3527     if (currentSelection != oldSelection) {
    3528         stopCorrectionPanelTimer();
    3529         dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
    3530     }
    3531 #endif // SUPPORT_AUTOCORRECTION_PANEL
     3146    m_spellingCorrector->stopPendingCorrection(oldSelection);
    35323147
    35333148    bool closeTyping = options & SelectionController::CloseTyping;
     
    35453160        }
    35463161
    3547         bool shouldCheckSpellingAndGrammar = true;
    3548 #if SUPPORT_AUTOCORRECTION_PANEL
    35493162        // Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
    3550         shouldCheckSpellingAndGrammar = !(options & SelectionController::SpellCorrectionTriggered);
    3551 #endif
     3163        bool shouldCheckSpellingAndGrammar = !(options & SelectionController::SpellCorrectionTriggered);
    35523164
    35533165        // When typing we check spelling elsewhere, so don't redo it here.
  • trunk/Source/WebCore/editing/Editor.h

    r83060 r83344  
    2929#include "ClipboardAccessPolicy.h"
    3030#include "Color.h"
    31 #include "CorrectionPanelInfo.h"
    3231#include "DocumentMarker.h"
    3332#include "EditAction.h"
     
    5251class CSSStyleDeclaration;
    5352class Clipboard;
     53class SpellingCorrectionController;
    5454class DeleteButtonController;
    5555class EditCommand;
     
    326326    void addToKillRing(Range*, bool prepend);
    327327
    328     void startCorrectionPanelTimer(CorrectionPanelInfo::PanelType);
     328    void startCorrectionPanelTimer();
    329329    // If user confirmed a correction in the correction panel, correction has non-zero length, otherwise it means that user has dismissed the panel.
    330330    void handleCorrectionPanelResult(const String& correction);
    331     void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel);
     331    void dismissCorrectionPanelAsIgnored();
    332332
    333333    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
     
    385385
    386386    bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
    387     void removeSpellAndCorrectionMarkersFromWordsToBeEdited(bool doNotRemoveIfSelectionAtWordBoundary);
     387    void updateMarkersForWordsAffectedByEditing(bool onlyHandleWordsContainingSelection);
    388388
    389389private:
     
    400400    bool m_shouldStyleWithCSS;
    401401    OwnPtr<KillRing> m_killRing;
    402     CorrectionPanelInfo m_correctionPanelInfo;
    403402    OwnPtr<SpellChecker> m_spellChecker;
    404     Timer<Editor> m_correctionPanelTimer;
    405     bool m_correctionPanelIsDismissedByEditor;
     403    OwnPtr<SpellingCorrectionController> m_spellingCorrector;
    406404    VisibleSelection m_mark;
    407405    bool m_areMarkedTextMatchesHighlighted;
     
    418416    void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
    419417    TextCheckingTypeMask textCheckingTypeMaskFor(TextCheckingOptions);
    420     void recordSpellcheckerResponseForModifiedCorrection(Range*, const String& corrected, const String& correction);
    421418
    422419    void selectComposition();
     
    429426
    430427    void changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle);
    431     void correctionPanelTimerFired(Timer<Editor>*);
     428
    432429    Node* findEventTargetFromSelection() const;
    433430    void stopCorrectionPanelTimer();
    434     String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel);
     431
    435432    void applyCorrectionPanelInfo(const Vector<DocumentMarker::MarkerType>& markerTypesToAdd);
    436433    // Return true if correction was applied, false otherwise.
  • trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp

    r83060 r83344  
    2727#include "SpellingCorrectionCommand.h"
    2828
    29 #include "CorrectionPanelInfo.h"
     29#include "SpellingCorrectionController.h"
    3030#include "DocumentFragment.h"
    3131#include "Frame.h"
  • trunk/Source/WebCore/editing/TypingCommand.cpp

    r83245 r83344  
    155155    ASSERT(frame);
    156156
    157 #if REMOVE_MARKERS_UPON_EDITING
    158157    if (!text.isEmpty())
    159         document->frame()->editor()->removeSpellAndCorrectionMarkersFromWordsToBeEdited(isSpaceOrNewline(text.characters()[0]));
    160 #endif
    161 
     158        document->frame()->editor()->updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text.characters()[0]));
     159   
    162160    insertText(document, text, frame->selection()->selection(), options, composition);
    163161}
     
    345343        if (p1 != p2)
    346344            document()->frame()->editor()->markMisspellingsAfterTypingToWord(p1, endingSelection());
    347 #if SUPPORT_AUTOCORRECTION_PANEL
    348345        else if (commandType == TypingCommand::InsertText)
    349             document()->frame()->editor()->startCorrectionPanelTimer(CorrectionPanelInfo::PanelTypeCorrection);
    350 #else
    351     UNUSED_PARAM(commandType);
    352 #endif
     346            document()->frame()->editor()->startCorrectionPanelTimer();
    353347    }
    354348}
     
    469463void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool killRing)
    470464{
    471 #if REMOVE_MARKERS_UPON_EDITING
    472     document()->frame()->editor()->removeSpellAndCorrectionMarkersFromWordsToBeEdited(false);
    473 #endif
     465    document()->frame()->editor()->updateMarkersForWordsAffectedByEditing(false);
     466
    474467    VisibleSelection selectionToDelete;
    475468    VisibleSelection selectionAfterUndo;
     
    568561void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool killRing)
    569562{
    570 #if REMOVE_MARKERS_UPON_EDITING
    571     document()->frame()->editor()->removeSpellAndCorrectionMarkersFromWordsToBeEdited(false);
    572 #endif
     563    document()->frame()->editor()->updateMarkersForWordsAffectedByEditing(false);
     564
    573565    VisibleSelection selectionToDelete;
    574566    VisibleSelection selectionAfterUndo;
  • trunk/Source/WebCore/editing/htmlediting.h

    r83247 r83344  
    225225    return c == noBreakSpace || c == ' ' || c == '\n' || c == '\t';
    226226}
     227
     228inline bool isAmbiguousBoundaryCharacter(UChar character)
     229{
     230    // These are characters that can behave as word boundaries, but can appear within words.
     231    // If they are just typed, i.e. if they are immediately followed by a caret, we want to delay text checking until the next character has been typed.
     232    // FIXME: this is required until 6853027 is fixed and text checking can do this for us.
     233    return character == '\'' || character == rightSingleQuotationMark || character == hebrewPunctuationGershayim;
     234}
     235
    227236String stringWithRebalancedWhitespace(const String&, bool startIsStartOfParagraph, bool endIsEndOfParagraph);
    228237const String& nonBreakingSpaceString();
  • trunk/Source/WebCore/page/EditorClient.h

    r81847 r83344  
    2828#define EditorClient_h
    2929
    30 #include "CorrectionPanelInfo.h"
     30#include "SpellingCorrectionController.h"
    3131#include "EditorInsertAction.h"
    3232#include "FloatRect.h"
  • trunk/Source/WebCore/page/Frame.cpp

    r83201 r83344  
    969969        return;
    970970
    971     m_editor.dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
     971    m_editor.dismissCorrectionPanelAsIgnored();
    972972
    973973#if ENABLE(SVG)
  • trunk/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.h

    r81847 r83344  
    2929#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
    3030#import <AppKit/NSTextChecker.h>
    31 #import <WebCore/CorrectionPanelInfo.h>
     31#import <WebCore/SpellingCorrectionController.h>
    3232#import <wtf/RetainPtr.h>
    3333
  • trunk/Source/WebKit2/UIProcess/mac/CorrectionPanel.h

    r81847 r83344  
    2929#if !defined(BUILDING_ON_SNOW_LEOPARD)
    3030#import <AppKit/NSTextChecker.h>
    31 #import <WebCore/CorrectionPanelInfo.h>
     31#import <WebCore/SpellingCorrectionController.h>
    3232#import <wtf/RetainPtr.h>
    3333
Note: See TracChangeset for help on using the changeset viewer.