[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

mrowe at apple.com mrowe at apple.com
Wed Dec 22 15:18:43 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 856d3c1242dab6a988afee23a15d32a737c34b59
Author: mrowe at apple.com <mrowe at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Oct 30 03:42:11 2010 +0000

    Roll out r70847 as it causes crashes when typing text in both Safari and Mail: <http://webkit.org/b/48708>.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70970 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index 4b05477..c1a8e11 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -926,7 +926,6 @@ SET(WebCore_SOURCES
     editing/SplitElementCommand.cpp
     editing/SplitTextNodeCommand.cpp
     editing/SplitTextNodeContainingElementCommand.cpp
-    editing/TextCheckingHelper.cpp
     editing/TextIterator.cpp
     editing/TypingCommand.cpp
     editing/UnlinkCommand.cpp
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index bba86af..3d034dc 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -1355,8 +1355,6 @@ webcore_sources += \
 	WebCore/editing/SplitTextNodeContainingElementCommand.cpp \
 	WebCore/editing/SplitTextNodeContainingElementCommand.h \
 	WebCore/editing/TextAffinity.h \
-	WebCore/editing/TextCheckingHelper.cpp \
-	WebCore/editing/TextCheckingHelper.h \
 	WebCore/editing/TextGranularity.h \
 	WebCore/editing/TextIterator.cpp \
 	WebCore/editing/TextIterator.h \
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index 3f9bd0d..f1f9c12 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -1437,8 +1437,6 @@
             'editing/SplitTextNodeContainingElementCommand.cpp',
             'editing/SplitTextNodeContainingElementCommand.h',
             'editing/TextAffinity.h',
-            'editing/TextCheckingHelper.cpp',
-            'editing/TextCheckingHelper.h',
             'editing/TextGranularity.h',
             'editing/TextIterator.cpp',
             'editing/TextIterator.h',
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 6e4e131..f80493a 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -817,7 +817,6 @@ SOURCES += \
     editing/SplitElementCommand.cpp \
     editing/SplitTextNodeCommand.cpp \
     editing/SplitTextNodeContainingElementCommand.cpp \
-    editing/TextCheckingHelper.cpp \
     editing/TextIterator.cpp \
     editing/TypingCommand.cpp \
     editing/UnlinkCommand.cpp \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 24a2d91..e0eb3f9 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -47940,62 +47940,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\editing\TextCheckingHelper.cpp"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug_Internal|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug_Cairo|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release_Cairo|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug_All|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\editing\TextCheckingHelper.h"
-				>
-			</File>
-			<File
 				RelativePath="..\editing\TextGranularity.h"
 				>
 			</File>
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 009f50b..ab13482 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -3067,8 +3067,6 @@
 		A7D3C5240B576B4B002CA450 /* PasteboardHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D3C5230B576B4B002CA450 /* PasteboardHelper.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A7D6B3490F61104500B79FD1 /* WorkerScriptLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6B3470F61104500B79FD1 /* WorkerScriptLoader.h */; };
 		A7D6B34A0F61104500B79FD1 /* WorkerScriptLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D6B3480F61104500B79FD1 /* WorkerScriptLoader.cpp */; };
-		A7DBF8DD1276919C006B6008 /* TextCheckingHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */; };
-		A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */; };
 		A7F338A311C0EFCA00A320A7 /* ShadowElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F338A111C0EFCA00A320A7 /* ShadowElement.cpp */; };
 		A7F338A411C0EFCA00A320A7 /* ShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F338A211C0EFCA00A320A7 /* ShadowElement.h */; };
 		A809F1470B73793A002E4D7F /* RenderSVGGradientStop.h in Headers */ = {isa = PBXBuildFile; fileRef = A809F1450B73793A002E4D7F /* RenderSVGGradientStop.h */; };
@@ -9154,8 +9152,6 @@
 		A7D3C5230B576B4B002CA450 /* PasteboardHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardHelper.h; sourceTree = "<group>"; };
 		A7D6B3470F61104500B79FD1 /* WorkerScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerScriptLoader.h; path = workers/WorkerScriptLoader.h; sourceTree = "<group>"; };
 		A7D6B3480F61104500B79FD1 /* WorkerScriptLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WorkerScriptLoader.cpp; path = workers/WorkerScriptLoader.cpp; sourceTree = "<group>"; };
-		A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextCheckingHelper.cpp; sourceTree = "<group>"; };
-		A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCheckingHelper.h; sourceTree = "<group>"; };
 		A7F338A111C0EFCA00A320A7 /* ShadowElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowElement.cpp; sourceTree = "<group>"; };
 		A7F338A211C0EFCA00A320A7 /* ShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowElement.h; sourceTree = "<group>"; };
 		A809F1450B73793A002E4D7F /* RenderSVGGradientStop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGGradientStop.h; sourceTree = "<group>"; };
@@ -14545,8 +14541,6 @@
 				93309DC6099E64910056E581 /* SplitTextNodeContainingElementCommand.cpp */,
 				93309DC7099E64910056E581 /* SplitTextNodeContainingElementCommand.h */,
 				93309DC8099E64910056E581 /* TextAffinity.h */,
-				A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */,
-				A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */,
 				93309DC9099E64910056E581 /* TextGranularity.h */,
 				93309DCC099E64910056E581 /* TextIterator.cpp */,
 				93309DCD099E64910056E581 /* TextIterator.h */,
@@ -21012,7 +21006,6 @@
 				B2C3DA340D006C1D00EF6F26 /* TextBoundaries.h in Headers */,
 				B2C3DA360D006C1D00EF6F26 /* TextBreakIterator.h in Headers */,
 				B2C3DA380D006C1D00EF6F26 /* TextBreakIteratorInternalICU.h in Headers */,
-				A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */,
 				B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */,
 				B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */,
 				B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */,
@@ -23613,7 +23606,6 @@
 				B2AFFC970D00A5DF0030074D /* TextBoundaries.mm in Sources */,
 				B2C3DA370D006C1D00EF6F26 /* TextBreakIteratorICU.cpp in Sources */,
 				B2AFFC980D00A5DF0030074D /* TextBreakIteratorInternalICUMac.mm in Sources */,
-				A7DBF8DD1276919C006B6008 /* TextCheckingHelper.cpp in Sources */,
 				B2C3DA390D006C1D00EF6F26 /* TextCodec.cpp in Sources */,
 				B2C3DA3B0D006C1D00EF6F26 /* TextCodecICU.cpp in Sources */,
 				B2C3DA3D0D006C1D00EF6F26 /* TextCodecLatin1.cpp in Sources */,
diff --git a/WebCore/editing/EditingAllInOne.cpp b/WebCore/editing/EditingAllInOne.cpp
index 81483f8..ba484be 100644
--- a/WebCore/editing/EditingAllInOne.cpp
+++ b/WebCore/editing/EditingAllInOne.cpp
@@ -65,7 +65,6 @@
 #include <SplitElementCommand.cpp>
 #include <SplitTextNodeCommand.cpp>
 #include <SplitTextNodeContainingElementCommand.cpp>
-#include <TextCheckingHelper.cpp>
 #include <TextIterator.cpp>
 #include <TypingCommand.cpp>
 #include <UnlinkCommand.cpp>
