Index: third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
index b73d2fc09cebd1e44ac6a0d6791d46166f8cf925..0c89d47e76816c3c67a2a0e6d7c469ff7da1069c 100644 |
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp |
@@ -144,7 +144,7 @@ void SpellChecker::didBeginEditing(Element* element) |
return; |
// We always recheck textfields because markers are removed from them on blur. |
VisibleSelection selection = VisibleSelection::selectionFromContentsOfNode(element); |
- markMisspellings(selection); |
+ markMisspellingsAndBadGrammar(selection); |
if (!isTextField) |
parent->setAlreadySpellChecked(true); |
} |
@@ -226,20 +226,90 @@ void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) |
int searchEndOffsetAfterWrap = spellingSearchEnd.offsetInContainerNode(); |
int misspellingOffset = 0; |
- String misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspelling(misspellingOffset, false); |
+ GrammarDetail grammarDetail; |
+ int grammarPhraseOffset = 0; |
+ Position grammarSearchStart, grammarSearchEnd; |
+ String badGrammarPhrase; |
+ String misspelledWord; |
+ |
+ bool isSpelling = true; |
+ int foundOffset = 0; |
+ String foundItem; |
+ if (unifiedTextCheckerEnabled()) { |
+ grammarSearchStart = spellingSearchStart; |
+ grammarSearchEnd = spellingSearchEnd; |
+ foundItem = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspellingOrBadGrammar(isSpelling, foundOffset, grammarDetail); |
+ if (isSpelling) { |
+ misspelledWord = foundItem; |
+ misspellingOffset = foundOffset; |
+ } else { |
+ badGrammarPhrase = foundItem; |
+ grammarPhraseOffset = foundOffset; |
+ } |
+ } else { |
+ misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspelling(misspellingOffset, false); |
+ grammarSearchStart = spellingSearchStart; |
+ grammarSearchEnd = spellingSearchEnd; |
+ if (!misspelledWord.isEmpty()) { |
+ // Stop looking at start of next misspelled word |
+ CharacterIterator chars(grammarSearchStart, grammarSearchEnd); |
+ chars.advance(misspellingOffset); |
+ grammarSearchEnd = chars.startPosition(); |
+ } |
- // If we did not find a misspelled word, wrap and try again (but don't bother if we started at the beginning of the |
+ badGrammarPhrase = TextCheckingHelper(spellCheckerClient(), grammarSearchStart, grammarSearchEnd).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false); |
+ } |
+ |
+ // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the |
// block rather than at a selection). |
- if (startedWithSelection && !misspelledWord) { |
+ if (startedWithSelection && !misspelledWord && !badGrammarPhrase) { |
spellingSearchStart = Position::editingPositionOf(topNode, 0); |
// going until the end of the very first chunk we tested is far enough |
spellingSearchEnd = Position::editingPositionOf(searchEndNodeAfterWrap, searchEndOffsetAfterWrap); |
- misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspelling(misspellingOffset, false); |
+ |
+ if (unifiedTextCheckerEnabled()) { |
+ grammarSearchStart = spellingSearchStart; |
+ grammarSearchEnd = spellingSearchEnd; |
+ foundItem = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspellingOrBadGrammar(isSpelling, foundOffset, grammarDetail); |
+ if (isSpelling) { |
+ misspelledWord = foundItem; |
+ misspellingOffset = foundOffset; |
+ } else { |
+ badGrammarPhrase = foundItem; |
+ grammarPhraseOffset = foundOffset; |
+ } |
+ } else { |
+ misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearchStart, spellingSearchEnd).findFirstMisspelling(misspellingOffset, false); |
+ grammarSearchStart = spellingSearchStart; |
+ grammarSearchEnd = spellingSearchEnd; |
+ if (!misspelledWord.isEmpty()) { |
+ // Stop looking at start of next misspelled word |
+ CharacterIterator chars(grammarSearchStart, grammarSearchEnd); |
+ chars.advance(misspellingOffset); |
+ grammarSearchEnd = chars.startPosition(); |
+ } |
+ |
+ badGrammarPhrase = TextCheckingHelper(spellCheckerClient(), grammarSearchStart, grammarSearchEnd).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false); |
+ } |
} |
- if (!misspelledWord.isEmpty()) { |
- // We found a misspelling. Select the misspelling, update the spelling |
- // panel, and store a marker so we draw the red squiggle later. |
+ if (!badGrammarPhrase.isEmpty()) { |
+ // We found bad grammar. Since we only searched for bad grammar up to the first misspelled word, the bad grammar |
+ // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling |
+ // panel, and store a marker so we draw the green squiggle later. |
+ |
+ DCHECK_GT(badGrammarPhrase.length(), 0u); |
+ DCHECK_NE(grammarDetail.location, -1); |
+ DCHECK_GT(grammarDetail.length, 0); |
+ |
+ // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph |
+ const EphemeralRange badGrammarRange = calculateCharacterSubrange(EphemeralRange(grammarSearchStart, grammarSearchEnd), grammarPhraseOffset + grammarDetail.location, grammarDetail.length); |
+ frame().selection().setSelection(VisibleSelection(badGrammarRange)); |
+ frame().selection().revealSelection(); |
+ frame().document()->markers().addMarker(badGrammarRange.startPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, grammarDetail.userDescription); |
+ } else if (!misspelledWord.isEmpty()) { |
+ // We found a misspelling, but not any earlier bad grammar. Select the misspelling, update the spelling panel, and store |
+ // a marker so we draw the red squiggle later. |
const EphemeralRange misspellingRange = calculateCharacterSubrange(EphemeralRange(spellingSearchStart, spellingSearchEnd), misspellingOffset, misspelledWord.length()); |
frame().selection().setSelection(VisibleSelection(misspellingRange)); |
@@ -260,24 +330,14 @@ void SpellChecker::showSpellingGuessPanel() |
spellCheckerClient().showSpellingUI(true); |
} |
-void SpellChecker::clearMisspellings(const VisibleSelection &movingSelection) |
+void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &movingSelection) |
{ |
removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); |
} |
-void SpellChecker::markMisspellings(const VisibleSelection &movingSelection) |
+void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelection) |
{ |
- if (unifiedTextCheckerEnabled()) { |
- if (!isContinuousSpellCheckingEnabled()) |
- return; |
- |
- // markMisspellings() is triggered by selection change, in which |
- // case we check spelling, but don't autocorrect misspellings. |
- markAllMisspellingsInRange(movingSelection.toNormalizedEphemeralRange()); |
- return; |
- } |
- |
- markMisspellingsWithTextCheckingHelper(movingSelection); |
+ markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnabled(), movingSelection); |
} |
void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSelection) |
@@ -285,12 +345,22 @@ void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe |
TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterLineBreak"); |
if (!unifiedTextCheckerEnabled()) { |
- markMisspellingsWithTextCheckingHelper(wordSelection); |
+ markMisspellings(wordSelection); |
return; |
} |
+ TextCheckingTypeMask textCheckingOptions = TextCheckingTypeGrammar; |
+ |
if (isContinuousSpellCheckingEnabled()) |
- markAllMisspellingsInRange(wordSelection.toNormalizedEphemeralRange()); |
+ textCheckingOptions |= TextCheckingTypeSpelling; |
+ |
+ VisibleSelection wholeParagraph( |
+ startOfParagraph(wordSelection.visibleStart()), |
+ endOfParagraph(wordSelection.visibleEnd())); |
+ |
+ markAllMisspellingsAndBadGrammarInRanges( |
+ textCheckingOptions, wordSelection.toNormalizedEphemeralRange(), |
+ wholeParagraph.toNormalizedEphemeralRange()); |
} |
void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping) |
@@ -306,8 +376,15 @@ void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word |
if (!(textCheckingOptions & TextCheckingTypeSpelling)) |
return; |
+ textCheckingOptions |= TextCheckingTypeGrammar; |
+ |
VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)); |
- markAllMisspellingsInRange(adjacentWords.toNormalizedEphemeralRange()); |
+ if (textCheckingOptions & TextCheckingTypeGrammar) { |
+ VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart)); |
+ markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedEphemeralRange(), selectedSentence.toNormalizedEphemeralRange()); |
+ } else { |
+ markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedEphemeralRange(), adjacentWords.toNormalizedEphemeralRange()); |
+ } |
return; |
} |
@@ -315,7 +392,45 @@ void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word |
return; |
// Check spelling of one word |
- markMisspellingsWithTextCheckingHelper(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary))); |
+ bool result = markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary))); |
+ |
+ if (!result) |
+ return; |
+ |
+ // Check grammar of entire sentence |
+ markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart))); |
+} |
+ |
+bool SpellChecker::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling) |
+{ |
+ // 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()) |
+ return false; |
+ |
+ TRACE_EVENT0("blink", "SpellChecker::markMisspellingsOrBadGrammar"); |
+ |
+ const EphemeralRange range = selection.toNormalizedEphemeralRange(); |
+ if (range.isNull()) |
+ return false; |
+ |
+ // If we're not in an editable node, bail. |
+ Node* editableNode = range.startPosition().computeContainerNode(); |
+ if (!editableNode || !hasEditableStyle(*editableNode)) |
+ return false; |
+ |
+ if (!isSpellCheckingEnabledFor(editableNode)) |
+ return false; |
+ |
+ TextCheckingHelper checker(spellCheckerClient(), range.startPosition(), range.endPosition()); |
+ if (checkSpelling) |
+ return checker.markAllMisspellings(); |
+ |
+ checker.markAllBadGrammar(); |
+ return false; |
} |
bool SpellChecker::isSpellCheckingEnabledFor(Node* node) const |
@@ -350,39 +465,24 @@ bool SpellChecker::isSpellCheckingEnabledFor(const VisibleSelection& selection) |
return false; |
} |
-void SpellChecker::markMisspellingsWithTextCheckingHelper(const VisibleSelection& selection) |
+bool SpellChecker::markMisspellings(const VisibleSelection& selection) |
{ |
- // This function is called with a selection already expanded to word boundaries. |
- // TODO(xiaochengh): 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. |
- if (!isContinuousSpellCheckingEnabled()) |
- return; |
- |
- TRACE_EVENT0("blink", "SpellChecker::markMisspellings"); |
- |
- const EphemeralRange& range = selection.toNormalizedEphemeralRange(); |
- if (range.isNull()) |
- return; |
- |
- // If we're not in an editable node, bail. |
- Node* editableNode = range.startPosition().computeContainerNode(); |
- if (!editableNode || !hasEditableStyle(*editableNode)) |
- return; |
- |
- if (!isSpellCheckingEnabledFor(editableNode)) |
- return; |
+ return markMisspellingsOrBadGrammar(selection, true); |
+} |
- TextCheckingHelper checker(spellCheckerClient(), range.startPosition(), range.endPosition()); |
- checker.markAllMisspellings(); |
+void SpellChecker::markBadGrammar(const VisibleSelection& selection) |
+{ |
+ markMisspellingsOrBadGrammar(selection, false); |
} |
-void SpellChecker::markAllMisspellingsInRange(const EphemeralRange& spellingRange) |
+void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, const EphemeralRange& spellingRange, const EphemeralRange& grammarRange) |
{ |
DCHECK(unifiedTextCheckerEnabled()); |
+ bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
+ |
// This function is called with selections already expanded to word boundaries. |
- if (spellingRange.isNull()) |
+ if (spellingRange.isNull() || (shouldMarkGrammar && grammarRange.isNull())) |
return; |
// If we're not in an editable node, bail. |
@@ -393,8 +493,8 @@ void SpellChecker::markAllMisspellingsInRange(const EphemeralRange& spellingRang |
if (!isSpellCheckingEnabledFor(editableNode)) |
return; |
- TextCheckingParagraph fullParagraphToCheck(spellingRange); |
- chunkAndMarkAllMisspellings(fullParagraphToCheck); |
+ TextCheckingParagraph fullParagraphToCheck(shouldMarkGrammar ? grammarRange : spellingRange); |
+ chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphToCheck); |
} |
static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) |
@@ -415,17 +515,17 @@ static EphemeralRange expandRangeToSentenceBoundary(const EphemeralRange& range) |
return expandEndToSentenceBoundary(EphemeralRange(sentenceStart.isNull() ? range.startPosition() : sentenceStart, range.endPosition())); |
} |
-void SpellChecker::chunkAndMarkAllMisspellings(Node* node, const EphemeralRange& insertedRange) |
+void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node, const EphemeralRange& insertedRange) |
{ |
- TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellings"); |
+ TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar"); |
if (!node) |
return; |
EphemeralRange paragraphRange(Position::firstPositionInNode(node), Position::lastPositionInNode(node)); |
TextCheckingParagraph textToCheck(insertedRange, paragraphRange); |
- chunkAndMarkAllMisspellings(textToCheck); |
+ chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), textToCheck); |
} |
-void SpellChecker::chunkAndMarkAllMisspellings(const TextCheckingParagraph& fullParagraphToCheck) |
+void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck) |
{ |
if (fullParagraphToCheck.isEmpty()) |
return; |
@@ -437,7 +537,7 @@ void SpellChecker::chunkAndMarkAllMisspellings(const TextCheckingParagraph& full |
// Check the full paragraph instead if the paragraph is short, which saves |
// the cost on sentence boundary finding. |
if (fullParagraphToCheck.rangeLength() <= kChunkSize) { |
- SpellCheckRequest* request = SpellCheckRequest::create(TextCheckingTypeSpelling, TextCheckingProcessBatch, paragraphRange, paragraphRange, 0); |
+ SpellCheckRequest* request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, paragraphRange, paragraphRange, 0); |
if (request) |
m_spellCheckRequester->requestCheckingFor(request); |
return; |
@@ -448,7 +548,7 @@ void SpellChecker::chunkAndMarkAllMisspellings(const TextCheckingParagraph& full |
EphemeralRange chunkRange = checkRangeIterator.calculateCharacterSubrange(0, kChunkSize); |
EphemeralRange checkRange = requestNum ? expandEndToSentenceBoundary(chunkRange) : expandRangeToSentenceBoundary(chunkRange); |
- SpellCheckRequest* request = SpellCheckRequest::create(TextCheckingTypeSpelling, TextCheckingProcessBatch, checkRange, paragraphRange, requestNum); |
+ SpellCheckRequest* request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkRange, paragraphRange, requestNum); |
if (request) |
m_spellCheckRequester->requestCheckingFor(request); |
@@ -482,6 +582,7 @@ void SpellChecker::markAndReplaceFor(SpellCheckRequest* request, const Vector<Te |
TextCheckingParagraph paragraph(request->checkingRange(), request->paragraphRange()); |
bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
+ bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
// Expand the range to encompass entire paragraphs, since text checking needs that much context. |
int selectionOffset = 0; |
@@ -527,6 +628,18 @@ void SpellChecker::markAndReplaceFor(SpellCheckRequest* request, const Vector<Te |
DCHECK_GE(resultLocation, 0); |
const EphemeralRange misspellingRange = calculateCharacterSubrange(paragraph.paragraphRange(), resultLocation, resultLength); |
frame().document()->markers().addMarker(misspellingRange.startPosition(), misspellingRange.endPosition(), DocumentMarker::Spelling, result->replacement, result->hash); |
+ } else if (shouldMarkGrammar && result->decoration == TextDecorationTypeGrammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) { |
+ DCHECK_GT(resultLength, 0); |
+ DCHECK_GE(resultLocation, 0); |
+ 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 (paragraph.checkingRangeCovers(resultLocation + detail->location, detail->length)) { |
+ const EphemeralRange badGrammarRange = calculateCharacterSubrange(paragraph.paragraphRange(), resultLocation + detail->location, detail->length); |
+ frame().document()->markers().addMarker(badGrammarRange.startPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->userDescription, result->hash); |
+ } |
+ } |
} else if (result->decoration == TextDecorationTypeInvisibleSpellcheck && resultLocation >= paragraph.checkingStart() && resultLocation + resultLength <= spellingRangeEndOffset) { |
DCHECK_GT(resultLength, 0); |
DCHECK_GE(resultLocation, 0); |
@@ -553,6 +666,25 @@ void SpellChecker::markAndReplaceFor(SpellCheckRequest* request, const Vector<Te |
} |
} |
+void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection) |
+{ |
+ if (unifiedTextCheckerEnabled()) { |
+ if (!isContinuousSpellCheckingEnabled()) |
+ return; |
+ |
+ // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings. |
+ TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling; |
+ if (markGrammar) |
+ textCheckingOptions |= TextCheckingTypeGrammar; |
+ markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedEphemeralRange(), grammarSelection.toNormalizedEphemeralRange()); |
+ return; |
+ } |
+ |
+ markMisspellings(spellingSelection); |
+ if (markGrammar) |
+ markBadGrammar(grammarSelection); |
+} |
+ |
void SpellChecker::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary) |
{ |
DCHECK(frame().selection().isAvailable()); |
@@ -645,6 +777,8 @@ void SpellChecker::didEndEditingOnTextField(Element* e) |
HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlElement(e); |
HTMLElement* innerEditor = textFormControlElement->innerEditorElement(); |
DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling); |
+ if (unifiedTextCheckerEnabled()) |
+ markerTypes.add(DocumentMarker::Grammar); |
for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) |
frame().document()->markers().removeMarkers(&node, markerTypes); |
} |
@@ -685,6 +819,7 @@ void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio |
// When continuous spell checking is off, existing markers disappear after the selection changes. |
if (!isContinuousSpellCheckingEnabled()) { |
frame().document()->markers().removeMarkers(DocumentMarker::Spelling); |
+ frame().document()->markers().removeMarkers(DocumentMarker::Grammar); |
return; |
} |
@@ -751,7 +886,12 @@ void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection, |
VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); |
if (oldAdjacentWords == newAdjacentWords) |
return; |
- markMisspellings(oldAdjacentWords); |
+ if (isContinuousSpellCheckingEnabled()) { |
+ VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); |
+ markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSentence); |
+ return; |
+ } |
+ markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); |
} |
static Node* findFirstMarkable(Node* node) |
@@ -795,6 +935,20 @@ bool SpellChecker::selectionStartHasSpellingMarkerFor(int from, int length) cons |
return selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length); |
} |
+TextCheckingTypeMask SpellChecker::resolveTextCheckingTypeMask(TextCheckingTypeMask textCheckingOptions) |
+{ |
+ bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
+ bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
+ |
+ TextCheckingTypeMask checkingTypes = 0; |
+ if (shouldMarkSpelling) |
+ checkingTypes |= TextCheckingTypeSpelling; |
+ if (shouldMarkGrammar) |
+ checkingTypes |= TextCheckingTypeGrammar; |
+ |
+ return checkingTypes; |
+} |
+ |
void SpellChecker::removeMarkers(const VisibleSelection& selection, DocumentMarker::MarkerTypes markerTypes) |
{ |
const EphemeralRange range = selection.toNormalizedEphemeralRange(); |
@@ -816,7 +970,7 @@ void SpellChecker::cancelCheck() |
void SpellChecker::requestTextChecking(const Element& element) |
{ |
const EphemeralRange rangeToCheck = EphemeralRange::rangeOfContents(element); |
- m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling, TextCheckingProcessBatch, rangeToCheck, rangeToCheck)); |
+ m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToCheck, rangeToCheck)); |
} |
DEFINE_TRACE(SpellChecker) |