Changeset 70970 in webkit
- Timestamp:
- Oct 29, 2010 8:42:11 PM (13 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/CMakeLists.txt
r70956 r70970 927 927 editing/SplitTextNodeCommand.cpp 928 928 editing/SplitTextNodeContainingElementCommand.cpp 929 editing/TextCheckingHelper.cpp930 929 editing/TextIterator.cpp 931 930 editing/TypingCommand.cpp -
trunk/WebCore/GNUmakefile.am
r70960 r70970 1356 1356 WebCore/editing/SplitTextNodeContainingElementCommand.h \ 1357 1357 WebCore/editing/TextAffinity.h \ 1358 WebCore/editing/TextCheckingHelper.cpp \1359 WebCore/editing/TextCheckingHelper.h \1360 1358 WebCore/editing/TextGranularity.h \ 1361 1359 WebCore/editing/TextIterator.cpp \ -
trunk/WebCore/WebCore.gypi
r70960 r70970 1438 1438 'editing/SplitTextNodeContainingElementCommand.h', 1439 1439 'editing/TextAffinity.h', 1440 'editing/TextCheckingHelper.cpp',1441 'editing/TextCheckingHelper.h',1442 1440 'editing/TextGranularity.h', 1443 1441 'editing/TextIterator.cpp', -
trunk/WebCore/WebCore.pro
r70960 r70970 818 818 editing/SplitTextNodeCommand.cpp \ 819 819 editing/SplitTextNodeContainingElementCommand.cpp \ 820 editing/TextCheckingHelper.cpp \821 820 editing/TextIterator.cpp \ 822 821 editing/TypingCommand.cpp \ -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r70960 r70970 47941 47941 </File> 47942 47942 <File 47943 RelativePath="..\editing\TextCheckingHelper.cpp"47944 >47945 <FileConfiguration47946 Name="Debug|Win32"47947 ExcludedFromBuild="true"47948 >47949 <Tool47950 Name="VCCLCompilerTool"47951 />47952 </FileConfiguration>47953 <FileConfiguration47954 Name="Release|Win32"47955 ExcludedFromBuild="true"47956 >47957 <Tool47958 Name="VCCLCompilerTool"47959 />47960 </FileConfiguration>47961 <FileConfiguration47962 Name="Debug_Internal|Win32"47963 ExcludedFromBuild="true"47964 >47965 <Tool47966 Name="VCCLCompilerTool"47967 />47968 </FileConfiguration>47969 <FileConfiguration47970 Name="Debug_Cairo|Win32"47971 ExcludedFromBuild="true"47972 >47973 <Tool47974 Name="VCCLCompilerTool"47975 />47976 </FileConfiguration>47977 <FileConfiguration47978 Name="Release_Cairo|Win32"47979 ExcludedFromBuild="true"47980 >47981 <Tool47982 Name="VCCLCompilerTool"47983 />47984 </FileConfiguration>47985 <FileConfiguration47986 Name="Debug_All|Win32"47987 ExcludedFromBuild="true"47988 >47989 <Tool47990 Name="VCCLCompilerTool"47991 />47992 </FileConfiguration>47993 </File>47994 <File47995 RelativePath="..\editing\TextCheckingHelper.h"47996 >47997 </File>47998 <File47999 47943 RelativePath="..\editing\TextGranularity.h" 48000 47944 > -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r70960 r70970 3068 3068 A7D6B3490F61104500B79FD1 /* WorkerScriptLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6B3470F61104500B79FD1 /* WorkerScriptLoader.h */; }; 3069 3069 A7D6B34A0F61104500B79FD1 /* WorkerScriptLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D6B3480F61104500B79FD1 /* WorkerScriptLoader.cpp */; }; 3070 A7DBF8DD1276919C006B6008 /* TextCheckingHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */; };3071 A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */; };3072 3070 A7F338A311C0EFCA00A320A7 /* ShadowElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F338A111C0EFCA00A320A7 /* ShadowElement.cpp */; }; 3073 3071 A7F338A411C0EFCA00A320A7 /* ShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F338A211C0EFCA00A320A7 /* ShadowElement.h */; }; … … 9155 9153 A7D6B3470F61104500B79FD1 /* WorkerScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerScriptLoader.h; path = workers/WorkerScriptLoader.h; sourceTree = "<group>"; }; 9156 9154 A7D6B3480F61104500B79FD1 /* WorkerScriptLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WorkerScriptLoader.cpp; path = workers/WorkerScriptLoader.cpp; sourceTree = "<group>"; }; 9157 A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextCheckingHelper.cpp; sourceTree = "<group>"; };9158 A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCheckingHelper.h; sourceTree = "<group>"; };9159 9155 A7F338A111C0EFCA00A320A7 /* ShadowElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowElement.cpp; sourceTree = "<group>"; }; 9160 9156 A7F338A211C0EFCA00A320A7 /* ShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowElement.h; sourceTree = "<group>"; }; … … 14546 14542 93309DC7099E64910056E581 /* SplitTextNodeContainingElementCommand.h */, 14547 14543 93309DC8099E64910056E581 /* TextAffinity.h */, 14548 A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */,14549 A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */,14550 14544 93309DC9099E64910056E581 /* TextGranularity.h */, 14551 14545 93309DCC099E64910056E581 /* TextIterator.cpp */, … … 21013 21007 B2C3DA360D006C1D00EF6F26 /* TextBreakIterator.h in Headers */, 21014 21008 B2C3DA380D006C1D00EF6F26 /* TextBreakIteratorInternalICU.h in Headers */, 21015 A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */,21016 21009 B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */, 21017 21010 B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */, … … 23614 23607 B2C3DA370D006C1D00EF6F26 /* TextBreakIteratorICU.cpp in Sources */, 23615 23608 B2AFFC980D00A5DF0030074D /* TextBreakIteratorInternalICUMac.mm in Sources */, 23616 A7DBF8DD1276919C006B6008 /* TextCheckingHelper.cpp in Sources */,23617 23609 B2C3DA390D006C1D00EF6F26 /* TextCodec.cpp in Sources */, 23618 23610 B2C3DA3B0D006C1D00EF6F26 /* TextCodecICU.cpp in Sources */, -
trunk/WebCore/editing/EditingAllInOne.cpp
r70852 r70970 66 66 #include <SplitTextNodeCommand.cpp> 67 67 #include <SplitTextNodeContainingElementCommand.cpp> 68 #include <TextCheckingHelper.cpp>69 68 #include <TextIterator.cpp> 70 69 #include <TypingCommand.cpp> -
trunk/WebCore/editing/Editor.cpp
r70847 r70970 63 63 #include "Page.h" 64 64 #include "Pasteboard.h" 65 #include "TextCheckingHelper.h"66 65 #include "RemoveFormatCommand.h" 67 66 #include "RenderBlock.h" … … 1661 1660 } 1662 1661 1662 static String findFirstMisspellingInRange(EditorClient* client, Range* searchRange, int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange) 1663 { 1664 ASSERT_ARG(client, client); 1665 ASSERT_ARG(searchRange, searchRange); 1666 1667 WordAwareIterator it(searchRange); 1668 firstMisspellingOffset = 0; 1669 1670 String firstMisspelling; 1671 int currentChunkOffset = 0; 1672 1673 while (!it.atEnd()) { 1674 const UChar* chars = it.characters(); 1675 int len = it.length(); 1676 1677 // Skip some work for one-space-char hunks 1678 if (!(len == 1 && chars[0] == ' ')) { 1679 1680 int misspellingLocation = -1; 1681 int misspellingLength = 0; 1682 client->checkSpellingOfString(chars, len, &misspellingLocation, &misspellingLength); 1683 1684 // 5490627 shows that there was some code path here where the String constructor below crashes. 1685 // We don't know exactly what combination of bad input caused this, so we're making this much 1686 // more robust against bad input on release builds. 1687 ASSERT(misspellingLength >= 0); 1688 ASSERT(misspellingLocation >= -1); 1689 ASSERT(!misspellingLength || misspellingLocation >= 0); 1690 ASSERT(misspellingLocation < len); 1691 ASSERT(misspellingLength <= len); 1692 ASSERT(misspellingLocation + misspellingLength <= len); 1693 1694 if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < len && misspellingLength <= len && misspellingLocation + misspellingLength <= len) { 1695 1696 // Compute range of misspelled word 1697 RefPtr<Range> misspellingRange = TextIterator::subrange(searchRange, currentChunkOffset + misspellingLocation, misspellingLength); 1698 1699 // Remember first-encountered misspelling and its offset. 1700 if (!firstMisspelling) { 1701 firstMisspellingOffset = currentChunkOffset + misspellingLocation; 1702 firstMisspelling = String(chars + misspellingLocation, misspellingLength); 1703 firstMisspellingRange = misspellingRange; 1704 } 1705 1706 // Store marker for misspelled word. 1707 ExceptionCode ec = 0; 1708 misspellingRange->startContainer(ec)->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling); 1709 ASSERT(!ec); 1710 1711 // Bail out if we're marking only the first misspelling, and not all instances. 1712 if (!markAll) 1713 break; 1714 } 1715 } 1716 1717 currentChunkOffset += len; 1718 it.advance(); 1719 } 1720 1721 return firstMisspelling; 1722 } 1723 1724 #ifndef BUILDING_ON_TIGER 1725 1726 static PassRefPtr<Range> paragraphAlignedRangeForRange(Range* arbitraryRange, int& offsetIntoParagraphAlignedRange, String& paragraphString) 1727 { 1728 ASSERT_ARG(arbitraryRange, arbitraryRange); 1729 1730 ExceptionCode ec = 0; 1731 1732 // Expand range to paragraph boundaries 1733 RefPtr<Range> paragraphRange = arbitraryRange->cloneRange(ec); 1734 setStart(paragraphRange.get(), startOfParagraph(arbitraryRange->startPosition())); 1735 setEnd(paragraphRange.get(), endOfParagraph(arbitraryRange->endPosition())); 1736 1737 // Compute offset from start of expanded range to start of original range 1738 RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), arbitraryRange->startPosition()); 1739 offsetIntoParagraphAlignedRange = TextIterator::rangeLength(offsetAsRange.get()); 1740 1741 // Fill in out parameter with string representing entire paragraph range. 1742 // Someday we might have a caller that doesn't use this, but for now all callers do. 1743 paragraphString = plainText(paragraphRange.get()); 1744 1745 return paragraphRange; 1746 } 1747 1748 static int findFirstGrammarDetailInRange(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int /*badGrammarPhraseLength*/, Range *searchRange, int startOffset, int endOffset, bool markAll) 1749 { 1750 // Found some bad grammar. Find the earliest detail range that starts in our search range (if any). 1751 // Optionally add a DocumentMarker for each detail in the range. 1752 int earliestDetailLocationSoFar = -1; 1753 int earliestDetailIndex = -1; 1754 for (unsigned i = 0; i < grammarDetails.size(); i++) { 1755 const GrammarDetail* detail = &grammarDetails[i]; 1756 ASSERT(detail->length > 0 && detail->location >= 0); 1757 1758 int detailStartOffsetInParagraph = badGrammarPhraseLocation + detail->location; 1759 1760 // Skip this detail if it starts before the original search range 1761 if (detailStartOffsetInParagraph < startOffset) 1762 continue; 1763 1764 // Skip this detail if it starts after the original search range 1765 if (detailStartOffsetInParagraph >= endOffset) 1766 continue; 1767 1768 if (markAll) { 1769 RefPtr<Range> badGrammarRange = TextIterator::subrange(searchRange, badGrammarPhraseLocation - startOffset + detail->location, detail->length); 1770 ExceptionCode ec = 0; 1771 badGrammarRange->startContainer(ec)->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription); 1772 ASSERT(!ec); 1773 } 1774 1775 // Remember this detail only if it's earlier than our current candidate (the details aren't in a guaranteed order) 1776 if (earliestDetailIndex < 0 || earliestDetailLocationSoFar > detail->location) { 1777 earliestDetailIndex = i; 1778 earliestDetailLocationSoFar = detail->location; 1779 } 1780 } 1781 1782 return earliestDetailIndex; 1783 } 1784 1785 static String findFirstBadGrammarInRange(EditorClient* client, Range* searchRange, GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll) 1786 { 1787 ASSERT_ARG(client, client); 1788 ASSERT_ARG(searchRange, searchRange); 1789 1790 // Initialize out parameters; these will be updated if we find something to return. 1791 outGrammarDetail.location = -1; 1792 outGrammarDetail.length = 0; 1793 outGrammarDetail.guesses.clear(); 1794 outGrammarDetail.userDescription = ""; 1795 outGrammarPhraseOffset = 0; 1796 1797 String firstBadGrammarPhrase; 1798 1799 // Expand the search range to encompass entire paragraphs, since grammar checking needs that much context. 1800 // Determine the character offset from the start of the paragraph to the start of the original search range, 1801 // since we will want to ignore results in this area. 1802 int searchRangeStartOffset; 1803 String paragraphString; 1804 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(searchRange, searchRangeStartOffset, paragraphString); 1805 1806 // Determine the character offset from the start of the paragraph to the end of the original search range, 1807 // since we will want to ignore results in this area also. 1808 int searchRangeEndOffset = searchRangeStartOffset + TextIterator::rangeLength(searchRange); 1809 1810 // Start checking from beginning of paragraph, but skip past results that occur before the start of the original search range. 1811 int startOffset = 0; 1812 while (startOffset < searchRangeEndOffset) { 1813 Vector<GrammarDetail> grammarDetails; 1814 int badGrammarPhraseLocation = -1; 1815 int badGrammarPhraseLength = 0; 1816 client->checkGrammarOfString(paragraphString.characters() + startOffset, paragraphString.length() - startOffset, grammarDetails, &badGrammarPhraseLocation, &badGrammarPhraseLength); 1817 1818 if (!badGrammarPhraseLength) { 1819 ASSERT(badGrammarPhraseLocation == -1); 1820 return String(); 1821 } 1822 1823 ASSERT(badGrammarPhraseLocation >= 0); 1824 badGrammarPhraseLocation += startOffset; 1825 1826 1827 // Found some bad grammar. Find the earliest detail range that starts in our search range (if any). 1828 int badGrammarIndex = findFirstGrammarDetailInRange(grammarDetails, badGrammarPhraseLocation, badGrammarPhraseLength, searchRange, searchRangeStartOffset, searchRangeEndOffset, markAll); 1829 if (badGrammarIndex >= 0) { 1830 ASSERT(static_cast<unsigned>(badGrammarIndex) < grammarDetails.size()); 1831 outGrammarDetail = grammarDetails[badGrammarIndex]; 1832 } 1833 1834 // If we found a detail in range, then we have found the first bad phrase (unless we found one earlier but 1835 // kept going so we could mark all instances). 1836 if (badGrammarIndex >= 0 && firstBadGrammarPhrase.isEmpty()) { 1837 outGrammarPhraseOffset = badGrammarPhraseLocation - searchRangeStartOffset; 1838 firstBadGrammarPhrase = paragraphString.substring(badGrammarPhraseLocation, badGrammarPhraseLength); 1839 1840 // Found one. We're done now, unless we're marking each instance. 1841 if (!markAll) 1842 break; 1843 } 1844 1845 // These results were all between the start of the paragraph and the start of the search range; look 1846 // beyond this phrase. 1847 startOffset = badGrammarPhraseLocation + badGrammarPhraseLength; 1848 } 1849 1850 return firstBadGrammarPhrase; 1851 } 1852 1853 #endif /* not BUILDING_ON_TIGER */ 1854 1855 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1856 1857 static String findFirstMisspellingOrBadGrammarInRange(EditorClient* client, Range* searchRange, bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail) 1858 { 1859 ASSERT_ARG(client, client); 1860 ASSERT_ARG(searchRange, searchRange); 1861 1862 String firstFoundItem; 1863 String misspelledWord; 1864 String badGrammarPhrase; 1865 ExceptionCode ec = 0; 1866 1867 // Initialize out parameters; these will be updated if we find something to return. 1868 outIsSpelling = true; 1869 outFirstFoundOffset = 0; 1870 outGrammarDetail.location = -1; 1871 outGrammarDetail.length = 0; 1872 outGrammarDetail.guesses.clear(); 1873 outGrammarDetail.userDescription = ""; 1874 1875 // Expand the search range to encompass entire paragraphs, since text checking needs that much context. 1876 // Determine the character offset from the start of the paragraph to the start of the original search range, 1877 // since we will want to ignore results in this area. 1878 RefPtr<Range> paragraphRange = searchRange->cloneRange(ec); 1879 setStart(paragraphRange.get(), startOfParagraph(searchRange->startPosition())); 1880 int totalRangeLength = TextIterator::rangeLength(paragraphRange.get()); 1881 setEnd(paragraphRange.get(), endOfParagraph(searchRange->startPosition())); 1882 1883 RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->startPosition()); 1884 int searchRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get()); 1885 int totalLengthProcessed = 0; 1886 1887 bool firstIteration = true; 1888 bool lastIteration = false; 1889 while (totalLengthProcessed < totalRangeLength) { 1890 // Iterate through the search range by paragraphs, checking each one for spelling and grammar. 1891 int currentLength = TextIterator::rangeLength(paragraphRange.get()); 1892 int currentStartOffset = firstIteration ? searchRangeStartOffset : 0; 1893 int currentEndOffset = currentLength; 1894 if (inSameParagraph(paragraphRange->startPosition(), searchRange->endPosition())) { 1895 // Determine the character offset from the end of the original search range to the end of the paragraph, 1896 // since we will want to ignore results in this area. 1897 RefPtr<Range> endOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->endPosition()); 1898 currentEndOffset = TextIterator::rangeLength(endOffsetAsRange.get()); 1899 lastIteration = true; 1900 } 1901 if (currentStartOffset < currentEndOffset) { 1902 String paragraphString = plainText(paragraphRange.get()); 1903 if (paragraphString.length() > 0) { 1904 bool foundGrammar = false; 1905 int spellingLocation = 0; 1906 int grammarPhraseLocation = 0; 1907 int grammarDetailLocation = 0; 1908 unsigned grammarDetailIndex = 0; 1909 1910 Vector<TextCheckingResult> results; 1911 uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling; 1912 client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results); 1913 1914 for (unsigned i = 0; i < results.size(); i++) { 1915 const TextCheckingResult* result = &results[i]; 1916 if (result->type == TextCheckingTypeSpelling && result->location >= currentStartOffset && result->location + result->length <= currentEndOffset) { 1917 ASSERT(result->length > 0 && result->location >= 0); 1918 spellingLocation = result->location; 1919 misspelledWord = paragraphString.substring(result->location, result->length); 1920 ASSERT(misspelledWord.length()); 1921 break; 1922 } 1923 if (checkGrammar && result->type == TextCheckingTypeGrammar && result->location < currentEndOffset && result->location + result->length > currentStartOffset) { 1924 ASSERT(result->length > 0 && result->location >= 0); 1925 // We can't stop after the first grammar result, since there might still be a spelling result after 1926 // it begins but before the first detail in it, but we can stop if we find a second grammar result. 1927 if (foundGrammar) 1928 break; 1929 for (unsigned j = 0; j < result->details.size(); j++) { 1930 const GrammarDetail* detail = &result->details[j]; 1931 ASSERT(detail->length > 0 && detail->location >= 0); 1932 if (result->location + detail->location >= currentStartOffset && result->location + detail->location + detail->length <= currentEndOffset && (!foundGrammar || result->location + detail->location < grammarDetailLocation)) { 1933 grammarDetailIndex = j; 1934 grammarDetailLocation = result->location + detail->location; 1935 foundGrammar = true; 1936 } 1937 } 1938 if (foundGrammar) { 1939 grammarPhraseLocation = result->location; 1940 outGrammarDetail = result->details[grammarDetailIndex]; 1941 badGrammarPhrase = paragraphString.substring(result->location, result->length); 1942 ASSERT(badGrammarPhrase.length()); 1943 } 1944 } 1945 } 1946 1947 if (!misspelledWord.isEmpty() && (!checkGrammar || badGrammarPhrase.isEmpty() || spellingLocation <= grammarDetailLocation)) { 1948 int spellingOffset = spellingLocation - currentStartOffset; 1949 if (!firstIteration) { 1950 RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition()); 1951 spellingOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get()); 1952 } 1953 outIsSpelling = true; 1954 outFirstFoundOffset = spellingOffset; 1955 firstFoundItem = misspelledWord; 1956 break; 1957 } 1958 if (checkGrammar && !badGrammarPhrase.isEmpty()) { 1959 int grammarPhraseOffset = grammarPhraseLocation - currentStartOffset; 1960 if (!firstIteration) { 1961 RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition()); 1962 grammarPhraseOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get()); 1963 } 1964 outIsSpelling = false; 1965 outFirstFoundOffset = grammarPhraseOffset; 1966 firstFoundItem = badGrammarPhrase; 1967 break; 1968 } 1969 } 1970 } 1971 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeLength) 1972 break; 1973 VisiblePosition newParagraphStart = startOfNextParagraph(paragraphRange->endPosition()); 1974 setStart(paragraphRange.get(), newParagraphStart); 1975 setEnd(paragraphRange.get(), endOfParagraph(newParagraphStart)); 1976 firstIteration = false; 1977 totalLengthProcessed += currentLength; 1978 } 1979 return firstFoundItem; 1980 } 1981 1982 #endif 1983 1663 1984 void Editor::advanceToNextMisspelling(bool startBeforeSelection) 1664 1985 { … … 1672 1993 VisibleSelection selection(frame()->selection()->selection()); 1673 1994 RefPtr<Range> spellingSearchRange(rangeOfContents(frame()->document())); 1674 TextCheckingHelper checker(client(), spellingSearchRange);1675 1676 1995 bool startedWithSelection = false; 1677 1996 if (selection.start().node()) { … … 1739 2058 int foundOffset = 0; 1740 2059 GrammarDetail grammarDetail; 1741 String foundItem = checker.findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);2060 String foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail); 1742 2061 if (isSpelling) { 1743 2062 misspelledWord = foundItem; … … 1749 2068 #else 1750 2069 RefPtr<Range> firstMisspellingRange; 1751 String misspelledWord = checker.findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);2070 String misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRange.get(), misspellingOffset, false, firstMisspellingRange); 1752 2071 String badGrammarPhrase; 1753 2072 … … 1766 2085 1767 2086 if (isGrammarCheckingEnabled()) 1768 badGrammarPhrase = checker.findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);2087 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRange.get(), grammarDetail, grammarPhraseOffset, false); 1769 2088 #endif 1770 2089 #endif … … 1779 2098 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1780 2099 grammarSearchRange = spellingSearchRange->cloneRange(ec); 1781 foundItem = checker.findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);2100 foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail); 1782 2101 if (isSpelling) { 1783 2102 misspelledWord = foundItem; … … 1788 2107 } 1789 2108 #else 1790 misspelledWord = checker.findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);2109 misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRange.get(), misspellingOffset, false, firstMisspellingRange); 1791 2110 1792 2111 #ifndef BUILDING_ON_TIGER … … 1799 2118 } 1800 2119 if (isGrammarCheckingEnabled()) 1801 badGrammarPhrase = checker.findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);2120 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRange.get(), grammarDetail, grammarPhraseOffset, false); 1802 2121 #endif 1803 2122 #endif … … 1863 2182 } 1864 2183 2184 #ifndef BUILDING_ON_TIGER 2185 static bool isRangeUngrammatical(EditorClient* client, Range *range, Vector<String>& guessesVector) 2186 { 2187 if (!client) 2188 return false; 2189 2190 ExceptionCode ec; 2191 if (!range || range->collapsed(ec)) 2192 return false; 2193 2194 // Returns true only if the passed range exactly corresponds to a bad grammar detail range. This is analogous 2195 // to isSelectionMisspelled. It's not good enough for there to be some bad grammar somewhere in the range, 2196 // or overlapping the range; the ranges must exactly match. 2197 guessesVector.clear(); 2198 int grammarPhraseOffset; 2199 2200 GrammarDetail grammarDetail; 2201 String badGrammarPhrase = findFirstBadGrammarInRange(client, range, grammarDetail, grammarPhraseOffset, false); 2202 2203 // No bad grammar in these parts at all. 2204 if (badGrammarPhrase.isEmpty()) 2205 return false; 2206 2207 // Bad grammar, but phrase (e.g. sentence) starts beyond start of range. 2208 if (grammarPhraseOffset > 0) 2209 return false; 2210 2211 ASSERT(grammarDetail.location >= 0 && grammarDetail.length > 0); 2212 2213 // Bad grammar, but start of detail (e.g. ungrammatical word) doesn't match start of range 2214 if (grammarDetail.location + grammarPhraseOffset) 2215 return false; 2216 2217 // Bad grammar at start of range, but end of bad grammar is before or after end of range 2218 if (grammarDetail.length != TextIterator::rangeLength(range)) 2219 return false; 2220 2221 // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen). 2222 // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work 2223 // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling 2224 // or a grammar error. 2225 client->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail); 2226 2227 return true; 2228 } 2229 #endif 2230 1865 2231 bool Editor::isSelectionUngrammatical() 1866 2232 { … … 1869 2235 #else 1870 2236 Vector<String> ignoredGuesses; 1871 return TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).isUngrammatical(ignoredGuesses);2237 return isRangeUngrammatical(client(), frame()->selection()->toNormalizedRange().get(), ignoredGuesses); 1872 2238 #endif 1873 2239 } … … 1879 2245 #else 1880 2246 Vector<String> guesses; 1881 // Ignore the result of is Ungrammatical; we just want the guesses, whether or not there are any1882 TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).isUngrammatical(guesses);2247 // Ignore the result of isRangeUngrammatical; we just want the guesses, whether or not there are any 2248 isRangeUngrammatical(client(), frame()->selection()->toNormalizedRange().get(), guesses); 1883 2249 return guesses; 1884 2250 #endif … … 1896 2262 } 1897 2263 2264 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 2265 2266 static Vector<String> guessesForMisspelledOrUngrammaticalRange(EditorClient* client, Range *range, bool checkGrammar, bool& misspelled, bool& ungrammatical) 2267 { 2268 Vector<String> guesses; 2269 ExceptionCode ec; 2270 misspelled = false; 2271 ungrammatical = false; 2272 2273 if (!client || !range || range->collapsed(ec)) 2274 return guesses; 2275 2276 // Expand the range to encompass entire paragraphs, since text checking needs that much context. 2277 int rangeStartOffset; 2278 String paragraphString; 2279 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(range, rangeStartOffset, paragraphString); 2280 int rangeLength = TextIterator::rangeLength(range); 2281 if (!rangeLength || !paragraphString.length()) 2282 return guesses; 2283 2284 Vector<TextCheckingResult> results; 2285 uint64_t checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling; 2286 client->checkTextOfParagraph(paragraphString.characters(), paragraphString.length(), checkingTypes, results); 2287 2288 for (unsigned i = 0; i < results.size(); i++) { 2289 const TextCheckingResult* result = &results[i]; 2290 if (result->type == TextCheckingTypeSpelling && result->location == rangeStartOffset && result->length == rangeLength) { 2291 String misspelledWord = paragraphString.substring(rangeStartOffset, rangeLength); 2292 ASSERT(misspelledWord.length()); 2293 client->getGuessesForWord(misspelledWord, guesses); 2294 client->updateSpellingUIWithMisspelledWord(misspelledWord); 2295 misspelled = true; 2296 return guesses; 2297 } 2298 } 2299 2300 if (!checkGrammar) 2301 return guesses; 2302 2303 for (unsigned i = 0; i < results.size(); i++) { 2304 const TextCheckingResult* result = &results[i]; 2305 if (result->type == TextCheckingTypeGrammar && result->location <= rangeStartOffset && result->location + result->length >= rangeStartOffset + rangeLength) { 2306 for (unsigned j = 0; j < result->details.size(); j++) { 2307 const GrammarDetail* detail = &result->details[j]; 2308 ASSERT(detail->length > 0 && detail->location >= 0); 2309 if (result->location + detail->location == rangeStartOffset && detail->length == rangeLength) { 2310 String badGrammarPhrase = paragraphString.substring(result->location, result->length); 2311 ASSERT(badGrammarPhrase.length()); 2312 for (unsigned k = 0; k < detail->guesses.size(); k++) 2313 guesses.append(detail->guesses[k]); 2314 client->updateSpellingUIWithGrammarString(badGrammarPhrase, *detail); 2315 ungrammatical = true; 2316 return guesses; 2317 } 2318 } 2319 } 2320 } 2321 return guesses; 2322 } 2323 2324 #endif 2325 1898 2326 Vector<String> Editor::guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical) 1899 2327 { 1900 2328 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 1901 return TextCheckingHelper(client(), frame()->selection()->toNormalizedRange()).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);2329 return guessesForMisspelledOrUngrammaticalRange(client(), frame()->selection()->toNormalizedRange().get(), isGrammarCheckingEnabled(), misspelled, ungrammatical); 1902 2330 #else 1903 2331 misspelled = isSelectionMisspelled(); … … 2076 2504 #endif 2077 2505 } 2078 2079 void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange) 2506 2507 static void markAllMisspellingsInRange(EditorClient* client, Range* searchRange, RefPtr<Range>& firstMisspellingRange) 2508 { 2509 // Use the "markAll" feature of findFirstMisspellingInRange. Ignore the return value and the "out parameter"; 2510 // all we need to do is mark every instance. 2511 int ignoredOffset; 2512 findFirstMisspellingInRange(client, searchRange, ignoredOffset, true, firstMisspellingRange); 2513 } 2514 2515 #ifndef BUILDING_ON_TIGER 2516 static void markAllBadGrammarInRange(EditorClient* client, Range* searchRange) 2517 { 2518 // Use the "markAll" feature of findFirstBadGrammarInRange. Ignore the return value and "out parameters"; all we need to 2519 // do is mark every instance. 2520 GrammarDetail ignoredGrammarDetail; 2521 int ignoredOffset; 2522 findFirstBadGrammarInRange(client, searchRange, ignoredGrammarDetail, ignoredOffset, true); 2523 } 2524 #endif 2525 2526 static void markMisspellingsOrBadGrammar(Editor* editor, const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange) 2080 2527 { 2081 2528 // This function is called with a selection already expanded to word boundaries. … … 2084 2531 // This function is used only for as-you-type checking, so if that's off we do nothing. Note that 2085 2532 // grammar checking can only be on if spell checking is also on. 2086 if (! isContinuousSpellCheckingEnabled())2533 if (!editor->isContinuousSpellCheckingEnabled()) 2087 2534 return; 2088 2535 … … 2096 2543 return; 2097 2544 2098 if (! isSpellCheckingEnabledInFocusedNode())2545 if (!editor->isSpellCheckingEnabledInFocusedNode()) 2099 2546 return; 2100 2547 2101 2548 // Get the spell checker if it is available 2102 if (!client()) 2103 return; 2104 2105 TextCheckingHelper checker(client(), searchRange); 2549 if (!editor->client()) 2550 return; 2551 2106 2552 if (checkSpelling) 2107 checker.markAllMisspellings(firstMisspellingRange);2553 markAllMisspellingsInRange(editor->client(), searchRange.get(), firstMisspellingRange); 2108 2554 else { 2109 2555 #ifdef BUILDING_ON_TIGER 2110 2556 ASSERT_NOT_REACHED(); 2111 2557 #else 2112 if ( isGrammarCheckingEnabled())2113 checker.markAllBadGrammar();2558 if (editor->isGrammarCheckingEnabled()) 2559 markAllBadGrammarInRange(editor->client(), searchRange.get()); 2114 2560 #endif 2115 2561 } … … 2131 2577 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange) 2132 2578 { 2133 markMisspellingsOrBadGrammar( selection, true, firstMisspellingRange);2579 markMisspellingsOrBadGrammar(this, selection, true, firstMisspellingRange); 2134 2580 } 2135 2581 … … 2138 2584 #ifndef BUILDING_ON_TIGER 2139 2585 RefPtr<Range> firstMisspellingRange; 2140 markMisspellingsOrBadGrammar( selection, false, firstMisspellingRange);2586 markMisspellingsOrBadGrammar(this, selection, false, firstMisspellingRange); 2141 2587 #else 2142 2588 UNUSED_PARAM(selection); … … 2188 2634 String paragraphString; 2189 2635 RefPtr<Range> paragraphRange; 2190 TextCheckingHelper checker(client(), grammarRange);2191 2636 2192 2637 if (shouldMarkGrammar) { 2193 2638 // The spelling range should be contained in the paragraph-aligned extension of the grammar range. 2194 paragraphRange = checker.paragraphAlignedRange(grammarRangeStartOffset, paragraphString);2639 paragraphRange = paragraphAlignedRangeForRange(grammarRange, grammarRangeStartOffset, paragraphString); 2195 2640 RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), spellingRange->startPosition()); 2196 2641 spellingRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get()); 2197 2642 grammarRangeEndOffset = grammarRangeStartOffset + TextIterator::rangeLength(grammarRange); 2198 2643 } else { 2199 paragraphRange = checker.paragraphAlignedRange(spellingRangeStartOffset, paragraphString);2644 paragraphRange = paragraphAlignedRangeForRange(spellingRange, spellingRangeStartOffset, paragraphString); 2200 2645 } 2201 2646 spellingRangeEndOffset = spellingRangeStartOffset + TextIterator::rangeLength(spellingRange); … … 2387 2832 if (!shouldInsertText(replacedString, selection.get(), EditorInsertActionPasted)) 2388 2833 return; 2389 2834 2390 2835 String paragraphString; 2391 2836 int selectionOffset; 2392 RefPtr<Range> paragraphRange = TextCheckingHelper(client(), selection).paragraphAlignedRange(selectionOffset, paragraphString);2837 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(selection.get(), selectionOffset, paragraphString); 2393 2838 replaceSelectionWithText(replacedString, false, false); 2394 2839 RefPtr<Range> changedRange = TextIterator::subrange(paragraphRange.get(), selectionOffset, replacedString.length()); -
trunk/WebCore/editing/Editor.h
r70847 r70970 405 405 void writeSelectionToPasteboard(Pasteboard*); 406 406 void revealSelectionAfterEditingOperation(); 407 void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);408 407 409 408 void selectComposition();
Note: See TracChangeset
for help on using the changeset viewer.