| Index: Source/core/editing/TextCheckingHelper.cpp
|
| diff --git a/Source/core/editing/TextCheckingHelper.cpp b/Source/core/editing/TextCheckingHelper.cpp
|
| deleted file mode 100644
|
| index 76e72729b2907eccc99046eaeec2208d64227cf7..0000000000000000000000000000000000000000
|
| --- a/Source/core/editing/TextCheckingHelper.cpp
|
| +++ /dev/null
|
| @@ -1,580 +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 "core/editing/TextCheckingHelper.h"
|
| -
|
| -#include "bindings/core/v8/ExceptionState.h"
|
| -#include "bindings/core/v8/ExceptionStatePlaceholder.h"
|
| -#include "core/dom/Document.h"
|
| -#include "core/dom/Range.h"
|
| -#include "core/editing/VisiblePosition.h"
|
| -#include "core/editing/VisibleUnits.h"
|
| -#include "core/editing/iterators/CharacterIterator.h"
|
| -#include "core/editing/iterators/WordAwareIterator.h"
|
| -#include "core/editing/markers/DocumentMarkerController.h"
|
| -#include "core/frame/LocalFrame.h"
|
| -#include "core/frame/Settings.h"
|
| -#include "core/page/SpellCheckerClient.h"
|
| -#include "platform/text/TextBreakIterator.h"
|
| -#include "platform/text/TextCheckerClient.h"
|
| -
|
| -namespace blink {
|
| -
|
| -static void findBadGrammars(TextCheckerClient& client, const UChar* text, int start, int length, 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;
|
| - ASSERT(0 <= badGrammarLocation && badGrammarLocation <= checkLength);
|
| - ASSERT(0 < badGrammarLength && 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);
|
| - }
|
| -}
|
| -
|
| -static void findMisspellings(TextCheckerClient& client, const UChar* text, int start, int length, Vector<TextCheckingResult>& results)
|
| -{
|
| - TextBreakIterator* iterator = wordBreakIterator(text + start, length);
|
| - if (!iterator)
|
| - return;
|
| - int wordStart = iterator->current();
|
| - while (0 <= wordStart) {
|
| - int wordEnd = iterator->next();
|
| - if (wordEnd < 0)
|
| - break;
|
| - int wordLength = wordEnd - wordStart;
|
| - int misspellingLocation = -1;
|
| - int misspellingLength = 0;
|
| - client.checkSpellingOfString(String(text + start + wordStart, wordLength), &misspellingLocation, &misspellingLength);
|
| - if (0 < misspellingLength) {
|
| - ASSERT(0 <= misspellingLocation && misspellingLocation <= wordLength);
|
| - ASSERT(0 < misspellingLength && misspellingLocation + misspellingLength <= wordLength);
|
| - TextCheckingResult misspelling;
|
| - misspelling.decoration = TextDecorationTypeSpelling;
|
| - misspelling.location = start + wordStart + misspellingLocation;
|
| - misspelling.length = misspellingLength;
|
| - misspelling.replacement = client.getAutoCorrectSuggestionForMisspelledWord(String(text + misspelling.location, misspelling.length));
|
| - results.append(misspelling);
|
| - }
|
| -
|
| - wordStart = wordEnd;
|
| - }
|
| -}
|
| -
|
| -void expandRangeToSentenceBoundary(Range& range)
|
| -{
|
| - range.setStart(startOfSentence(VisiblePosition(range.startPosition())).deepEquivalent());
|
| - range.setEnd(endOfSentence(VisiblePosition(range.endPosition())).deepEquivalent());
|
| -}
|
| -
|
| -static PassRefPtrWillBeRawPtr<Range> expandToParagraphBoundary(PassRefPtrWillBeRawPtr<Range> range)
|
| -{
|
| - RefPtrWillBeRawPtr<Range> paragraphRange = range->cloneRange();
|
| - paragraphRange->setStart(startOfParagraph(VisiblePosition(range->startPosition())).deepEquivalent());
|
| - paragraphRange->setEnd(endOfParagraph(VisiblePosition(range->endPosition())).deepEquivalent());
|
| - return paragraphRange;
|
| -}
|
| -
|
| -TextCheckingParagraph::TextCheckingParagraph(PassRefPtrWillBeRawPtr<Range> checkingRange)
|
| - : m_checkingRange(checkingRange)
|
| - , m_checkingStart(-1)
|
| - , m_checkingEnd(-1)
|
| - , m_checkingLength(-1)
|
| -{
|
| -}
|
| -
|
| -TextCheckingParagraph::TextCheckingParagraph(PassRefPtrWillBeRawPtr<Range> checkingRange, PassRefPtrWillBeRawPtr<Range> paragraphRange)
|
| - : m_checkingRange(checkingRange)
|
| - , m_paragraphRange(paragraphRange)
|
| - , m_checkingStart(-1)
|
| - , m_checkingEnd(-1)
|
| - , m_checkingLength(-1)
|
| -{
|
| -}
|
| -
|
| -TextCheckingParagraph::~TextCheckingParagraph()
|
| -{
|
| -}
|
| -
|
| -void TextCheckingParagraph::expandRangeToNextEnd()
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - paragraphRange()->setEnd(endOfParagraph(startOfNextParagraph(VisiblePosition(paragraphRange()->startPosition()))).deepEquivalent());
|
| - invalidateParagraphRangeValues();
|
| -}
|
| -
|
| -void TextCheckingParagraph::invalidateParagraphRangeValues()
|
| -{
|
| - m_checkingStart = m_checkingEnd = -1;
|
| - m_offsetAsRange = nullptr;
|
| - m_text = String();
|
| -}
|
| -
|
| -int TextCheckingParagraph::rangeLength() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - return TextIterator::rangeLength(paragraphRange()->startPosition(), paragraphRange()->endPosition());
|
| -}
|
| -
|
| -PassRefPtrWillBeRawPtr<Range> TextCheckingParagraph::paragraphRange() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (!m_paragraphRange)
|
| - m_paragraphRange = expandToParagraphBoundary(checkingRange());
|
| - return m_paragraphRange;
|
| -}
|
| -
|
| -PassRefPtrWillBeRawPtr<Range> TextCheckingParagraph::subrange(int characterOffset, int characterCount) const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - EphemeralRange range = calculateCharacterSubrange(EphemeralRange(paragraphRange().get()), characterOffset, characterCount);
|
| - if (range.isNull())
|
| - return nullptr;
|
| - return Range::create(range.document(), range.startPosition(), range.endPosition());
|
| -}
|
| -
|
| -int TextCheckingParagraph::offsetTo(const Position& position, ExceptionState& exceptionState) const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - RefPtrWillBeRawPtr<Range> range = offsetAsRange()->cloneRange();
|
| - range->setEnd(position.computeContainerNode(), position.computeOffsetInContainerNode(), exceptionState);
|
| - if (exceptionState.hadException())
|
| - return 0;
|
| - return TextIterator::rangeLength(range->startPosition(), range->endPosition());
|
| -}
|
| -
|
| -bool TextCheckingParagraph::isEmpty() const
|
| -{
|
| - // Both predicates should have same result, but we check both just for sure.
|
| - // We need to investigate to remove this redundancy.
|
| - return isRangeEmpty() || isTextEmpty();
|
| -}
|
| -
|
| -PassRefPtrWillBeRawPtr<Range> TextCheckingParagraph::offsetAsRange() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (!m_offsetAsRange)
|
| - m_offsetAsRange = Range::create(paragraphRange()->startContainer()->document(), paragraphRange()->startPosition(), checkingRange()->startPosition());
|
| -
|
| - return m_offsetAsRange;
|
| -}
|
| -
|
| -const String& TextCheckingParagraph::text() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (m_text.isEmpty())
|
| - m_text = plainText(EphemeralRange(paragraphRange().get()));
|
| - return m_text;
|
| -}
|
| -
|
| -int TextCheckingParagraph::checkingStart() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (m_checkingStart == -1)
|
| - m_checkingStart = TextIterator::rangeLength(offsetAsRange()->startPosition(), offsetAsRange()->endPosition());
|
| - return m_checkingStart;
|
| -}
|
| -
|
| -int TextCheckingParagraph::checkingEnd() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (m_checkingEnd == -1)
|
| - m_checkingEnd = checkingStart() + TextIterator::rangeLength(checkingRange()->startPosition(), checkingRange()->endPosition());
|
| - return m_checkingEnd;
|
| -}
|
| -
|
| -int TextCheckingParagraph::checkingLength() const
|
| -{
|
| - ASSERT(m_checkingRange);
|
| - if (-1 == m_checkingLength)
|
| - m_checkingLength = TextIterator::rangeLength(checkingRange()->startPosition(), checkingRange()->endPosition());
|
| - return m_checkingLength;
|
| -}
|
| -
|
| -TextCheckingHelper::TextCheckingHelper(SpellCheckerClient& client, const Position& start, const Position& end)
|
| - : m_client(&client)
|
| - , m_start(start)
|
| - , m_end(end)
|
| -{
|
| -}
|
| -
|
| -TextCheckingHelper::~TextCheckingHelper()
|
| -{
|
| -}
|
| -
|
| -String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtrWillBeRawPtr<Range>& firstMisspellingRange)
|
| -{
|
| - WordAwareIterator it(m_start, m_end);
|
| - firstMisspellingOffset = 0;
|
| -
|
| - String firstMisspelling;
|
| - int currentChunkOffset = 0;
|
| -
|
| - while (!it.atEnd()) {
|
| - int length = it.length();
|
| -
|
| - // Skip some work for one-space-char hunks
|
| - if (!(length == 1 && it.characterAt(0) == ' ')) {
|
| -
|
| - int misspellingLocation = -1;
|
| - int misspellingLength = 0;
|
| - m_client->textChecker().checkSpellingOfString(it.substring(0, length), &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 < length);
|
| - ASSERT(misspellingLength <= length);
|
| - ASSERT(misspellingLocation + misspellingLength <= length);
|
| -
|
| - if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < length && misspellingLength <= length && misspellingLocation + misspellingLength <= length) {
|
| -
|
| - // Compute range of misspelled word
|
| - const EphemeralRange misspellingRange = calculateCharacterSubrange(EphemeralRange(m_start, m_end), currentChunkOffset + misspellingLocation, misspellingLength);
|
| -
|
| - // Remember first-encountered misspelling and its offset.
|
| - if (!firstMisspelling) {
|
| - firstMisspellingOffset = currentChunkOffset + misspellingLocation;
|
| - firstMisspelling = it.substring(misspellingLocation, misspellingLength);
|
| - firstMisspellingRange = Range::create(misspellingRange.document(), m_start, m_end);
|
| - }
|
| -
|
| - // Store marker for misspelled word.
|
| - misspellingRange.document().markers().addMarker(misspellingRange.startPosition(), misspellingRange.endPosition(), DocumentMarker::Spelling);
|
| -
|
| - // Bail out if we're marking only the first misspelling, and not all instances.
|
| - if (!markAll)
|
| - break;
|
| - }
|
| - }
|
| -
|
| - currentChunkOffset += length;
|
| - it.advance();
|
| - }
|
| -
|
| - return firstMisspelling;
|
| -}
|
| -
|
| -String TextCheckingHelper::findFirstMisspellingOrBadGrammar(bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail)
|
| -{
|
| - if (!unifiedTextCheckerEnabled())
|
| - return "";
|
| -
|
| - String firstFoundItem;
|
| - String misspelledWord;
|
| - String badGrammarPhrase;
|
| -
|
| - // 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.
|
| - Position paragraphStart = startOfParagraph(VisiblePosition(m_start)).toParentAnchoredPosition();
|
| - Position paragraphEnd = m_end;
|
| - int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEnd);
|
| - paragraphEnd = endOfParagraph(VisiblePosition(m_start)).toParentAnchoredPosition();
|
| -
|
| - int rangeStartOffset = TextIterator::rangeLength(paragraphStart, m_start);
|
| - 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(paragraphStart, paragraphEnd);
|
| - int currentStartOffset = firstIteration ? rangeStartOffset : 0;
|
| - int currentEndOffset = currentLength;
|
| - if (inSameParagraph(VisiblePosition(paragraphStart), VisiblePosition(m_end))) {
|
| - // 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.
|
| - currentEndOffset = TextIterator::rangeLength(paragraphStart, m_end);
|
| - lastIteration = true;
|
| - }
|
| - 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;
|
| - TextCheckingTypeMask checkingTypes = checkGrammar ? (TextCheckingTypeSpelling | TextCheckingTypeGrammar) : TextCheckingTypeSpelling;
|
| - checkTextOfParagraph(m_client->textChecker(), paragraphString, checkingTypes, results);
|
| -
|
| - for (unsigned i = 0; i < results.size(); i++) {
|
| - const TextCheckingResult* result = &results[i];
|
| - if (result->decoration == TextDecorationTypeSpelling && 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->decoration == TextDecorationTypeGrammar && 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)
|
| - spellingOffset += TextIterator::rangeLength(m_start, paragraphStart);
|
| - outIsSpelling = true;
|
| - outFirstFoundOffset = spellingOffset;
|
| - firstFoundItem = misspelledWord;
|
| - break;
|
| - }
|
| - if (checkGrammar && !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)
|
| - break;
|
| - VisiblePosition newParagraphStart = startOfNextParagraph(VisiblePosition(paragraphEnd));
|
| - paragraphStart = newParagraphStart.toParentAnchoredPosition();
|
| - paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPosition();
|
| - firstIteration = false;
|
| - totalLengthProcessed += currentLength;
|
| - }
|
| - 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];
|
| - 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) {
|
| - 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(Range::create(m_start.computeContainerNode()->document(), 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) {
|
| - 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, paragraph.checkingStart(), paragraph.checkingEnd(), 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 - 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;
|
| -}
|
| -
|
| -void TextCheckingHelper::markAllMisspellings(RefPtrWillBeRawPtr<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()
|
| -{
|
| - // Use the "markAll" feature of ofindFirstBadGrammar. 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
|
| -{
|
| - ASSERT(m_start.isNotNull());
|
| - Document& doc = m_start.computeContainerNode()->document();
|
| - return blink::unifiedTextCheckerEnabled(doc.frame());
|
| -}
|
| -
|
| -void checkTextOfParagraph(TextCheckerClient& client, const String& text, TextCheckingTypeMask checkingTypes, Vector<TextCheckingResult>& results)
|
| -{
|
| - Vector<UChar> characters;
|
| - text.appendTo(characters);
|
| - unsigned length = text.length();
|
| -
|
| - Vector<TextCheckingResult> spellingResult;
|
| - if (checkingTypes & TextCheckingTypeSpelling)
|
| - findMisspellings(client, characters.data(), 0, length, spellingResult);
|
| -
|
| - Vector<TextCheckingResult> grammarResult;
|
| - if (checkingTypes & TextCheckingTypeGrammar) {
|
| - // Only checks grammartical error before the first misspellings
|
| - int grammarCheckLength = length;
|
| - for (const auto& spelling : spellingResult) {
|
| - if (spelling.location < grammarCheckLength)
|
| - grammarCheckLength = spelling.location;
|
| - }
|
| -
|
| - 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)
|
| - return false;
|
| -
|
| - const Settings* settings = frame->settings();
|
| - if (!settings)
|
| - return false;
|
| -
|
| - return settings->unifiedTextCheckerEnabled();
|
| -}
|
| -
|
| -}
|
|
|