diff --git a/WebCore/editing/Editor.cpp b/WebCore/editing/Editor.cpp
index c74d765..169b765 100644
--- a/WebCore/editing/Editor.cpp
+++ b/WebCore/editing/Editor.cpp
@@ -62,7 +62,6 @@
 #include "NodeList.h"
 #include "Page.h"
 #include "Pasteboard.h"
-#include "TextCheckingHelper.h"
 #include "RemoveFormatCommand.h"
 #include "RenderBlock.h"
 #include "RenderPart.h"
@@ -1660,6 +1659,328 @@ void Editor::learnSpelling()
     client()->learnWord(text);
 }
 
+static String findFirstMisspellingInRange(EditorClient* client, Range* searchRange, int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange)
+{
+    ASSERT_ARG(client, client);
+    ASSERT_ARG(searchRange, searchRange);
+    
+    WordAwareIterator it(searchRange);
+    firstMisspellingOffset = 0;
+    
+    String firstMisspelling;
+    int currentChunkOffset = 0;
+
+    while (!it.atEnd()) {
+        const UChar* chars = it.characters();
+        int len = it.length();
+        
+        // Skip some work for one-space-char hunks
+        if (!(len == 1 && chars[0] == ' ')) {
+            
+            int misspellingLocation = -1;
+            int misspellingLength = 0;
+            client->checkSpellingOfString(chars, len, &misspellingLocation, &misspellingLength);
+
+            // 5490627 shows that there was some code path here where the String constructor below crashes.
+            // We don't know exactly what combination of bad input caused this, so we're making this much
+            // more robust against bad input on release builds.
+            ASSERT(misspellingLength >= 0);
+            ASSERT(misspellingLocation >= -1);
+            ASSERT(!misspellingLength || misspellingLocation >= 0);
+            ASSERT(misspellingLocation < len);
+            ASSERT(misspellingLength <= len);
+            ASSERT(misspellingLocation + misspellingLength <= len);
+            
+            if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < len && misspellingLength <= len && misspellingLocation + misspellingLength <= len) {
+                
+                // Compute range of misspelled word
+                RefPtr<Range> misspellingRange = TextIterator::subrange(searchRange, currentChunkOffset + misspellingLocation, misspellingLength);
+
+                // Remember first-encountered misspelling and its offset.
+                if (!firstMisspelling) {
+                    firstMisspellingOffset = currentChunkOffset + misspellingLocation;
+                    firstMisspelling = String(chars + misspellingLocation, misspellingLength);
+                    firstMisspellingRange = misspellingRange;
+                }
+
+                // Store marker for misspelled word.
+                ExceptionCode ec = 0;
+                misspellingRange->startContainer(ec)->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
+                ASSERT(!ec);
+
+                // Bail out if we're marking only the first misspelling, and not all instances.
+                if (!markAll)
+                    break;
+            }
+        }
+        
+        currentChunkOffset += len;
+        it.advance();
+    }
+    
+    return firstMisspelling;
+}
+
+#ifndef BUILDING_ON_TIGER
+
+static PassRefPtr<Range> paragraphAlignedRangeForRange(Range* arbitraryRange, int& offsetIntoParagraphAlignedRange, String& paragraphString)
+{
+    ASSERT_ARG(arbitraryRange, arbitraryRange);
+    
+    ExceptionCode ec = 0;
+    
+    // Expand range to paragraph boundaries
+    RefPtr<Range> paragraphRange = arbitraryRange->cloneRange(ec);
+    setStart(paragraphRange.get(), startOfParagraph(arbitraryRange->startPosition()));
+    setEnd(paragraphRange.get(), endOfParagraph(arbitraryRange->endPosition()));
+    
+    // Compute offset from start of expanded range to start of original range
+    RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), arbitraryRange->startPosition());
+    offsetIntoParagraphAlignedRange = TextIterator::rangeLength(offsetAsRange.get());
+    
+    // Fill in out parameter with string representing entire paragraph range.
+    // Someday we might have a caller that doesn't use this, but for now all callers do.
+    paragraphString = plainText(paragraphRange.get());
+
+    return paragraphRange;
+}
+
+static int findFirstGrammarDetailInRange(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int /*badGrammarPhraseLength*/, Range *searchRange, int startOffset, int endOffset, bool markAll)
+{
+    // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).
+    // Optionally add a DocumentMarker for each detail in the range.
+    int earliestDetailLocationSoFar = -1;
+    int earliestDetailIndex = -1;
+    for (unsigned i = 0; i < grammarDetails.size(); i++) {
+        const GrammarDetail* detail = &grammarDetails[i];
+        ASSERT(detail->length > 0 && detail->location >= 0);
+        
+        int detailStartOffsetInParagraph = badGrammarPhraseLocation + detail->location;
+        
+        // Skip this detail if it starts before the original search range
+        if (detailStartOffsetInParagraph < startOffset)
+            continue;
+        
+        // Skip this detail if it starts after the original search range
+        if (detailStartOffsetInParagraph >= endOffset)
+            continue;
+        
+        if (markAll) {
+            RefPtr<Range> badGrammarRange = TextIterator::subrange(searchRange, badGrammarPhraseLocation - startOffset + detail->location, detail->length);
+            ExceptionCode ec = 0;
+            badGrammarRange->startContainer(ec)->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription);
+            ASSERT(!ec);
+        }
+        
+        // Remember this detail only if it's earlier than our current candidate (the details aren't in a guaranteed order)
+        if (earliestDetailIndex < 0 || earliestDetailLocationSoFar > detail->location) {
+            earliestDetailIndex = i;
+            earliestDetailLocationSoFar = detail->location;
+        }
+    }
+    
+    return earliestDetailIndex;
+}
+    
+static String findFirstBadGrammarInRange(EditorClient* client, Range* searchRange, GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll)
+{
+    ASSERT_ARG(client, client);
+    ASSERT_ARG(searchRange, searchRange);
+    
+    // Initialize out parameters; these will be updated if we find something to return.
+    outGrammarDetail.location = -1;
+    outGrammarDetail.length = 0;
+    outGrammarDetail.guesses.clear();
+    outGrammarDetail.userDescription = "";
+    outGrammarPhraseOffset = 0;
+    
+    String firstBadGrammarPhrase;
+
+    // Expand the search range to encompass entire paragraphs, since grammar checking needs that much context.
+    // Determine the character offset from the start of the paragraph to the start of the original search range,
+    // since we will want to ignore results in this area.
+    int searchRangeStartOffset;
+    String paragraphString;
+    RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(searchRange, searchRangeStartOffset, paragraphString);
+        
+    // Determine the character offset from the start of the paragraph to the end of the original search range, 
+    // since we will want to ignore results in this area also.
+    int searchRangeEndOffset = searchRangeStartOffset + TextIterator::rangeLength(searchRange);
+        
+    // Start checking from beginning of paragraph, but skip past results that occur before the start of the original search range.
+    int startOffset = 0;
+    while (startOffset < searchRangeEndOffset) {
+        Vector<GrammarDetail> grammarDetails;
+        int badGrammarPhraseLocation = -1;
+        int badGrammarPhraseLength = 0;
+        client->checkGrammarOfString(paragraphString.characters() + startOffset, paragraphString.length() - startOffset, grammarDetails, &badGrammarPhraseLocation, &badGrammarPhraseLength);
+        
+        if (!badGrammarPhraseLength) {
+            ASSERT(badGrammarPhraseLocation == -1);
+            return String();
+        }
+
+        ASSERT(badGrammarPhraseLocation >= 0);
+        badGrammarPhraseLocation += startOffset;
+
+        
+        // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).
+        int badGrammarIndex = findFirstGrammarDetailInRange(grammarDetails, badGrammarPhraseLocation, badGrammarPhraseLength, searchRange, searchRangeStartOffset, searchRangeEndOffset, markAll);
+        if (badGrammarIndex >= 0) {
+            ASSERT(static_cast<unsigned>(badGrammarIndex) < grammarDetails.size());
+            outGrammarDetail = grammarDetails[badGrammarIndex];
+        }
+
+        // If we found a detail in range, then we have found the first bad phrase (unless we found one earlier but
+        // kept going so we could mark all instances).
+        if (badGrammarIndex >= 0 && firstBadGrammarPhrase.isEmpty()) {
+            outGrammarPhraseOffset = badGrammarPhraseLocation - searchRangeStartOffset;
+            firstBadGrammarPhrase = paragraphString.substring(badGrammarPhraseLocation, badGrammarPhraseLength);
+            
+            // Found one. We're done now, unless we're marking each instance.
+            if (!markAll)
+                break;
+        }
+
+        // These results were all between the start of the paragraph and the start of the search range; look
+        // beyond this phrase.
+        startOffset = badGrammarPhraseLocation + badGrammarPhraseLength;
+    }
+    
+    return firstBadGrammarPhrase;
+}
+    
+#endif /* not BUILDING_ON_TIGER */
+
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+static String findFirstMisspellingOrBadGrammarInRange(EditorClient* client, Range* searchRange, bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail)
+{
+    ASSERT_ARG(client, client);
+    ASSERT_ARG(searchRange, searchRange);
+    
+    String firstFoundItem;
+    String misspelledWord;
+    String badGrammarPhrase;
+    ExceptionCode ec = 0;
+    
+    // Initialize out parameters; these will be updated if we find something to return.
+    outIsSpelling = true;
+    outFirstFoundOffset = 0;
+    outGrammarDetail.location = -1;
+    outGrammarDetail.length = 0;
+    outGrammarDetail.guesses.clear();
+    outGrammarDetail.userDescription = "";
+    
+    // Expand the search range to encompass entire paragraphs, since text checking needs that much context.
+    // Determine the character offset from the start of the paragraph to the start of the original search range,
+    // since we will want to ignore results in this area.
+    RefPtr<Range> paragraphRange = searchRange->cloneRange(ec);
+    setStart(paragraphRange.get(), startOfParagraph(searchRange->startPosition()));
+    int totalRangeLength = TextIterator::rangeLength(paragraphRange.get());
+    setEnd(paragraphRange.get(), endOfParagraph(searchRange->startPosition()));
+    
+    RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->startPosition());
+    int searchRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get());
+    int totalLengthProcessed = 0;
+    
+    bool firstIteration = true;
+    bool lastIteration = false;
+    while (totalLengthProcessed < totalRangeLength) {
+        // Iterate through the search range by paragraphs, checking each one for spelling and grammar.
+        int currentLength = TextIterator::rangeLength(paragraphRange.get());
+        int currentStartOffset = firstIteration ? searchRangeStartOffset : 0;
+        int currentEndOffset = currentLength;
+        if (inSameParagraph(paragraphRange->startPosition(), searchRange->endPosition())) {
+            // Determine the character offset from the end of the original search range to the end of the paragraph,
+            // since we will want to ignore results in this area.
+            RefPtr<Range> endOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->endPosition());
+            currentEndOffset = TextIterator::rangeLength(endOffsetAsRange.get());
+            lastIteration = true;
+        }
+        if (currentStartOffset < currentEndOffset) {
+            String paragraphString = plainText(paragraphRange.get());
+            if (paragraphString.length() > 0) {
+                bool foundGrammar = false;
+                int spellingLocation = 0;
+                int grammarPhraseLocation = 0;
+                int grammarDetailLocation = 0;
+                unsigned grammarDetailIndex = 0;
+                
+                Vector<TextCheckingResult> results;
+                uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
+                client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results);
+                
+                for (unsigned i = 0; i < results.size(); i++) {
+                    const TextCheckingResult* result = &results[i];
+                    if (result->type == TextCheckingTypeSpelling && result->location >= currentStartOffset && result->location + result->length <= currentEndOffset) {
+                        ASSERT(result->length > 0 && result->location >= 0);
+                        spellingLocation = result->location;
+                        misspelledWord = paragraphString.substring(result->location, result->length);
+                        ASSERT(misspelledWord.length());
+                        break;
+                    }
+                    if (checkGrammar && result->type == TextCheckingTypeGrammar && result->location < currentEndOffset && result->location + result->length > currentStartOffset) {
+                        ASSERT(result->length > 0 && result->location >= 0);
+                        // We can't stop after the first grammar result, since there might still be a spelling result after
+                        // it begins but before the first detail in it, but we can stop if we find a second grammar result.
+                        if (foundGrammar)
+                            break;
+                        for (unsigned j = 0; j < result->details.size(); j++) {
+                            const GrammarDetail* detail = &result->details[j];
+                            ASSERT(detail->length > 0 && detail->location >= 0);
+                            if (result->location + detail->location >= currentStartOffset && result->location + detail->location + detail->length <= currentEndOffset && (!foundGrammar || result->location + detail->location < grammarDetailLocation)) {
+                                grammarDetailIndex = j;
+                                grammarDetailLocation = result->location + detail->location;
+                                foundGrammar = true;
+                            }
+                        }
+                        if (foundGrammar) {
+                            grammarPhraseLocation = result->location;
+                            outGrammarDetail = result->details[grammarDetailIndex];
+                            badGrammarPhrase = paragraphString.substring(result->location, result->length);
+                            ASSERT(badGrammarPhrase.length());
+                        }
+                    }
+                }
+
+                if (!misspelledWord.isEmpty() && (!checkGrammar || badGrammarPhrase.isEmpty() || spellingLocation <= grammarDetailLocation)) {
+                    int spellingOffset = spellingLocation - currentStartOffset;
+                    if (!firstIteration) {
+                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition());
+                        spellingOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());
+                    }
+                    outIsSpelling = true;
+                    outFirstFoundOffset = spellingOffset;
+                    firstFoundItem = misspelledWord;
+                    break;
+                }
+                if (checkGrammar && !badGrammarPhrase.isEmpty()) {
+                    int grammarPhraseOffset = grammarPhraseLocation - currentStartOffset;
+                    if (!firstIteration) {
+                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition());
+                        grammarPhraseOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());
+                    }
+                    outIsSpelling = false;
+                    outFirstFoundOffset = grammarPhraseOffset;
+                    firstFoundItem = badGrammarPhrase;
+                    break;
+                }
+            }
+        }
+        if (lastIteration || totalLengthProcessed + currentLength >= totalRangeLength)
+            break;
+        VisiblePosition newParagraphStart = startOfNextParagraph(paragraphRange->endPosition());
+        setStart(paragraphRange.get(), newParagraphStart);
+        setEnd(paragraphRange.get(), endOfParagraph(newParagraphStart));
+        firstIteration = false;
+        totalLengthProcessed += currentLength;
+    }
+    return firstFoundItem;
+}
+
+#endif
+
 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
 {
     ExceptionCode ec = 0;
@@ -1671,8 +1992,6 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
     // repeated "check spelling" commands work.
     VisibleSelection selection(frame()->selection()->selection());
     RefPtr<Range> spellingSearchRange(rangeOfContents(frame()->document()));
-    TextCheckingHelper checker(client(), spellingSearchRange);
-
     bool startedWithSelection = false;
     if (selection.start().node()) {
         startedWithSelection = true;
@@ -1738,7 +2057,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
     bool isSpelling = true;
     int foundOffset = 0;
     GrammarDetail grammarDetail;
-    String foundItem = checker.findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
+    String foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
     if (isSpelling) {
         misspelledWord = foundItem;
         misspellingOffset = foundOffset;
@@ -1748,7 +2067,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
     }
 #else
     RefPtr<Range> firstMisspellingRange;
-    String misspelledWord = checker.findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
+    String misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRange.get(), misspellingOffset, false, firstMisspellingRange);
     String badGrammarPhrase;
 
 #ifndef BUILDING_ON_TIGER
@@ -1765,7 +2084,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
     }
     
     if (isGrammarCheckingEnabled())
