| Index: third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp b/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp
|
| index 975ef0a42c2d0f941cf90431ae893d3d53da2760..407cea58e7966b20e26a59fc7f5d5cb9d6c3fd73 100644
|
| --- a/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp
|
| @@ -41,39 +41,16 @@
|
|
|
| namespace blink {
|
|
|
| -static void findBadGrammars(TextCheckerClient& client, const UChar* text, int start, int length, Vector<TextCheckingResult>& results)
|
| +static void findMisspellings(TextCheckerClient& client, const String& text, Vector<TextCheckingResult>& results)
|
| {
|
| - int checkLocation = start;
|
| - int checkLength = length;
|
| -
|
| - while (0 < checkLength) {
|
| - int badGrammarLocation = -1;
|
| - int badGrammarLength = 0;
|
| - Vector<GrammarDetail> badGrammarDetails;
|
| - client.checkGrammarOfString(String(text + checkLocation, checkLength), badGrammarDetails, &badGrammarLocation, &badGrammarLength);
|
| - if (!badGrammarLength)
|
| - break;
|
| - DCHECK_LE(0, badGrammarLocation);
|
| - DCHECK_LE(badGrammarLocation, checkLength);
|
| - DCHECK_LT(0, badGrammarLength);
|
| - DCHECK_LE(badGrammarLocation + badGrammarLength, checkLength);
|
| - TextCheckingResult badGrammar;
|
| - badGrammar.decoration = TextDecorationTypeGrammar;
|
| - badGrammar.location = checkLocation + badGrammarLocation;
|
| - badGrammar.length = badGrammarLength;
|
| - badGrammar.details.swap(badGrammarDetails);
|
| - results.append(badGrammar);
|
| -
|
| - checkLocation += (badGrammarLocation + badGrammarLength);
|
| - checkLength -= (badGrammarLocation + badGrammarLength);
|
| - }
|
| -}
|
| + Vector<UChar> characters;
|
| + text.appendTo(characters);
|
| + unsigned length = text.length();
|
|
|
| -static void findMisspellings(TextCheckerClient& client, const UChar* text, int start, int length, Vector<TextCheckingResult>& results)
|
| -{
|
| - TextBreakIterator* iterator = wordBreakIterator(text + start, length);
|
| + TextBreakIterator* iterator = wordBreakIterator(characters.data(), length);
|
| if (!iterator)
|
| return;
|
| +
|
| int wordStart = iterator->current();
|
| while (0 <= wordStart) {
|
| int wordEnd = iterator->next();
|
| @@ -82,7 +59,7 @@ static void findMisspellings(TextCheckerClient& client, const UChar* text, int s
|
| int wordLength = wordEnd - wordStart;
|
| int misspellingLocation = -1;
|
| int misspellingLength = 0;
|
| - client.checkSpellingOfString(String(text + start + wordStart, wordLength), &misspellingLocation, &misspellingLength);
|
| + client.checkSpellingOfString(String(characters.data() + wordStart, wordLength), &misspellingLocation, &misspellingLength);
|
| if (0 < misspellingLength) {
|
| DCHECK_LE(0, misspellingLocation);
|
| DCHECK_LE(misspellingLocation, wordLength);
|
| @@ -90,7 +67,7 @@ static void findMisspellings(TextCheckerClient& client, const UChar* text, int s
|
| DCHECK_LE(misspellingLocation + misspellingLength, wordLength);
|
| TextCheckingResult misspelling;
|
| misspelling.decoration = TextDecorationTypeSpelling;
|
| - misspelling.location = start + wordStart + misspellingLocation;
|
| + misspelling.location = wordStart + misspellingLocation;
|
| misspelling.length = misspellingLength;
|
| results.append(misspelling);
|
| }
|
| @@ -314,22 +291,16 @@ String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, boo
|
| return firstMisspelling;
|
| }
|
|
|
| -String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail)
|
| +String TextCheckingHelper::findFirstMisspellingOrBadGrammar(int& outFirstFoundOffset)
|
| {
|
| if (!unifiedTextCheckerEnabled())
|
| return "";
|
|
|
| String firstFoundItem;
|
| String misspelledWord;
|
| - String badGrammarPhrase;
|
|
|
| - // Initialize out parameters; these will be updated if we find something to return.
|
| - outIsSpelling = true;
|
| + // Initialize out parameter; it will be updated if we find something to return.
|
| 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,
|
| @@ -345,7 +316,7 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool& outIsSpelling,
|
| bool firstIteration = true;
|
| bool lastIteration = false;
|
| while (totalLengthProcessed < totalRangeLength) {
|
| - // Iterate through the search range by paragraphs, checking each one for spelling and grammar.
|
| + // Iterate through the search range by paragraphs, checking each one for spelling.
|
| int currentLength = TextIterator::rangeLength(paragraphStart, paragraphEnd);
|
| int currentStartOffset = firstIteration ? rangeStartOffset : 0;
|
| int currentEndOffset = currentLength;
|
| @@ -358,14 +329,10 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool& outIsSpelling,
|
| if (currentStartOffset < currentEndOffset) {
|
| String paragraphString = plainText(EphemeralRange(paragraphStart, paragraphEnd));
|
| if (paragraphString.length() > 0) {
|
| - bool foundGrammar = false;
|
| int spellingLocation = 0;
|
| - int grammarPhraseLocation = 0;
|
| - int grammarDetailLocation = 0;
|
| - unsigned grammarDetailIndex = 0;
|
|
|
| Vector<TextCheckingResult> results;
|
| - checkTextOfParagraph(m_client->textChecker(), paragraphString, results);
|
| + findMisspellings(m_client->textChecker(), paragraphString, results);
|
|
|
| for (unsigned i = 0; i < results.size(); i++) {
|
| const TextCheckingResult* result = &results[i];
|
| @@ -377,50 +344,16 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool& outIsSpelling,
|
| DCHECK(misspelledWord.length());
|
| break;
|
| }
|
| - if (result->decoration == TextDecorationTypeGrammar && result->location < currentEndOffset && result->location + result->length > currentStartOffset) {
|
| - DCHECK_GT(result->length, 0);
|
| - DCHECK_GE(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];
|
| - DCHECK_GT(detail->length, 0);
|
| - DCHECK_GE(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);
|
| - DCHECK(badGrammarPhrase.length());
|
| - }
|
| - }
|
| }
|
|
|
| - if (!misspelledWord.isEmpty() && (badGrammarPhrase.isEmpty() || spellingLocation <= grammarDetailLocation)) {
|
| + if (!misspelledWord.isEmpty()) {
|
| int spellingOffset = spellingLocation - currentStartOffset;
|
| if (!firstIteration)
|
| spellingOffset += TextIterator::rangeLength(m_start, paragraphStart);
|
| - outIsSpelling = true;
|
| outFirstFoundOffset = spellingOffset;
|
| firstFoundItem = misspelledWord;
|
| break;
|
| }
|
| - if (!badGrammarPhrase.isEmpty()) {
|
| - int grammarPhraseOffset = grammarPhraseLocation - currentStartOffset;
|
| - if (!firstIteration)
|
| - grammarPhraseOffset += TextIterator::rangeLength(m_start, paragraphStart);
|
| - outIsSpelling = false;
|
| - outFirstFoundOffset = grammarPhraseOffset;
|
| - firstFoundItem = badGrammarPhrase;
|
| - break;
|
| - }
|
| }
|
| }
|
| if (lastIteration || totalLengthProcessed + currentLength >= totalRangeLength)
|
| @@ -434,101 +367,6 @@ String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool& outIsSpelling,
|
| return firstFoundItem;
|
| }
|
|
|
| -int TextCheckingHelper::findFirstGrammarDetail(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int startOffset, int endOffset, bool markAll) const
|
| -{
|
| - // 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];
|
| - DCHECK_GT(detail->length, 0);
|
| - DCHECK_GE(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) {
|
| - const EphemeralRange badGrammarRange = calculateCharacterSubrange(EphemeralRange(m_start, m_end), badGrammarPhraseLocation - startOffset + detail->location, detail->length);
|
| - badGrammarRange.document().markers().addMarker(badGrammarRange.startPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->userDescription);
|
| - }
|
| -
|
| - // 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;
|
| -}
|
| -
|
| -String TextCheckingHelper::findFirstBadGrammar(GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll)
|
| -{
|
| - // 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.
|
| - TextCheckingParagraph paragraph(EphemeralRange(m_start, m_end));
|
| -
|
| - // 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 < paragraph.checkingEnd()) {
|
| - Vector<GrammarDetail> grammarDetails;
|
| - int badGrammarPhraseLocation = -1;
|
| - int badGrammarPhraseLength = 0;
|
| - m_client->textChecker().checkGrammarOfString(paragraph.textSubstring(startOffset), grammarDetails, &badGrammarPhraseLocation, &badGrammarPhraseLength);
|
| -
|
| - if (!badGrammarPhraseLength) {
|
| - DCHECK_EQ(badGrammarPhraseLocation, -1);
|
| - return String();
|
| - }
|
| -
|
| - DCHECK_GE(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, paragraph.checkingStart(), paragraph.checkingEnd(), markAll);
|
| - if (badGrammarIndex >= 0) {
|
| - DCHECK_LT(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 - paragraph.checkingStart();
|
| - firstBadGrammarPhrase = paragraph.textSubstring(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;
|
| -}
|
| -
|
| bool TextCheckingHelper::markAllMisspellings()
|
| {
|
| // Use the "markAll" feature of findFirstMisspelling. Ignore the return value and the "out parameter";
|
| @@ -537,15 +375,6 @@ bool TextCheckingHelper::markAllMisspellings()
|
| return findFirstMisspelling(ignoredOffset, true).isEmpty();
|
| }
|
|
|
| -void TextCheckingHelper::markAllBadGrammar()
|
| -{
|
| - // 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);
|
| -}
|
| -
|
| bool TextCheckingHelper::unifiedTextCheckerEnabled() const
|
| {
|
| DCHECK(m_start.isNotNull());
|
| @@ -553,36 +382,6 @@ bool TextCheckingHelper::unifiedTextCheckerEnabled() const
|
| return blink::unifiedTextCheckerEnabled(doc.frame());
|
| }
|
|
|
| -void checkTextOfParagraph(TextCheckerClient& client, const String& text, Vector<TextCheckingResult>& results)
|
| -{
|
| - Vector<UChar> characters;
|
| - text.appendTo(characters);
|
| - unsigned length = text.length();
|
| -
|
| - Vector<TextCheckingResult> spellingResult;
|
| - findMisspellings(client, characters.data(), 0, length, spellingResult);
|
| -
|
| - // Only checks grammartical error before the first misspellings
|
| - int grammarCheckLength = length;
|
| - for (const auto& spelling : spellingResult) {
|
| - if (spelling.location < grammarCheckLength)
|
| - grammarCheckLength = spelling.location;
|
| - }
|
| -
|
| - Vector<TextCheckingResult> grammarResult;
|
| - findBadGrammars(client, characters.data(), 0, grammarCheckLength, grammarResult);
|
| -
|
| - if (grammarResult.size())
|
| - results.swap(grammarResult);
|
| -
|
| - if (spellingResult.size()) {
|
| - if (results.isEmpty())
|
| - results.swap(spellingResult);
|
| - else
|
| - results.appendVector(spellingResult);
|
| - }
|
| -}
|
| -
|
| bool unifiedTextCheckerEnabled(const LocalFrame* frame)
|
| {
|
| if (!frame)
|
|
|