| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 return isHTMLTextAreaElement(textControl); | 64 return isHTMLTextAreaElement(textControl); |
| 65 } | 65 } |
| 66 | 66 |
| 67 bool isSelectionInTextFormControl(const VisibleSelection& selection) | 67 bool isSelectionInTextFormControl(const VisibleSelection& selection) |
| 68 { | 68 { |
| 69 return !!enclosingTextFormControl(selection.start()); | 69 return !!enclosingTextFormControl(selection.start()); |
| 70 } | 70 } |
| 71 | 71 |
| 72 } // namespace | 72 } // namespace |
| 73 | 73 |
| 74 PassOwnPtr<SpellChecker> SpellChecker::create(LocalFrame& frame) | 74 PassOwnPtrWillBeRawPtr<SpellChecker> SpellChecker::create(LocalFrame& frame) |
| 75 { | 75 { |
| 76 return adoptPtr(new SpellChecker(frame)); | 76 return adoptPtrWillBeNoop(new SpellChecker(frame)); |
| 77 } | 77 } |
| 78 | 78 |
| 79 static SpellCheckerClient& emptySpellCheckerClient() | 79 static SpellCheckerClient& emptySpellCheckerClient() |
| 80 { | 80 { |
| 81 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); | 81 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); |
| 82 return client; | 82 return client; |
| 83 } | 83 } |
| 84 | 84 |
| 85 SpellCheckerClient& SpellChecker::spellCheckerClient() const | 85 SpellCheckerClient& SpellChecker::spellCheckerClient() const |
| 86 { | 86 { |
| 87 if (Page* page = m_frame.page()) | 87 if (Page* page = m_frame->page()) |
| 88 return page->spellCheckerClient(); | 88 return page->spellCheckerClient(); |
| 89 return emptySpellCheckerClient(); | 89 return emptySpellCheckerClient(); |
| 90 } | 90 } |
| 91 | 91 |
| 92 TextCheckerClient& SpellChecker::textChecker() const | 92 TextCheckerClient& SpellChecker::textChecker() const |
| 93 { | 93 { |
| 94 return spellCheckerClient().textChecker(); | 94 return spellCheckerClient().textChecker(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 SpellChecker::SpellChecker(LocalFrame& frame) | 97 SpellChecker::SpellChecker(LocalFrame& frame) |
| 98 : m_frame(frame) | 98 : m_frame(&frame) |
| 99 , m_spellCheckRequester(adoptPtr(new SpellCheckRequester(frame))) | 99 , m_spellCheckRequester(SpellCheckRequester::create(frame)) |
| 100 { | 100 { |
| 101 } | 101 } |
| 102 | 102 |
| 103 SpellChecker::~SpellChecker() | 103 SpellChecker::~SpellChecker() |
| 104 { | 104 { |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool SpellChecker::isContinuousSpellCheckingEnabled() const | 107 bool SpellChecker::isContinuousSpellCheckingEnabled() const |
| 108 { | 108 { |
| 109 return spellCheckerClient().isContinuousSpellCheckingEnabled(); | 109 return spellCheckerClient().isContinuousSpellCheckingEnabled(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void SpellChecker::toggleContinuousSpellChecking() | 112 void SpellChecker::toggleContinuousSpellChecking() |
| 113 { | 113 { |
| 114 spellCheckerClient().toggleContinuousSpellChecking(); | 114 spellCheckerClient().toggleContinuousSpellChecking(); |
| 115 if (isContinuousSpellCheckingEnabled()) | 115 if (isContinuousSpellCheckingEnabled()) |
| 116 return; | 116 return; |
| 117 for (Frame* frame = m_frame.page()->mainFrame(); frame; frame = frame->tree(
).traverseNext()) { | 117 for (Frame* frame = m_frame->page()->mainFrame(); frame; frame = frame->tree
().traverseNext()) { |
| 118 if (!frame->isLocalFrame()) | 118 if (!frame->isLocalFrame()) |
| 119 continue; | 119 continue; |
| 120 for (Node* node = &toLocalFrame(frame)->document()->rootNode(); node; no
de = NodeTraversal::next(*node)) { | 120 for (Node* node = &toLocalFrame(frame)->document()->rootNode(); node; no
de = NodeTraversal::next(*node)) { |
| 121 node->setAlreadySpellChecked(false); | 121 node->setAlreadySpellChecked(false); |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 bool SpellChecker::isGrammarCheckingEnabled() | 126 bool SpellChecker::isGrammarCheckingEnabled() |
| 127 { | 127 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 149 VisibleSelection selection = VisibleSelection::selectionFromContents
OfNode(element); | 149 VisibleSelection selection = VisibleSelection::selectionFromContents
OfNode(element); |
| 150 markMisspellingsAndBadGrammar(selection); | 150 markMisspellingsAndBadGrammar(selection); |
| 151 if (!isTextField) | 151 if (!isTextField) |
| 152 parent->setAlreadySpellChecked(true); | 152 parent->setAlreadySpellChecked(true); |
| 153 } | 153 } |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 void SpellChecker::ignoreSpelling() | 157 void SpellChecker::ignoreSpelling() |
| 158 { | 158 { |
| 159 if (RefPtrWillBeRawPtr<Range> selectedRange = m_frame.selection().toNormaliz
edRange()) | 159 if (RefPtrWillBeRawPtr<Range> selectedRange = m_frame->selection().toNormali
zedRange()) |
| 160 m_frame.document()->markers().removeMarkers(selectedRange.get(), Documen
tMarker::Spelling); | 160 m_frame->document()->markers().removeMarkers(selectedRange.get(), Docume
ntMarker::Spelling); |
| 161 } | 161 } |
| 162 | 162 |
| 163 void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) | 163 void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) |
| 164 { | 164 { |
| 165 // The basic approach is to search in two phases - from the selection end to
the end of the doc, and | 165 // The basic approach is to search in two phases - from the selection end to
the end of the doc, and |
| 166 // then we wrap and search from the doc start to (approximately) where we st
arted. | 166 // then we wrap and search from the doc start to (approximately) where we st
arted. |
| 167 | 167 |
| 168 // Start at the end of the selection, search to edge of document. Starting a
t the selection end makes | 168 // Start at the end of the selection, search to edge of document. Starting a
t the selection end makes |
| 169 // repeated "check spelling" commands work. | 169 // repeated "check spelling" commands work. |
| 170 VisibleSelection selection(m_frame.selection().selection()); | 170 VisibleSelection selection(m_frame->selection().selection()); |
| 171 Position spellingSearchStart, spellingSearchEnd; | 171 Position spellingSearchStart, spellingSearchEnd; |
| 172 Range::selectNodeContents(m_frame.document(), spellingSearchStart, spellingS
earchEnd); | 172 Range::selectNodeContents(m_frame->document(), spellingSearchStart, spelling
SearchEnd); |
| 173 | 173 |
| 174 bool startedWithSelection = false; | 174 bool startedWithSelection = false; |
| 175 if (selection.start().deprecatedNode()) { | 175 if (selection.start().deprecatedNode()) { |
| 176 startedWithSelection = true; | 176 startedWithSelection = true; |
| 177 if (startBeforeSelection) { | 177 if (startBeforeSelection) { |
| 178 VisiblePosition start(selection.visibleStart()); | 178 VisiblePosition start(selection.visibleStart()); |
| 179 // We match AppKit's rule: Start 1 character before the selection. | 179 // We match AppKit's rule: Start 1 character before the selection. |
| 180 VisiblePosition oneBeforeStart = start.previous(); | 180 VisiblePosition oneBeforeStart = start.previous(); |
| 181 spellingSearchStart = (oneBeforeStart.isNotNull() ? oneBeforeStart :
start).toParentAnchoredPosition(); | 181 spellingSearchStart = (oneBeforeStart.isNotNull() ? oneBeforeStart :
start).toParentAnchoredPosition(); |
| 182 } else { | 182 } else { |
| 183 spellingSearchStart = selection.visibleEnd().toParentAnchoredPositio
n(); | 183 spellingSearchStart = selection.visibleEnd().toParentAnchoredPositio
n(); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 Position position = spellingSearchStart; | 187 Position position = spellingSearchStart; |
| 188 if (!isEditablePosition(position)) { | 188 if (!isEditablePosition(position)) { |
| 189 // This shouldn't happen in very often because the Spelling menu items a
ren't enabled unless the | 189 // This shouldn't happen in very often because the Spelling menu items a
ren't enabled unless the |
| 190 // selection is editable. | 190 // selection is editable. |
| 191 // This can happen in Mail for a mix of non-editable and editable conten
t (like Stationary), | 191 // This can happen in Mail for a mix of non-editable and editable conten
t (like Stationary), |
| 192 // when spell checking the whole document before sending the message. | 192 // when spell checking the whole document before sending the message. |
| 193 // In that case the document might not be editable, but there are editab
le pockets that need to be spell checked. | 193 // In that case the document might not be editable, but there are editab
le pockets that need to be spell checked. |
| 194 | 194 |
| 195 position = firstEditableVisiblePositionAfterPositionInRoot(position, m_f
rame.document()->documentElement()).deepEquivalent(); | 195 position = firstEditableVisiblePositionAfterPositionInRoot(position, m_f
rame->document()->documentElement()).deepEquivalent(); |
| 196 if (position.isNull()) | 196 if (position.isNull()) |
| 197 return; | 197 return; |
| 198 | 198 |
| 199 spellingSearchStart = position.parentAnchoredEquivalent(); | 199 spellingSearchStart = position.parentAnchoredEquivalent(); |
| 200 startedWithSelection = false; // won't need to wrap | 200 startedWithSelection = false; // won't need to wrap |
| 201 } | 201 } |
| 202 | 202 |
| 203 // topNode defines the whole range we want to operate on | 203 // topNode defines the whole range we want to operate on |
| 204 ContainerNode* topNode = highestEditableRoot(position); | 204 ContainerNode* topNode = highestEditableRoot(position); |
| 205 // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(high
estEditableRoot()) returns true (e.g. a <table>) | 205 // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(high
estEditableRoot()) returns true (e.g. a <table>) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 // takes precedence and we ignore any potential misspelled word. Select
the grammar detail, update the spelling | 299 // takes precedence and we ignore any potential misspelled word. Select
the grammar detail, update the spelling |
| 300 // panel, and store a marker so we draw the green squiggle later. | 300 // panel, and store a marker so we draw the green squiggle later. |
| 301 | 301 |
| 302 ASSERT(badGrammarPhrase.length() > 0); | 302 ASSERT(badGrammarPhrase.length() > 0); |
| 303 ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0); | 303 ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0); |
| 304 | 304 |
| 305 // FIXME 4859190: This gets confused with doubled punctuation at the end
of a paragraph | 305 // FIXME 4859190: This gets confused with doubled punctuation at the end
of a paragraph |
| 306 Position badGrammarStart = grammarSearchStart; | 306 Position badGrammarStart = grammarSearchStart; |
| 307 Position badGrammarEnd = grammarSearchEnd; | 307 Position badGrammarEnd = grammarSearchEnd; |
| 308 TextIterator::subrange(badGrammarStart, badGrammarEnd, grammarPhraseOffs
et + grammarDetail.location, grammarDetail.length); | 308 TextIterator::subrange(badGrammarStart, badGrammarEnd, grammarPhraseOffs
et + grammarDetail.location, grammarDetail.length); |
| 309 m_frame.selection().setSelection(VisibleSelection(badGrammarStart, badGr
ammarEnd)); | 309 m_frame->selection().setSelection(VisibleSelection(badGrammarStart, badG
rammarEnd)); |
| 310 m_frame.selection().revealSelection(); | 310 m_frame->selection().revealSelection(); |
| 311 | 311 |
| 312 m_frame.document()->markers().addMarker(badGrammarStart, badGrammarEnd,
DocumentMarker::Grammar, grammarDetail.userDescription); | 312 m_frame->document()->markers().addMarker(badGrammarStart, badGrammarEnd,
DocumentMarker::Grammar, grammarDetail.userDescription); |
| 313 } else if (!misspelledWord.isEmpty()) { | 313 } else if (!misspelledWord.isEmpty()) { |
| 314 // We found a misspelling, but not any earlier bad grammar. Select the m
isspelling, update the spelling panel, and store | 314 // We found a misspelling, but not any earlier bad grammar. Select the m
isspelling, update the spelling panel, and store |
| 315 // a marker so we draw the red squiggle later. | 315 // a marker so we draw the red squiggle later. |
| 316 | 316 |
| 317 Position misspellingStart = spellingSearchStart; | 317 Position misspellingStart = spellingSearchStart; |
| 318 Position misspellingEnd = spellingSearchEnd; | 318 Position misspellingEnd = spellingSearchEnd; |
| 319 TextIterator::subrange(misspellingStart, misspellingEnd, misspellingOffs
et, misspelledWord.length()); | 319 TextIterator::subrange(misspellingStart, misspellingEnd, misspellingOffs
et, misspelledWord.length()); |
| 320 m_frame.selection().setSelection(VisibleSelection(misspellingStart, miss
pellingEnd, DOWNSTREAM)); | 320 m_frame->selection().setSelection(VisibleSelection(misspellingStart, mis
spellingEnd, DOWNSTREAM)); |
| 321 m_frame.selection().revealSelection(); | 321 m_frame->selection().revealSelection(); |
| 322 | 322 |
| 323 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); | 323 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); |
| 324 m_frame.document()->markers().addMarker(misspellingStart, misspellingEnd
, DocumentMarker::Spelling); | 324 m_frame->document()->markers().addMarker(misspellingStart, misspellingEn
d, DocumentMarker::Spelling); |
| 325 } | 325 } |
| 326 } | 326 } |
| 327 | 327 |
| 328 void SpellChecker::showSpellingGuessPanel() | 328 void SpellChecker::showSpellingGuessPanel() |
| 329 { | 329 { |
| 330 if (spellCheckerClient().spellingUIIsShowing()) { | 330 if (spellCheckerClient().spellingUIIsShowing()) { |
| 331 spellCheckerClient().showSpellingUI(false); | 331 spellCheckerClient().showSpellingUI(false); |
| 332 return; | 332 return; |
| 333 } | 333 } |
| 334 | 334 |
| 335 advanceToNextMisspelling(true); | 335 advanceToNextMisspelling(true); |
| 336 spellCheckerClient().showSpellingUI(true); | 336 spellCheckerClient().showSpellingUI(true); |
| 337 } | 337 } |
| 338 | 338 |
| 339 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) | 339 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) |
| 340 { | 340 { |
| 341 RefPtrWillBeRawPtr<Range> selectedRange = movingSelection.toNormalizedRange(
); | 341 RefPtrWillBeRawPtr<Range> selectedRange = movingSelection.toNormalizedRange(
); |
| 342 if (selectedRange) | 342 if (selectedRange) |
| 343 m_frame.document()->markers().removeMarkers(selectedRange.get(), Documen
tMarker::MisspellingMarkers()); | 343 m_frame->document()->markers().removeMarkers(selectedRange.get(), Docume
ntMarker::MisspellingMarkers()); |
| 344 } | 344 } |
| 345 | 345 |
| 346 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingS
election) | 346 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingS
election) |
| 347 { | 347 { |
| 348 markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnab
led() && isGrammarCheckingEnabled(), movingSelection); | 348 markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnab
led() && isGrammarCheckingEnabled(), movingSelection); |
| 349 } | 349 } |
| 350 | 350 |
| 351 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe
lection) | 351 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe
lection) |
| 352 { | 352 { |
| 353 if (unifiedTextCheckerEnabled()) { | 353 if (unifiedTextCheckerEnabled()) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 if (!misspellingRange) | 407 if (!misspellingRange) |
| 408 return; | 408 return; |
| 409 | 409 |
| 410 // Get the misspelled word. | 410 // Get the misspelled word. |
| 411 const String misspelledWord = plainText(misspellingRange.get()); | 411 const String misspelledWord = plainText(misspellingRange.get()); |
| 412 String autocorrectedString = textChecker().getAutoCorrectSuggestionForMisspe
lledWord(misspelledWord); | 412 String autocorrectedString = textChecker().getAutoCorrectSuggestionForMisspe
lledWord(misspelledWord); |
| 413 | 413 |
| 414 // If autocorrected word is non empty, replace the misspelled word by this w
ord. | 414 // If autocorrected word is non empty, replace the misspelled word by this w
ord. |
| 415 if (!autocorrectedString.isEmpty()) { | 415 if (!autocorrectedString.isEmpty()) { |
| 416 VisibleSelection newSelection(misspellingRange.get(), DOWNSTREAM); | 416 VisibleSelection newSelection(misspellingRange.get(), DOWNSTREAM); |
| 417 if (newSelection != m_frame.selection().selection()) { | 417 if (newSelection != m_frame->selection().selection()) { |
| 418 m_frame.selection().setSelection(newSelection); | 418 m_frame->selection().setSelection(newSelection); |
| 419 } | 419 } |
| 420 | 420 |
| 421 m_frame.editor().replaceSelectionWithText(autocorrectedString, false, fa
lse); | 421 m_frame->editor().replaceSelectionWithText(autocorrectedString, false, f
alse); |
| 422 | 422 |
| 423 // Reset the charet one character further. | 423 // Reset the charet one character further. |
| 424 m_frame.selection().moveTo(m_frame.selection().selection().visibleEnd())
; | 424 m_frame->selection().moveTo(m_frame->selection().selection().visibleEnd(
)); |
| 425 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForw
ard, CharacterGranularity); | 425 m_frame->selection().modify(FrameSelection::AlterationMove, DirectionFor
ward, CharacterGranularity); |
| 426 } | 426 } |
| 427 | 427 |
| 428 if (!isGrammarCheckingEnabled()) | 428 if (!isGrammarCheckingEnabled()) |
| 429 return; | 429 return; |
| 430 | 430 |
| 431 // Check grammar of entire sentence | 431 // Check grammar of entire sentence |
| 432 markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wo
rdStart))); | 432 markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wo
rdStart))); |
| 433 } | 433 } |
| 434 | 434 |
| 435 void SpellChecker::markMisspellingsOrBadGrammar(const VisibleSelection& selectio
n, bool checkSpelling, RefPtrWillBeRawPtr<Range>& firstMisspellingRange) | 435 void SpellChecker::markMisspellingsOrBadGrammar(const VisibleSelection& selectio
n, bool checkSpelling, RefPtrWillBeRawPtr<Range>& firstMisspellingRange) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 466 if (!node) | 466 if (!node) |
| 467 return false; | 467 return false; |
| 468 const Element* focusedElement = node->isElementNode() ? toElement(node) : no
de->parentElement(); | 468 const Element* focusedElement = node->isElementNode() ? toElement(node) : no
de->parentElement(); |
| 469 if (!focusedElement) | 469 if (!focusedElement) |
| 470 return false; | 470 return false; |
| 471 return focusedElement->isSpellCheckingEnabled(); | 471 return focusedElement->isSpellCheckingEnabled(); |
| 472 } | 472 } |
| 473 | 473 |
| 474 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const | 474 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const |
| 475 { | 475 { |
| 476 return isSpellCheckingEnabledFor(m_frame.selection().start().deprecatedNode(
)); | 476 return isSpellCheckingEnabledFor(m_frame->selection().start().deprecatedNode
()); |
| 477 } | 477 } |
| 478 | 478 |
| 479 void SpellChecker::markMisspellings(const VisibleSelection& selection, RefPtrWil
lBeRawPtr<Range>& firstMisspellingRange) | 479 void SpellChecker::markMisspellings(const VisibleSelection& selection, RefPtrWil
lBeRawPtr<Range>& firstMisspellingRange) |
| 480 { | 480 { |
| 481 markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange); | 481 markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange); |
| 482 } | 482 } |
| 483 | 483 |
| 484 void SpellChecker::markBadGrammar(const VisibleSelection& selection) | 484 void SpellChecker::markBadGrammar(const VisibleSelection& selection) |
| 485 { | 485 { |
| 486 RefPtrWillBeRawPtr<Range> firstMisspellingRange = nullptr; | 486 RefPtrWillBeRawPtr<Range> firstMisspellingRange = nullptr; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 501 Node* editableNode = spellingRange->startContainer(); | 501 Node* editableNode = spellingRange->startContainer(); |
| 502 if (!editableNode || !editableNode->hasEditableStyle()) | 502 if (!editableNode || !editableNode->hasEditableStyle()) |
| 503 return; | 503 return; |
| 504 | 504 |
| 505 if (!isSpellCheckingEnabledFor(editableNode)) | 505 if (!isSpellCheckingEnabledFor(editableNode)) |
| 506 return; | 506 return; |
| 507 | 507 |
| 508 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; | 508 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; |
| 509 TextCheckingParagraph fullParagraphToCheck(rangeToCheck); | 509 TextCheckingParagraph fullParagraphToCheck(rangeToCheck); |
| 510 | 510 |
| 511 bool asynchronous = m_frame.settings() && m_frame.settings()->asynchronousSp
ellCheckingEnabled(); | 511 bool asynchronous = m_frame->settings() && m_frame->settings()->asynchronous
SpellCheckingEnabled(); |
| 512 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT
oCheck, asynchronous); | 512 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT
oCheck, asynchronous); |
| 513 } | 513 } |
| 514 | 514 |
| 515 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node) | 515 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node) |
| 516 { | 516 { |
| 517 if (!node) | 517 if (!node) |
| 518 return; | 518 return; |
| 519 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*m_frame.document(),
firstPositionInNode(node), lastPositionInNode(node)); | 519 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*m_frame->document(),
firstPositionInNode(node), lastPositionInNode(node)); |
| 520 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck); | 520 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck); |
| 521 bool asynchronous = true; | 521 bool asynchronous = true; |
| 522 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe
ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous); | 522 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe
ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous); |
| 523 } | 523 } |
| 524 | 524 |
| 525 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask
textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as
ynchronous) | 525 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask
textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as
ynchronous) |
| 526 { | 526 { |
| 527 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) | 527 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) |
| 528 return; | 528 return; |
| 529 | 529 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 551 currentChunkStart += checkingLength; | 551 currentChunkStart += checkingLength; |
| 552 } | 552 } |
| 553 } | 553 } |
| 554 | 554 |
| 555 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask
textCheckingOptions, Range* checkRange, Range* paragraphRange, bool asynchronou
s, int requestNumber, int* checkingLength) | 555 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask
textCheckingOptions, Range* checkRange, Range* paragraphRange, bool asynchronou
s, int requestNumber, int* checkingLength) |
| 556 { | 556 { |
| 557 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange); | 557 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange); |
| 558 if (checkingLength) | 558 if (checkingLength) |
| 559 *checkingLength = sentenceToCheck.checkingLength(); | 559 *checkingLength = sentenceToCheck.checkingLength(); |
| 560 | 560 |
| 561 RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextChe
ckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkRange, paragr
aphRange, requestNumber); | 561 RefPtrWillBeRawPtr<SpellCheckRequest> request = SpellCheckRequest::create(re
solveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkR
ange, paragraphRange, requestNumber); |
| 562 | 562 |
| 563 if (asynchronous) { | 563 if (asynchronous) { |
| 564 m_spellCheckRequester->requestCheckingFor(request); | 564 m_spellCheckRequester->requestCheckingFor(request); |
| 565 } else { | 565 } else { |
| 566 Vector<TextCheckingResult> results; | 566 Vector<TextCheckingResult> results; |
| 567 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC
heckingTypeMask(textCheckingOptions), results); | 567 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC
heckingTypeMask(textCheckingOptions), results); |
| 568 markAndReplaceFor(request, results); | 568 markAndReplaceFor(request, results); |
| 569 } | 569 } |
| 570 } | 570 } |
| 571 | 571 |
| 572 void SpellChecker::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, cons
t Vector<TextCheckingResult>& results) | 572 void SpellChecker::markAndReplaceFor(PassRefPtrWillBeRawPtr<SpellCheckRequest> r
equest, const Vector<TextCheckingResult>& results) |
| 573 { | 573 { |
| 574 ASSERT(request); | 574 ASSERT(request); |
| 575 | 575 |
| 576 TextCheckingTypeMask textCheckingOptions = request->data().mask(); | 576 TextCheckingTypeMask textCheckingOptions = request->data().mask(); |
| 577 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); | 577 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); |
| 578 | 578 |
| 579 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; | 579 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
| 580 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; | 580 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
| 581 | 581 |
| 582 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. | 582 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. |
| 583 int selectionOffset = 0; | 583 int selectionOffset = 0; |
| 584 int ambiguousBoundaryOffset = -1; | 584 int ambiguousBoundaryOffset = -1; |
| 585 bool selectionChanged = false; | 585 bool selectionChanged = false; |
| 586 bool restoreSelectionAfterChange = false; | 586 bool restoreSelectionAfterChange = false; |
| 587 bool adjustSelectionForParagraphBoundaries = false; | 587 bool adjustSelectionForParagraphBoundaries = false; |
| 588 | 588 |
| 589 if (shouldMarkSpelling) { | 589 if (shouldMarkSpelling) { |
| 590 if (m_frame.selection().isCaret()) { | 590 if (m_frame->selection().isCaret()) { |
| 591 // Attempt to save the caret position so we can restore it later if
needed | 591 // Attempt to save the caret position so we can restore it later if
needed |
| 592 Position caretPosition = m_frame.selection().end(); | 592 Position caretPosition = m_frame->selection().end(); |
| 593 selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPT
ION); | 593 selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPT
ION); |
| 594 restoreSelectionAfterChange = true; | 594 restoreSelectionAfterChange = true; |
| 595 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) | 595 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) |
| 596 adjustSelectionForParagraphBoundaries = true; | 596 adjustSelectionForParagraphBoundaries = true; |
| 597 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) | 597 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) |
| 598 ambiguousBoundaryOffset = selectionOffset - 1; | 598 ambiguousBoundaryOffset = selectionOffset - 1; |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 | 601 |
| 602 for (unsigned i = 0; i < results.size(); i++) { | 602 for (unsigned i = 0; i < results.size(); i++) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 631 invisibleSpellcheckRange->startContainer()->document().markers().add
Marker(invisibleSpellcheckRange.get(), DocumentMarker::InvisibleSpellcheck, resu
lt->replacement, result->hash); | 631 invisibleSpellcheckRange->startContainer()->document().markers().add
Marker(invisibleSpellcheckRange.get(), DocumentMarker::InvisibleSpellcheck, resu
lt->replacement, result->hash); |
| 632 } | 632 } |
| 633 } | 633 } |
| 634 | 634 |
| 635 if (selectionChanged) { | 635 if (selectionChanged) { |
| 636 TextCheckingParagraph extendedParagraph(paragraph); | 636 TextCheckingParagraph extendedParagraph(paragraph); |
| 637 // Restore the caret position if we have made any replacements | 637 // Restore the caret position if we have made any replacements |
| 638 extendedParagraph.expandRangeToNextEnd(); | 638 extendedParagraph.expandRangeToNextEnd(); |
| 639 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs
et <= extendedParagraph.rangeLength()) { | 639 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs
et <= extendedParagraph.rangeLength()) { |
| 640 RefPtrWillBeRawPtr<Range> selectionRange = extendedParagraph.subrang
e(0, selectionOffset); | 640 RefPtrWillBeRawPtr<Range> selectionRange = extendedParagraph.subrang
e(0, selectionOffset); |
| 641 m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM
); | 641 m_frame->selection().moveTo(selectionRange->endPosition(), DOWNSTREA
M); |
| 642 if (adjustSelectionForParagraphBoundaries) | 642 if (adjustSelectionForParagraphBoundaries) |
| 643 m_frame.selection().modify(FrameSelection::AlterationMove, Direc
tionForward, CharacterGranularity); | 643 m_frame->selection().modify(FrameSelection::AlterationMove, Dire
ctionForward, CharacterGranularity); |
| 644 } else { | 644 } else { |
| 645 // If this fails for any reason, the fallback is to go one position
beyond the last replacement | 645 // If this fails for any reason, the fallback is to go one position
beyond the last replacement |
| 646 m_frame.selection().moveTo(m_frame.selection().selection().visibleEn
d()); | 646 m_frame->selection().moveTo(m_frame->selection().selection().visible
End()); |
| 647 m_frame.selection().modify(FrameSelection::AlterationMove, Direction
Forward, CharacterGranularity); | 647 m_frame->selection().modify(FrameSelection::AlterationMove, Directio
nForward, CharacterGranularity); |
| 648 } | 648 } |
| 649 } | 649 } |
| 650 } | 650 } |
| 651 | 651 |
| 652 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& spellin
gSelection, bool markGrammar, const VisibleSelection& grammarSelection) | 652 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& spellin
gSelection, bool markGrammar, const VisibleSelection& grammarSelection) |
| 653 { | 653 { |
| 654 if (unifiedTextCheckerEnabled()) { | 654 if (unifiedTextCheckerEnabled()) { |
| 655 if (!isContinuousSpellCheckingEnabled()) | 655 if (!isContinuousSpellCheckingEnabled()) |
| 656 return; | 656 return; |
| 657 | 657 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 677 // We want to remove the markers from a word if an editing command will chan
ge the word. This can happen in one of | 677 // We want to remove the markers from a word if an editing command will chan
ge the word. This can happen in one of |
| 678 // several scenarios: | 678 // several scenarios: |
| 679 // 1. Insert in the middle of a word. | 679 // 1. Insert in the middle of a word. |
| 680 // 2. Appending non whitespace at the beginning of word. | 680 // 2. Appending non whitespace at the beginning of word. |
| 681 // 3. Appending non whitespace at the end of word. | 681 // 3. Appending non whitespace at the end of word. |
| 682 // Note that, appending only whitespaces at the beginning or end of word won
't change the word, so we don't need to | 682 // Note that, appending only whitespaces at the beginning or end of word won
't change the word, so we don't need to |
| 683 // remove the markers on that word. | 683 // remove the markers on that word. |
| 684 // Of course, if current selection is a range, we potentially will edit two
words that fall on the boundaries of | 684 // Of course, if current selection is a range, we potentially will edit two
words that fall on the boundaries of |
| 685 // selection, and remove words between the selection boundaries. | 685 // selection, and remove words between the selection boundaries. |
| 686 // | 686 // |
| 687 VisiblePosition startOfSelection = m_frame.selection().selection().visibleSt
art(); | 687 VisiblePosition startOfSelection = m_frame->selection().selection().visibleS
tart(); |
| 688 VisiblePosition endOfSelection = m_frame.selection().selection().visibleEnd(
); | 688 VisiblePosition endOfSelection = m_frame->selection().selection().visibleEnd
(); |
| 689 if (startOfSelection.isNull()) | 689 if (startOfSelection.isNull()) |
| 690 return; | 690 return; |
| 691 // First word is the word that ends after or on the start of selection. | 691 // First word is the word that ends after or on the start of selection. |
| 692 VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfO
nBoundary); | 692 VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfO
nBoundary); |
| 693 VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBou
ndary); | 693 VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBou
ndary); |
| 694 // Last word is the word that begins before or on the end of selection | 694 // Last word is the word that begins before or on the end of selection |
| 695 VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnB
oundary); | 695 VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnB
oundary); |
| 696 VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBound
ary); | 696 VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBound
ary); |
| 697 | 697 |
| 698 if (startOfFirstWord.isNull()) { | 698 if (startOfFirstWord.isNull()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 725 | 725 |
| 726 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.
isNull() || endOfLastWord.isNull()) | 726 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.
isNull() || endOfLastWord.isNull()) |
| 727 return; | 727 return; |
| 728 | 728 |
| 729 // Now we remove markers on everything between startOfFirstWord and endOfLas
tWord. | 729 // Now we remove markers on everything between startOfFirstWord and endOfLas
tWord. |
| 730 // However, if an autocorrection change a single word to multiple words, we
want to remove correction mark from all the | 730 // However, if an autocorrection change a single word to multiple words, we
want to remove correction mark from all the |
| 731 // resulted words even we only edit one of them. For example, assuming autoc
orrection changes "avantgarde" to "avant | 731 // resulted words even we only edit one of them. For example, assuming autoc
orrection changes "avantgarde" to "avant |
| 732 // garde", we will have CorrectionIndicator marker on both words and on the
whitespace between them. If we then edit garde, | 732 // garde", we will have CorrectionIndicator marker on both words and on the
whitespace between them. If we then edit garde, |
| 733 // we would like to remove the marker from word "avant" and whitespace as we
ll. So we need to get the continous range of | 733 // we would like to remove the marker from word "avant" and whitespace as we
ll. So we need to get the continous range of |
| 734 // of marker that contains the word in question, and remove marker on that w
hole range. | 734 // of marker that contains the word in question, and remove marker on that w
hole range. |
| 735 Document* document = m_frame.document(); | 735 Document* document = m_frame->document(); |
| 736 ASSERT(document); | 736 ASSERT(document); |
| 737 RefPtrWillBeRawPtr<Range> wordRange = Range::create(*document, startOfFirstW
ord.deepEquivalent(), endOfLastWord.deepEquivalent()); | 737 RefPtrWillBeRawPtr<Range> wordRange = Range::create(*document, startOfFirstW
ord.deepEquivalent(), endOfLastWord.deepEquivalent()); |
| 738 document->markers().removeMarkers(wordRange.get(), DocumentMarker::Misspelli
ngMarkers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); | 738 document->markers().removeMarkers(wordRange.get(), DocumentMarker::Misspelli
ngMarkers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); |
| 739 } | 739 } |
| 740 | 740 |
| 741 void SpellChecker::didEndEditingOnTextField(Element* e) | 741 void SpellChecker::didEndEditingOnTextField(Element* e) |
| 742 { | 742 { |
| 743 // Remove markers when deactivating a selection in an <input type="text"/>. | 743 // Remove markers when deactivating a selection in an <input type="text"/>. |
| 744 // Prevent new ones from appearing too. | 744 // Prevent new ones from appearing too. |
| 745 m_spellCheckRequester->cancelCheck(); | 745 m_spellCheckRequester->cancelCheck(); |
| 746 HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlEl
ement(e); | 746 HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlEl
ement(e); |
| 747 HTMLElement* innerEditor = textFormControlElement->innerEditorElement(); | 747 HTMLElement* innerEditor = textFormControlElement->innerEditorElement(); |
| 748 DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling); | 748 DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling); |
| 749 if (isGrammarCheckingEnabled() || unifiedTextCheckerEnabled()) | 749 if (isGrammarCheckingEnabled() || unifiedTextCheckerEnabled()) |
| 750 markerTypes.add(DocumentMarker::Grammar); | 750 markerTypes.add(DocumentMarker::Grammar); |
| 751 for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, inner
Editor)) { | 751 for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, inner
Editor)) { |
| 752 m_frame.document()->markers().removeMarkers(node, markerTypes); | 752 m_frame->document()->markers().removeMarkers(node, markerTypes); |
| 753 } | 753 } |
| 754 } | 754 } |
| 755 | 755 |
| 756 void SpellChecker::replaceMisspelledRange(const String& text) | 756 void SpellChecker::replaceMisspelledRange(const String& text) |
| 757 { | 757 { |
| 758 RefPtrWillBeRawPtr<Range> caretRange = m_frame.selection().toNormalizedRange
(); | 758 RefPtrWillBeRawPtr<Range> caretRange = m_frame->selection().toNormalizedRang
e(); |
| 759 if (!caretRange) | 759 if (!caretRange) |
| 760 return; | 760 return; |
| 761 DocumentMarkerVector markers = m_frame.document()->markers().markersInRange(
caretRange.get(), DocumentMarker::MisspellingMarkers()); | 761 DocumentMarkerVector markers = m_frame->document()->markers().markersInRange
(caretRange.get(), DocumentMarker::MisspellingMarkers()); |
| 762 if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset
()) | 762 if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset
()) |
| 763 return; | 763 return; |
| 764 RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocum
ent(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endC
ontainer(), markers[0]->endOffset()); | 764 RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocum
ent(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endC
ontainer(), markers[0]->endOffset()); |
| 765 if (!markerRange) | 765 if (!markerRange) |
| 766 return; | 766 return; |
| 767 m_frame.selection().setSelection(VisibleSelection(markerRange.get()), Charac
terGranularity); | 767 m_frame->selection().setSelection(VisibleSelection(markerRange.get()), Chara
cterGranularity); |
| 768 m_frame.editor().replaceSelectionWithText(text, false, false); | 768 m_frame->editor().replaceSelectionWithText(text, false, false); |
| 769 } | 769 } |
| 770 | 770 |
| 771 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) | 771 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) |
| 772 { | 772 { |
| 773 bool closeTyping = options & FrameSelection::CloseTyping; | 773 bool closeTyping = options & FrameSelection::CloseTyping; |
| 774 bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabl
ed(); | 774 bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabl
ed(); |
| 775 bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled &
& isGrammarCheckingEnabled(); | 775 bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled &
& isGrammarCheckingEnabled(); |
| 776 if (isContinuousSpellCheckingEnabled) { | 776 if (isContinuousSpellCheckingEnabled) { |
| 777 VisibleSelection newAdjacentWords; | 777 VisibleSelection newAdjacentWords; |
| 778 VisibleSelection newSelectedSentence; | 778 VisibleSelection newSelectedSentence; |
| 779 bool caretBrowsing = m_frame.settings() && m_frame.settings()->caretBrow
singEnabled(); | 779 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr
owsingEnabled(); |
| 780 const VisibleSelection newSelection = m_frame.selection().selection(); | 780 const VisibleSelection newSelection = m_frame->selection().selection(); |
| 781 if (isSelectionInTextFormControl(newSelection)) { | 781 if (isSelectionInTextFormControl(newSelection)) { |
| 782 Position newStart = newSelection.start(); | 782 Position newStart = newSelection.start(); |
| 783 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::st
artOfWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); | 783 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::st
artOfWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); |
| 784 if (isContinuousGrammarCheckingEnabled) | 784 if (isContinuousGrammarCheckingEnabled) |
| 785 newSelectedSentence.setWithoutValidation(HTMLTextFormControlElem
ent::startOfSentence(newStart), HTMLTextFormControlElement::endOfSentence(newSta
rt)); | 785 newSelectedSentence.setWithoutValidation(HTMLTextFormControlElem
ent::startOfSentence(newStart), HTMLTextFormControlElement::endOfSentence(newSta
rt)); |
| 786 } else if (newSelection.isContentEditable() || caretBrowsing) { | 786 } else if (newSelection.isContentEditable() || caretBrowsing) { |
| 787 VisiblePosition newStart(newSelection.visibleStart()); | 787 VisiblePosition newStart(newSelection.visibleStart()); |
| 788 newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIf
OnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); | 788 newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIf
OnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); |
| 789 if (isContinuousGrammarCheckingEnabled) | 789 if (isContinuousGrammarCheckingEnabled) |
| 790 newSelectedSentence = VisibleSelection(startOfSentence(newStart)
, endOfSentence(newStart)); | 790 newSelectedSentence = VisibleSelection(startOfSentence(newStart)
, endOfSentence(newStart)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 805 && oldSelection.start().inDocument()) { | 805 && oldSelection.start().inDocument()) { |
| 806 spellCheckOldSelection(oldSelection, newAdjacentWords); | 806 spellCheckOldSelection(oldSelection, newAdjacentWords); |
| 807 } | 807 } |
| 808 | 808 |
| 809 // FIXME(http://crbug.com/382809): | 809 // FIXME(http://crbug.com/382809): |
| 810 // shouldEraseMarkersAfterChangeSelection is true, we cause synchronous | 810 // shouldEraseMarkersAfterChangeSelection is true, we cause synchronous |
| 811 // layout. | 811 // layout. |
| 812 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eSpelling)) { | 812 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eSpelling)) { |
| 813 Position start, end; | 813 Position start, end; |
| 814 if (newAdjacentWords.toNormalizedPositions(start, end)) | 814 if (newAdjacentWords.toNormalizedPositions(start, end)) |
| 815 m_frame.document()->markers().removeMarkers(start, end, Document
Marker::Spelling); | 815 m_frame->document()->markers().removeMarkers(start, end, Documen
tMarker::Spelling); |
| 816 } | 816 } |
| 817 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eGrammar)) { | 817 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eGrammar)) { |
| 818 Position start, end; | 818 Position start, end; |
| 819 if (newSelectedSentence.toNormalizedPositions(start, end)) | 819 if (newSelectedSentence.toNormalizedPositions(start, end)) |
| 820 m_frame.document()->markers().removeMarkers(start, end, Document
Marker::Grammar); | 820 m_frame->document()->markers().removeMarkers(start, end, Documen
tMarker::Grammar); |
| 821 } | 821 } |
| 822 } | 822 } |
| 823 | 823 |
| 824 // When continuous spell checking is off, existing markers disappear after t
he selection changes. | 824 // When continuous spell checking is off, existing markers disappear after t
he selection changes. |
| 825 if (!isContinuousSpellCheckingEnabled) | 825 if (!isContinuousSpellCheckingEnabled) |
| 826 m_frame.document()->markers().removeMarkers(DocumentMarker::Spelling); | 826 m_frame->document()->markers().removeMarkers(DocumentMarker::Spelling); |
| 827 if (!isContinuousGrammarCheckingEnabled) | 827 if (!isContinuousGrammarCheckingEnabled) |
| 828 m_frame.document()->markers().removeMarkers(DocumentMarker::Grammar); | 828 m_frame->document()->markers().removeMarkers(DocumentMarker::Grammar); |
| 829 } | 829 } |
| 830 | 830 |
| 831 void SpellChecker::removeSpellingMarkers() | 831 void SpellChecker::removeSpellingMarkers() |
| 832 { | 832 { |
| 833 m_frame.document()->markers().removeMarkers(DocumentMarker::MisspellingMarke
rs()); | 833 m_frame->document()->markers().removeMarkers(DocumentMarker::MisspellingMark
ers()); |
| 834 } | 834 } |
| 835 | 835 |
| 836 void SpellChecker::removeSpellingMarkersUnderWords(const Vector<String>& words) | 836 void SpellChecker::removeSpellingMarkersUnderWords(const Vector<String>& words) |
| 837 { | 837 { |
| 838 MarkerRemoverPredicate removerPredicate(words); | 838 MarkerRemoverPredicate removerPredicate(words); |
| 839 | 839 |
| 840 DocumentMarkerController& markerController = m_frame.document()->markers(); | 840 DocumentMarkerController& markerController = m_frame->document()->markers(); |
| 841 markerController.removeMarkers(removerPredicate); | 841 markerController.removeMarkers(removerPredicate); |
| 842 markerController.repaintMarkers(); | 842 markerController.repaintMarkers(); |
| 843 } | 843 } |
| 844 | 844 |
| 845 void SpellChecker::spellCheckAfterBlur() | 845 void SpellChecker::spellCheckAfterBlur() |
| 846 { | 846 { |
| 847 if (!m_frame.selection().selection().isContentEditable()) | 847 if (!m_frame->selection().selection().isContentEditable()) |
| 848 return; | 848 return; |
| 849 | 849 |
| 850 if (isSelectionInTextField(m_frame.selection().selection())) { | 850 if (isSelectionInTextField(m_frame->selection().selection())) { |
| 851 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. | 851 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. |
| 852 return; | 852 return; |
| 853 } | 853 } |
| 854 | 854 |
| 855 VisibleSelection empty; | 855 VisibleSelection empty; |
| 856 spellCheckOldSelection(m_frame.selection().selection(), empty); | 856 spellCheckOldSelection(m_frame->selection().selection(), empty); |
| 857 } | 857 } |
| 858 | 858 |
| 859 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) | 859 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) |
| 860 { | 860 { |
| 861 VisiblePosition oldStart(oldSelection.visibleStart()); | 861 VisiblePosition oldStart(oldSelection.visibleStart()); |
| 862 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L
eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); | 862 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L
eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); |
| 863 if (oldAdjacentWords != newAdjacentWords) { | 863 if (oldAdjacentWords != newAdjacentWords) { |
| 864 if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) { | 864 if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) { |
| 865 VisibleSelection selectedSentence = VisibleSelection(startOfSentence
(oldStart), endOfSentence(oldStart)); | 865 VisibleSelection selectedSentence = VisibleSelection(startOfSentence
(oldStart), endOfSentence(oldStart)); |
| 866 markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSenten
ce); | 866 markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSenten
ce); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 883 node = node->firstChild(); | 883 node = node->firstChild(); |
| 884 else | 884 else |
| 885 node = node->nextSibling(); | 885 node = node->nextSibling(); |
| 886 } | 886 } |
| 887 | 887 |
| 888 return 0; | 888 return 0; |
| 889 } | 889 } |
| 890 | 890 |
| 891 bool SpellChecker::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerT
ype, int from, int length) const | 891 bool SpellChecker::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerT
ype, int from, int length) const |
| 892 { | 892 { |
| 893 Node* node = findFirstMarkable(m_frame.selection().start().deprecatedNode())
; | 893 Node* node = findFirstMarkable(m_frame->selection().start().deprecatedNode()
); |
| 894 if (!node) | 894 if (!node) |
| 895 return false; | 895 return false; |
| 896 | 896 |
| 897 unsigned startOffset = static_cast<unsigned>(from); | 897 unsigned startOffset = static_cast<unsigned>(from); |
| 898 unsigned endOffset = static_cast<unsigned>(from + length); | 898 unsigned endOffset = static_cast<unsigned>(from + length); |
| 899 DocumentMarkerVector markers = m_frame.document()->markers().markersFor(node
); | 899 DocumentMarkerVector markers = m_frame->document()->markers().markersFor(nod
e); |
| 900 for (size_t i = 0; i < markers.size(); ++i) { | 900 for (size_t i = 0; i < markers.size(); ++i) { |
| 901 DocumentMarker* marker = markers[i]; | 901 DocumentMarker* marker = markers[i]; |
| 902 if (marker->startOffset() <= startOffset && endOffset <= marker->endOffs
et() && marker->type() == markerType) | 902 if (marker->startOffset() <= startOffset && endOffset <= marker->endOffs
et() && marker->type() == markerType) |
| 903 return true; | 903 return true; |
| 904 } | 904 } |
| 905 | 905 |
| 906 return false; | 906 return false; |
| 907 } | 907 } |
| 908 | 908 |
| 909 bool SpellChecker::selectionStartHasSpellingMarkerFor(int from, int length) cons
t | 909 bool SpellChecker::selectionStartHasSpellingMarkerFor(int from, int length) cons
t |
| (...skipping 10 matching lines...) Expand all Loading... |
| 920 if (shouldMarkSpelling) | 920 if (shouldMarkSpelling) |
| 921 checkingTypes |= TextCheckingTypeSpelling; | 921 checkingTypes |= TextCheckingTypeSpelling; |
| 922 if (shouldMarkGrammar) | 922 if (shouldMarkGrammar) |
| 923 checkingTypes |= TextCheckingTypeGrammar; | 923 checkingTypes |= TextCheckingTypeGrammar; |
| 924 | 924 |
| 925 return checkingTypes; | 925 return checkingTypes; |
| 926 } | 926 } |
| 927 | 927 |
| 928 bool SpellChecker::unifiedTextCheckerEnabled() const | 928 bool SpellChecker::unifiedTextCheckerEnabled() const |
| 929 { | 929 { |
| 930 return blink::unifiedTextCheckerEnabled(&m_frame); | 930 return blink::unifiedTextCheckerEnabled(m_frame); |
| 931 } | 931 } |
| 932 | 932 |
| 933 void SpellChecker::cancelCheck() | 933 void SpellChecker::cancelCheck() |
| 934 { | 934 { |
| 935 m_spellCheckRequester->cancelCheck(); | 935 m_spellCheckRequester->cancelCheck(); |
| 936 } | 936 } |
| 937 | 937 |
| 938 void SpellChecker::requestTextChecking(const Element& element) | 938 void SpellChecker::requestTextChecking(const Element& element) |
| 939 { | 939 { |
| 940 RefPtrWillBeRawPtr<Range> rangeToCheck = rangeOfContents(const_cast<Element*
>(&element)); | 940 RefPtrWillBeRawPtr<Range> rangeToCheck = rangeOfContents(const_cast<Element*
>(&element)); |
| 941 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe
ck, rangeToCheck)); | 941 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe
ck, rangeToCheck)); |
| 942 } | 942 } |
| 943 | 943 |
| 944 void SpellChecker::trace(Visitor* visitor) |
| 945 { |
| 946 visitor->trace(m_frame); |
| 947 visitor->trace(m_spellCheckRequester); |
| 948 } |
| 944 | 949 |
| 945 } // namespace blink | 950 } // namespace blink |
| OLD | NEW |