-        badGrammarPhrase = checker.findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
+        badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRange.get(), grammarDetail, grammarPhraseOffset, false);
 #endif
 #endif
     
@@ -1778,7 +2097,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
         
 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
         grammarSearchRange = spellingSearchRange->cloneRange(ec);
-        foundItem = checker.findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
+        foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
         if (isSpelling) {
             misspelledWord = foundItem;
             misspellingOffset = foundOffset;
@@ -1787,7 +2106,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
             grammarPhraseOffset = foundOffset;
         }
 #else
-        misspelledWord = checker.findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
+        misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRange.get(), misspellingOffset, false, firstMisspellingRange);
 
 #ifndef BUILDING_ON_TIGER
         grammarSearchRange = spellingSearchRange->cloneRange(ec);
@@ -1798,7 +2117,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
             grammarSearchRange->setEnd(chars.range()->startContainer(ec), chars.range()->startOffset(ec), ec);
         }
         if (isGrammarCheckingEnabled())
-            badGrammarPhrase = checker.findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
+            badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRange.get(), grammarDetail, grammarPhraseOffset, false);
 #endif
 #endif
     }
@@ -1862,13 +2181,60 @@ bool Editor::isSelectionMisspelled()
     return true;
 }
 
+#ifndef BUILDING_ON_TIGER
+static bool isRangeUngrammatical(EditorClient* client, Range *range, Vector<String>& guessesVector)
+{
+    if (!client)
+        return false;
+
+    ExceptionCode ec;
+    if (!range || range->collapsed(ec))
+        return false;
+    
+    // Returns true only if the passed range exactly corresponds to a bad grammar detail range. This is analogous
+    // to isSelectionMisspelled. It's not good enough for there to be some bad grammar somewhere in the range,
+    // or overlapping the range; the ranges must exactly match.
+    guessesVector.clear();
+    int grammarPhraseOffset;
+    
+    GrammarDetail grammarDetail;
+    String badGrammarPhrase = findFirstBadGrammarInRange(client, range, grammarDetail, grammarPhraseOffset, false);    
+    
+    // No bad grammar in these parts at all.
+    if (badGrammarPhrase.isEmpty())
+        return false;
+    
+    // Bad grammar, but phrase (e.g. sentence) starts beyond start of range.
+    if (grammarPhraseOffset > 0)
+        return false;
+    
+    ASSERT(grammarDetail.location >= 0 && grammarDetail.length > 0);
+    
+    // Bad grammar, but start of detail (e.g. ungrammatical word) doesn't match start of range
+    if (grammarDetail.location + grammarPhraseOffset)
+        return false;
+    
+    // Bad grammar at start of range, but end of bad grammar is before or after end of range
+    if (grammarDetail.length != TextIterator::rangeLength(range))
+        return false;
+    
+    // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
+    // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
+    // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling
+    // or a grammar error.
+    client->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
+    
+    return true;
+}
+#endif
+
 bool Editor::isSelectionUngrammatical()
 {
 #ifdef BUILDING_ON_TIGER
     return false;
 #else
     Vector<String> ignoredGuesses;
-    return TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).isUngrammatical(ignoredGuesses);
+    return isRangeUngrammatical(client(), frame()->selection()->toNormalizedRange().get(), ignoredGuesses);
 #endif
 }
 
@@ -1878,8 +2244,8 @@ Vector<String> Editor::guessesForUngrammaticalSelection()
     return Vector<String>();
 #else
     Vector<String> guesses;
-    // Ignore the result of isUngrammatical; we just want the guesses, whether or not there are any
-    TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).isUngrammatical(guesses);
+    // Ignore the result of isRangeUngrammatical; we just want the guesses, whether or not there are any
+    isRangeUngrammatical(client(), frame()->selection()->toNormalizedRange().get(), guesses);
     return guesses;
 #endif
 }
@@ -1895,10 +2261,72 @@ Vector<String> Editor::guessesForMisspelledSelection()
     return guesses;
 }
 
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+static Vector<String> guessesForMisspelledOrUngrammaticalRange(EditorClient* client, Range *range, bool checkGrammar, bool& misspelled, bool& ungrammatical)
+{
+    Vector<String> guesses;
+    ExceptionCode ec;
+    misspelled = false;
+    ungrammatical = false;
+    
+    if (!client || !range || range->collapsed(ec))
+        return guesses;
+
+    // Expand the range to encompass entire paragraphs, since text checking needs that much context.
+    int rangeStartOffset;
+    String paragraphString;
+    RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(range, rangeStartOffset, paragraphString);
+    int rangeLength = TextIterator::rangeLength(range);
+    if (!rangeLength || !paragraphString.length())
+        return guesses;
+
+    Vector<TextCheckingResult> results;
+    uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
+    client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results);
+    
+    for (unsigned i = 0; i < results.size(); i++) {
+        const TextCheckingResult* result = &results[i];
+        if (result->type == TextCheckingTypeSpelling && result->location == rangeStartOffset && result->length == rangeLength) {
+            String misspelledWord = paragraphString.substring(rangeStartOffset, rangeLength);
+            ASSERT(misspelledWord.length());
+            client->getGuessesForWord(misspelledWord, guesses);
+            client->updateSpellingUIWithMisspelledWord(misspelledWord);
+            misspelled = true;
+            return guesses;
+        }
+    }
+    
+    if (!checkGrammar)
+        return guesses;
+        
+    for (unsigned i = 0; i < results.size(); i++) {
+        const TextCheckingResult* result = &results[i];
+        if (result->type == TextCheckingTypeGrammar && result->location <= rangeStartOffset && result->location + result->length >= rangeStartOffset + rangeLength) {
+            for (unsigned j = 0; j < result->details.size(); j++) {
+                const GrammarDetail* detail = &result->details[j];
+                ASSERT(detail->length > 0 && detail->location >= 0);
+                if (result->location + detail->location == rangeStartOffset && detail->length == rangeLength) {
+                    String badGrammarPhrase = paragraphString.substring(result->location, result->length);
+                    ASSERT(badGrammarPhrase.length());
+                    for (unsigned k = 0; k < detail->guesses.size(); k++)
+                        guesses.append(detail->guesses[k]);
+                    client->updateSpellingUIWithGrammarString(badGrammarPhrase, *detail);
+                    ungrammatical = true;
+                    return guesses;
+                }
+            }
+        }
+    }
+    return guesses;
+}
+
+#endif
+
 Vector<String> Editor::guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical)
 {
 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-    return TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);
+    return guessesForMisspelledOrUngrammaticalRange(client(), frame()->selection()->toNormalizedRange().get(), isGrammarCheckingEnabled(), misspelled, ungrammatical);
 #else
     misspelled = isSelectionMisspelled();
     if (misspelled) {
@@ -2075,15 +2503,34 @@ void Editor::markMisspellingsAfterTypingToPosition(const VisiblePosition &p)
     markBadGrammar(VisibleSelection(startOfSentence(p), endOfSentence(p)));
 #endif
 }
+
+static void markAllMisspellingsInRange(EditorClient* client, Range* searchRange, RefPtr<Range>& firstMisspellingRange)
+{
+    // Use the "markAll" feature of findFirstMisspellingInRange. Ignore the return value and the "out parameter";
+    // all we need to do is mark every instance.
+    int ignoredOffset;
+    findFirstMisspellingInRange(client, searchRange, ignoredOffset, true, firstMisspellingRange);
+}
+
+#ifndef BUILDING_ON_TIGER
+static void markAllBadGrammarInRange(EditorClient* client, Range* searchRange)
+{
+    // Use the "markAll" feature of findFirstBadGrammarInRange. Ignore the return value and "out parameters"; all we need to
+    // do is mark every instance.
+    GrammarDetail ignoredGrammarDetail;
+    int ignoredOffset;
+    findFirstBadGrammarInRange(client, searchRange, ignoredGrammarDetail, ignoredOffset, true);
+}
+#endif
     
-void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
+static void markMisspellingsOrBadGrammar(Editor* editor, const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
 {
     // This function is called with a selection already expanded to word boundaries.
     // Might be nice to assert that here.
     
     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
     // grammar checking can only be on if spell checking is also on.
-    if (!isContinuousSpellCheckingEnabled())
+    if (!editor->isContinuousSpellCheckingEnabled())
         return;
     
     RefPtr<Range> searchRange(selection.toNormalizedRange());
@@ -2095,22 +2542,21 @@ void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, boo
     if (!editableNode || !editableNode->isContentEditable())
         return;
 
-    if (!isSpellCheckingEnabledInFocusedNode())
+    if (!editor->isSpellCheckingEnabledInFocusedNode())
         return;
 
     // Get the spell checker if it is available
-    if (!client())
+    if (!editor->client())
         return;
     
-    TextCheckingHelper checker(client(), searchRange);
     if (checkSpelling)
-        checker.markAllMisspellings(firstMisspellingRange);
+        markAllMisspellingsInRange(editor->client(), searchRange.get(), firstMisspellingRange);
     else {
 #ifdef BUILDING_ON_TIGER
         ASSERT_NOT_REACHED();
 #else
-        if (isGrammarCheckingEnabled())
-            checker.markAllBadGrammar();
+        if (editor->isGrammarCheckingEnabled())
+            markAllBadGrammarInRange(editor->client(), searchRange.get());
 #endif
     }    
 }
@@ -2130,14 +2576,14 @@ bool Editor::isSpellCheckingEnabledInFocusedNode() const
 
 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
 {
-    markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
+    markMisspellingsOrBadGrammar(this, selection, true, firstMisspellingRange);
 }
     
 void Editor::markBadGrammar(const VisibleSelection& selection)
 {
 #ifndef BUILDING_ON_TIGER
     RefPtr<Range> firstMisspellingRange;
-    markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
+    markMisspellingsOrBadGrammar(this, selection, false, firstMisspellingRange);
 #else
     UNUSED_PARAM(selection);
 #endif
@@ -2187,16 +2633,15 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions textCh
     bool adjustSelectionForParagraphBoundaries = false;
     String paragraphString;
     RefPtr<Range> paragraphRange;
-    TextCheckingHelper checker(client(), grammarRange);
 
     if (shouldMarkGrammar) {
         // The spelling range should be contained in the paragraph-aligned extension of the grammar range.
-        paragraphRange = checker.paragraphAlignedRange(grammarRangeStartOffset, paragraphString);
+        paragraphRange = paragraphAlignedRangeForRange(grammarRange, grammarRangeStartOffset, paragraphString);
         RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), spellingRange->startPosition());
         spellingRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get());
         grammarRangeEndOffset = grammarRangeStartOffset + TextIterator::rangeLength(grammarRange);
     } else {
-        paragraphRange = checker.paragraphAlignedRange(spellingRangeStartOffset, paragraphString);
+        paragraphRange = paragraphAlignedRangeForRange(spellingRange, spellingRangeStartOffset, paragraphString);
     }
     spellingRangeEndOffset = spellingRangeStartOffset + TextIterator::rangeLength(spellingRange);
     paragraphLength = paragraphString.length();
@@ -2386,10 +2831,10 @@ void Editor::changeBackToReplacedString(const String& replacedString)
     RefPtr<Range> selection = selectedRange();
     if (!shouldInsertText(replacedString, selection.get(), EditorInsertActionPasted))
         return;
-    
+        
     String paragraphString;
     int selectionOffset;
-    RefPtr<Range> paragraphRange = TextCheckingHelper(client(), selection).paragraphAlignedRange(selectionOffset, paragraphString);
+    RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(selection.get(), selectionOffset, paragraphString);
     replaceSelectionWithText(replacedString, false, false);
     RefPtr<Range> changedRange = TextIterator::subrange(paragraphRange.get(), selectionOffset, replacedString.length());
     changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::Replacement, String());
diff --git a/WebCore/editing/Editor.h b/WebCore/editing/Editor.h
index 110e3f9..e942560 100644
--- a/WebCore/editing/Editor.h
+++ b/WebCore/editing/Editor.h
@@ -404,7 +404,6 @@ private:
     void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
     void writeSelectionToPasteboard(Pasteboard*);
     void revealSelectionAfterEditingOperation();
-    void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
 
     void selectComposition();
     void confirmComposition(const String&, bool preserveSelection);
diff --git a/WebCore/editing/TextCheckingHelper.cpp b/WebCore/editing/TextCheckingHelper.cpp
deleted file mode 100644
index 49674ff..0000000
--- a/WebCore/editing/TextCheckingHelper.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "TextCheckingHelper.h"
-
-#include "Range.h"
-#include "TextIterator.h"
-#include "VisiblePosition.h"
-#include "visible_units.h"
-
-namespace WebCore {
-
-TextCheckingHelper::TextCheckingHelper(EditorClient* client, PassRefPtr<Range> range)
-    : m_client(client)
-    , m_range(range)
-{
-    ASSERT_ARG(m_client, m_client);
-    ASSERT_ARG(m_range, m_range);
-}
-
-TextCheckingHelper::~TextCheckingHelper()
-{
-}
-
-PassRefPtr<Range> TextCheckingHelper::paragraphAlignedRange(int& offsetIntoParagraphAlignedRange, String& paragraphString) const
-{
-#ifndef BUILDING_ON_TIGER
-    ExceptionCode ec = 0;
-    
-    // Expand range to paragraph boundaries
-    RefPtr<Range> paragraphRange = m_range->cloneRange(ec);
-    setStart(paragraphRange.get(), startOfParagraph(m_range->startPosition()));
-    setEnd(paragraphRange.get(), endOfParagraph(m_range->endPosition()));
-    
-    // Compute offset from start of expanded range to start of original range
-    RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), m_range->startPosition());
-    offsetIntoParagraphAlignedRange = TextIterator::rangeLength(offsetAsRange.get());
-    
-    // Fill in out parameter with string representing entire paragraph range.
-    // Someday we might have a caller that doesn't use this, but for now all callers do.
-    paragraphString = plainText(paragraphRange.get());
-
-    return paragraphRange;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(offsetIntoParagraphAlignedRange);
-    UNUSED_PARAM(paragraphString);
-    return PassRefPtr<Range>(0);
-#endif
-}
-
-String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange)
-{
-    WordAwareIterator it(m_range.get());
-    firstMisspellingOffset = 0;
-    
-    String firstMisspelling;
-    int currentChunkOffset = 0;
-
-    while (!it.atEnd()) {
-        const UChar* chars = it.characters();
-        int len = it.length();
-        
-        // Skip some work for one-space-char hunks
-        if (!(len == 1 && chars[0] == ' ')) {
-            
-            int misspellingLocation = -1;
-            int misspellingLength = 0;
-            m_client->checkSpellingOfString(chars, len, &misspellingLocation, &misspellingLength);
-
-            // 5490627 shows that there was some code path here where the String constructor below crashes.
-            // We don't know exactly what combination of bad input caused this, so we're making this much
-            // more robust against bad input on release builds.
-            ASSERT(misspellingLength >= 0);
-            ASSERT(misspellingLocation >= -1);
-            ASSERT(!misspellingLength || misspellingLocation >= 0);
-            ASSERT(misspellingLocation < len);
-            ASSERT(misspellingLength <= len);
-            ASSERT(misspellingLocation + misspellingLength <= len);
-            
-            if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < len && misspellingLength <= len && misspellingLocation + misspellingLength <= len) {
-                
-                // Compute range of misspelled word
-                RefPtr<Range> misspellingRange = TextIterator::subrange(m_range.get(), currentChunkOffset + misspellingLocation, misspellingLength);
-
-                // Remember first-encountered misspelling and its offset.
-                if (!firstMisspelling) {
-                    firstMisspellingOffset = currentChunkOffset + misspellingLocation;
-                    firstMisspelling = String(chars + misspellingLocation, misspellingLength);
-                    firstMisspellingRange = misspellingRange;
-                }
-
-                // Store marker for misspelled word.
-                ExceptionCode ec = 0;
-                misspellingRange->startContainer(ec)->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
-                ASSERT(!ec);
-
-                // Bail out if we're marking only the first misspelling, and not all instances.
-                if (!markAll)
-                    break;
-            }
-        }
-        
-        currentChunkOffset += len;
-        it.advance();
-    }
-    
-    return firstMisspelling;
-}
-
-String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail)
-{
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-    String firstFoundItem;
-    String misspelledWord;
-    String badGrammarPhrase;
-    ExceptionCode ec = 0;
-    
-    // Initialize out parameters; these will be updated if we find something to return.
-    outIsSpelling = true;
-    outFirstFoundOffset = 0;
-    outGrammarDetail.location = -1;
-    outGrammarDetail.length = 0;
-    outGrammarDetail.guesses.clear();
-    outGrammarDetail.userDescription = "";
-    
-    // Expand the search range to encompass entire paragraphs, since text checking needs that much context.
-    // Determine the character offset from the start of the paragraph to the start of the original search range,
-    // since we will want to ignore results in this area.
-    RefPtr<Range> paragraphRange = m_range->cloneRange(ec);
-    setStart(paragraphRange.get(), startOfParagraph(m_range->startPosition()));
-    int totalRangeLength = TextIterator::rangeLength(paragraphRange.get());
-    setEnd(paragraphRange.get(), endOfParagraph(m_range->startPosition()));
-    
-    RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), m_range->startPosition());
-    int rangeStartOffset = TextIterator::rangeLength(offsetAsRange.get());
-    int totalLengthProcessed = 0;
-    
-    bool firstIteration = true;
-    bool lastIteration = false;
-    while (totalLengthProcessed < totalRangeLength) {
-        // Iterate through the search range by paragraphs, checking each one for spelling and grammar.
-        int currentLength = TextIterator::rangeLength(paragraphRange.get());
-        int currentStartOffset = firstIteration ? rangeStartOffset : 0;
-        int currentEndOffset = currentLength;
-        if (inSameParagraph(paragraphRange->startPosition(), m_range->endPosition())) {
-            // Determine the character offset from the end of the original search range to the end of the paragraph,
-            // since we will want to ignore results in this area.
-            RefPtr<Range> endOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), m_range->endPosition());
-            currentEndOffset = TextIterator::rangeLength(endOffsetAsRange.get());
-            lastIteration = true;
-        }
-        if (currentStartOffset < currentEndOffset) {
-            String paragraphString = plainText(paragraphRange.get());
-            if (paragraphString.length() > 0) {
-                bool foundGrammar = false;
-                int spellingLocation = 0;
-                int grammarPhraseLocation = 0;
-                int grammarDetailLocation = 0;
-                unsigned grammarDetailIndex = 0;
-                
-                Vector<TextCheckingResult> results;
-                uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
-                m_client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results);
-                
-                for (unsigned i = 0; i < results.size(); i++) {
-                    const TextCheckingResult* result = &results[i];
-                    if (result->type == TextCheckingTypeSpelling && result->location >= currentStartOffset && result->location + result->length <= currentEndOffset) {
-                        ASSERT(result->length > 0 && result->location >= 0);
-                        spellingLocation = result->location;
-                        misspelledWord = paragraphString.substring(result->location, result->length);
-                        ASSERT(misspelledWord.length());
-                        break;
-                    }
-                    if (checkGrammar && result->type == TextCheckingTypeGrammar && result->location < currentEndOffset && result->location + result->length > currentStartOffset) {
-                        ASSERT(result->length > 0 && result->location >= 0);
-                        // We can't stop after the first grammar result, since there might still be a spelling result after
-                        // it begins but before the first detail in it, but we can stop if we find a second grammar result.
-                        if (foundGrammar)
-                            break;
-                        for (unsigned j = 0; j < result->details.size(); j++) {
-                            const GrammarDetail* detail = &result->details[j];
-                            ASSERT(detail->length > 0 && detail->location >= 0);
-                            if (result->location + detail->location >= currentStartOffset && result->location + detail->location + detail->length <= currentEndOffset && (!foundGrammar || result->location + detail->location < grammarDetailLocation)) {
-                                grammarDetailIndex = j;
-                                grammarDetailLocation = result->location + detail->location;
-                                foundGrammar = true;
-                            }
-                        }
-                        if (foundGrammar) {
-                            grammarPhraseLocation = result->location;
-                            outGrammarDetail = result->details[grammarDetailIndex];
-                            badGrammarPhrase = paragraphString.substring(result->location, result->length);
-                            ASSERT(badGrammarPhrase.length());
-                        }
-                    }
-                }
-
-                if (!misspelledWord.isEmpty() && (!checkGrammar || badGrammarPhrase.isEmpty() || spellingLocation <= grammarDetailLocation)) {
-                    int spellingOffset = spellingLocation - currentStartOffset;
-                    if (!firstIteration) {
-                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), m_range->startPosition(), paragraphRange->startPosition());
-                        spellingOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());
-                    }
-                    outIsSpelling = true;
-                    outFirstFoundOffset = spellingOffset;
-                    firstFoundItem = misspelledWord;
-                    break;
-                }
-                if (checkGrammar && !badGrammarPhrase.isEmpty()) {
-                    int grammarPhraseOffset = grammarPhraseLocation - currentStartOffset;
-                    if (!firstIteration) {
-                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), m_range->startPosition(), paragraphRange->startPosition());
-                        grammarPhraseOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());
-                    }
-                    outIsSpelling = false;
-                    outFirstFoundOffset = grammarPhraseOffset;
-                    firstFoundItem = badGrammarPhrase;
-                    break;
-                }
-            }
-        }
-        if (lastIteration || totalLengthProcessed + currentLength >= totalRangeLength)
-            break;
-        VisiblePosition newParagraphStart = startOfNextParagraph(paragraphRange->endPosition());
-        setStart(paragraphRange.get(), newParagraphStart);
-        setEnd(paragraphRange.get(), endOfParagraph(newParagraphStart));
-        firstIteration = false;
-        totalLengthProcessed += currentLength;
-    }
-    return firstFoundItem;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(checkGrammar);
-    UNUSED_PARAM(outIsSpelling);
-    UNUSED_PARAM(outFirstFoundOffset);
-    UNUSED_PARAM(outGrammarDetail);
-    return "";
-#endif
-}
-
-int TextCheckingHelper::findFirstGrammarDetail(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int /*badGrammarPhraseLength*/, int startOffset, int endOffset, bool markAll)
-{
-#ifndef BUILDING_ON_TIGER
-    // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).
-    // Optionally add a DocumentMarker for each detail in the range.
-    int earliestDetailLocationSoFar = -1;
-    int earliestDetailIndex = -1;
-    for (unsigned i = 0; i < grammarDetails.size(); i++) {
-        const GrammarDetail* detail = &grammarDetails[i];
-        ASSERT(detail->length > 0 && detail->location >= 0);
-        
-        int detailStartOffsetInParagraph = badGrammarPhraseLocation + detail->location;
-        
-        // Skip this detail if it starts before the original search range
-        if (detailStartOffsetInParagraph < startOffset)
-            continue;
-        
-        // Skip this detail if it starts after the original search range
-        if (detailStartOffsetInParagraph >= endOffset)
-            continue;
-        
-        if (markAll) {
-            RefPtr<Range> badGrammarRange = TextIterator::subrange(m_range.get(), badGrammarPhraseLocation - startOffset + detail->location, detail->length);
-            ExceptionCode ec = 0;
-            badGrammarRange->startContainer(ec)->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription);
-            ASSERT(!ec);
-        }
-        
-        // Remember this detail only if it's earlier than our current candidate (the details aren't in a guaranteed order)
-        if (earliestDetailIndex < 0 || earliestDetailLocationSoFar > detail->location) {
-            earliestDetailIndex = i;
-            earliestDetailLocationSoFar = detail->location;
-        }
-    }
-    
-    return earliestDetailIndex;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(grammarDetails);
-    UNUSED_PARAM(badGrammarPhraseLocation);
-    UNUSED_PARAM(startOffset);
-    UNUSED_PARAM(endOffset);
-    UNUSED_PARAM(markAll);
-    return 0;
-#endif
-}
-
-String TextCheckingHelper::findFirstBadGrammar(GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll)
-{
-#ifndef BUILDING_ON_TIGER
-    // Initialize out parameters; these will be updated if we find something to return.
-    outGrammarDetail.location = -1;
-    outGrammarDetail.length = 0;
-    outGrammarDetail.guesses.clear();
-    outGrammarDetail.userDescription = "";
-    outGrammarPhraseOffset = 0;
-    
-    String firstBadGrammarPhrase;
-
-    // Expand the search range to encompass entire paragraphs, since grammar checking needs that much context.
-    // Determine the character offset from the start of the paragraph to the start of the original search range,
-    // since we will want to ignore results in this area.
-    int searchRangeStartOffset;
-    String paragraphString;
-    RefPtr<Range> paragraphRange = paragraphAlignedRange(searchRangeStartOffset, paragraphString);
-        
-    // Determine the character offset from the start of the paragraph to the end of the original search range, 
-    // since we will want to ignore results in this area also.
-    int searchRangeEndOffset = searchRangeStartOffset + TextIterator::rangeLength(m_range.get());
-        
-    // Start checking from beginning of paragraph, but skip past results that occur before the start of the original search range.
-    int startOffset = 0;
-    while (startOffset < searchRangeEndOffset) {
-        Vector<GrammarDetail> grammarDetails;
-        int badGrammarPhraseLocation = -1;
-        int badGrammarPhraseLength = 0;
-        m_client->checkGrammarOfString(paragraphString.characters() + startOffset, paragraphString.length() - startOffset, grammarDetails, &badGrammarPhraseLocation, &badGrammarPhraseLength);
-        
-        if (!badGrammarPhraseLength) {
-            ASSERT(badGrammarPhraseLocation == -1);
-            return String();
-        }
-
-        ASSERT(badGrammarPhraseLocation >= 0);
-        badGrammarPhraseLocation += startOffset;
-
-        
-        // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).
-        int badGrammarIndex = findFirstGrammarDetail(grammarDetails, badGrammarPhraseLocation, badGrammarPhraseLength, searchRangeStartOffset, searchRangeEndOffset, markAll);
-        if (badGrammarIndex >= 0) {
-            ASSERT(static_cast<unsigned>(badGrammarIndex) < grammarDetails.size());
-            outGrammarDetail = grammarDetails[badGrammarIndex];
-        }
-
-        // If we found a detail in range, then we have found the first bad phrase (unless we found one earlier but
-        // kept going so we could mark all instances).
-        if (badGrammarIndex >= 0 && firstBadGrammarPhrase.isEmpty()) {
-            outGrammarPhraseOffset = badGrammarPhraseLocation - searchRangeStartOffset;
-            firstBadGrammarPhrase = paragraphString.substring(badGrammarPhraseLocation, badGrammarPhraseLength);
-            
-            // Found one. We're done now, unless we're marking each instance.
-            if (!markAll)
-                break;
-        }
-
-        // These results were all between the start of the paragraph and the start of the search range; look
-        // beyond this phrase.
-        startOffset = badGrammarPhraseLocation + badGrammarPhraseLength;
-    }
-    
-    return firstBadGrammarPhrase;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(outGrammarDetail);
-    UNUSED_PARAM(outGrammarPhraseOffset);
-    UNUSED_PARAM(markAll);
-#endif
-}
-
-
-bool TextCheckingHelper::isUngrammatical(Vector<String>& guessesVector) const
-{
-#ifndef BUILDING_ON_TIGER
-    if (!m_client)
-        return false;
-
-    ExceptionCode ec;
-    if (!m_range || m_range->collapsed(ec))
-        return false;
-    
-    // Returns true only if the passed range exactly corresponds to a bad grammar detail range. This is analogous
-    // to isSelectionMisspelled. It's not good enough for there to be some bad grammar somewhere in the range,
-    // or overlapping the range; the ranges must exactly match.
-    guessesVector.clear();
-    int grammarPhraseOffset;
-    
-    GrammarDetail grammarDetail;
-    String badGrammarPhrase = const_cast<TextCheckingHelper*>(this)->findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);    
-    
-    // No bad grammar in these parts at all.
-    if (badGrammarPhrase.isEmpty())
-        return false;
-    
-    // Bad grammar, but phrase (e.g. sentence) starts beyond start of range.
-    if (grammarPhraseOffset > 0)
-        return false;
-    
-    ASSERT(grammarDetail.location >= 0 && grammarDetail.length > 0);
-    
-    // Bad grammar, but start of detail (e.g. ungrammatical word) doesn't match start of range
-    if (grammarDetail.location + grammarPhraseOffset)
-        return false;
-    
-    // Bad grammar at start of range, but end of bad grammar is before or after end of range
-    if (grammarDetail.length != TextIterator::rangeLength(m_range.get()))
-        return false;
-    
-    // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
-    // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
-    // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling
-    // or a grammar error.
-    m_client->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
-    
-    return true;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(guessesVector);
-    return true;
-#endif
-}
-
-Vector<String> TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange(bool checkGrammar, bool& misspelled, bool& ungrammatical) const
-{
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-    Vector<String> guesses;
-    ExceptionCode ec;
-    misspelled = false;
-    ungrammatical = false;
-    
-    if (!m_client || !m_range || m_range->collapsed(ec))
-        return guesses;
-
-    // Expand the range to encompass entire paragraphs, since text checking needs that much context.
-    int rangeStartOffset;
-    String paragraphString;
-    RefPtr<Range> paragraphRange = paragraphAlignedRange(rangeStartOffset, paragraphString);
-    int rangeLength = TextIterator::rangeLength(m_range.get());
-    if (!rangeLength || !paragraphString.length())
-        return guesses;
-
-    Vector<TextCheckingResult> results;
-    uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
-    m_client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results);
-    
-    for (unsigned i = 0; i < results.size(); i++) {
-        const TextCheckingResult* result = &results[i];
-        if (result->type == TextCheckingTypeSpelling && result->location == rangeStartOffset && result->length == rangeLength) {
-            String misspelledWord = paragraphString.substring(rangeStartOffset, rangeLength);
-            ASSERT(misspelledWord.length());
-            m_client->getGuessesForWord(misspelledWord, guesses);
-            m_client->updateSpellingUIWithMisspelledWord(misspelledWord);
-            misspelled = true;
-            return guesses;
-        }
-    }
-    
-    if (!checkGrammar)
-        return guesses;
-        
-    for (unsigned i = 0; i < results.size(); i++) {
-        const TextCheckingResult* result = &results[i];
-        if (result->type == TextCheckingTypeGrammar && result->location <= rangeStartOffset && result->location + result->length >= rangeStartOffset + rangeLength) {
-            for (unsigned j = 0; j < result->details.size(); j++) {
-                const GrammarDetail* detail = &result->details[j];
-                ASSERT(detail->length > 0 && detail->location >= 0);
-                if (result->location + detail->location == rangeStartOffset && detail->length == rangeLength) {
-                    String badGrammarPhrase = paragraphString.substring(result->location, result->length);
-                    ASSERT(badGrammarPhrase.length());
-                    for (unsigned k = 0; k < detail->guesses.size(); k++)
-                        guesses.append(detail->guesses[k]);
-                    m_client->updateSpellingUIWithGrammarString(badGrammarPhrase, *detail);
-                    ungrammatical = true;
-                    return guesses;
-                }
-            }
-        }
-    }
-    return guesses;
-#else
-    ASSERT_NOT_REACHED();
-    UNUSED_PARAM(checkGrammar);
-    UNUSED_PARAM(misspelled);
-    UNUSED_PARAM(ungrammatical);
-    return Vector<String>();
-#endif
-}
-
-
-void TextCheckingHelper::markAllMisspellings(RefPtr<Range>& firstMisspellingRange)
-{
-    // Use the "markAll" feature of findFirstMisspelling. Ignore the return value and the "out parameter";
-    // all we need to do is mark every instance.
-    int ignoredOffset;
-    findFirstMisspelling(ignoredOffset, true, firstMisspellingRange);
-}
-
-void TextCheckingHelper::markAllBadGrammar()
-{
-#ifndef BUILDING_ON_TIGER
-    // Use the "markAll" feature of findFirstBadGrammar. Ignore the return value and "out parameters"; all we need to
-    // do is mark every instance.
-    GrammarDetail ignoredGrammarDetail;
-    int ignoredOffset;
-    findFirstBadGrammar(ignoredGrammarDetail, ignoredOffset, true);
-#else
-    ASSERT_NOT_REACHED();
-#endif
-}
-
-}
diff --git a/WebCore/editing/TextCheckingHelper.h b/WebCore/editing/TextCheckingHelper.h
deleted file mode 100644
index 1dd3b3d..0000000
--- a/WebCore/editing/TextCheckingHelper.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef TextCheckingHelper_h
-#define TextCheckingHelper_h
-
-#include "EditorClient.h"
-
-namespace WebCore {
-
-class Range;
-
-class TextCheckingHelper : public Noncopyable {
-public:
-    TextCheckingHelper(EditorClient*, PassRefPtr<Range>);
-    ~TextCheckingHelper();
-
-    String findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange);
-    String findFirstMisspellingOrBadGrammar(bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail);
-    String findFirstBadGrammar(GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll);
-    int findFirstGrammarDetail(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int badGrammarPhraseLength, int startOffset, int endOffset, bool markAll);
-    void markAllMisspellings(RefPtr<Range>& firstMisspellingRange);
-    void markAllBadGrammar();
-
-    bool isUngrammatical(Vector<String>& guessesVector) const;
-    Vector<String> guessesForMisspelledOrUngrammaticalRange(bool checkGrammar, bool& misspelled, bool& ungrammatical) const;
-    PassRefPtr<Range> paragraphAlignedRange(int& offsetIntoParagraphAlignedRange, String& paragraphString) const;
-private:
-    EditorClient* m_client;
-    RefPtr<Range> m_range;
-};
-
-} // namespace WebCore
-
-#endif // TextCheckingHelper_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list