| 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 RefPtrWillBeRawPtr<Range> spellingSearchRange(rangeOfContents(m_frame.docume
nt())); | 171 RefPtrWillBeRawPtr<Range> spellingSearchRange(rangeOfContents(m_frame->docum
ent())); |
| 172 | 172 |
| 173 bool startedWithSelection = false; | 173 bool startedWithSelection = false; |
| 174 if (selection.start().deprecatedNode()) { | 174 if (selection.start().deprecatedNode()) { |
| 175 startedWithSelection = true; | 175 startedWithSelection = true; |
| 176 if (startBeforeSelection) { | 176 if (startBeforeSelection) { |
| 177 VisiblePosition start(selection.visibleStart()); | 177 VisiblePosition start(selection.visibleStart()); |
| 178 // We match AppKit's rule: Start 1 character before the selection. | 178 // We match AppKit's rule: Start 1 character before the selection. |
| 179 VisiblePosition oneBeforeStart = start.previous(); | 179 VisiblePosition oneBeforeStart = start.previous(); |
| 180 setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? one
BeforeStart : start); | 180 setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? one
BeforeStart : start); |
| 181 } else { | 181 } else { |
| 182 setStart(spellingSearchRange.get(), selection.visibleEnd()); | 182 setStart(spellingSearchRange.get(), selection.visibleEnd()); |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 | 185 |
| 186 Position position = spellingSearchRange->startPosition(); | 186 Position position = spellingSearchRange->startPosition(); |
| 187 if (!isEditablePosition(position)) { | 187 if (!isEditablePosition(position)) { |
| 188 // This shouldn't happen in very often because the Spelling menu items a
ren't enabled unless the | 188 // This shouldn't happen in very often because the Spelling menu items a
ren't enabled unless the |
| 189 // selection is editable. | 189 // selection is editable. |
| 190 // This can happen in Mail for a mix of non-editable and editable conten
t (like Stationary), | 190 // This can happen in Mail for a mix of non-editable and editable conten
t (like Stationary), |
| 191 // when spell checking the whole document before sending the message. | 191 // when spell checking the whole document before sending the message. |
| 192 // In that case the document might not be editable, but there are editab
le pockets that need to be spell checked. | 192 // In that case the document might not be editable, but there are editab
le pockets that need to be spell checked. |
| 193 | 193 |
| 194 position = firstEditableVisiblePositionAfterPositionInRoot(position, m_f
rame.document()->documentElement()).deepEquivalent(); | 194 position = firstEditableVisiblePositionAfterPositionInRoot(position, m_f
rame->document()->documentElement()).deepEquivalent(); |
| 195 if (position.isNull()) | 195 if (position.isNull()) |
| 196 return; | 196 return; |
| 197 | 197 |
| 198 Position rangeCompliantPosition = position.parentAnchoredEquivalent(); | 198 Position rangeCompliantPosition = position.parentAnchoredEquivalent(); |
| 199 spellingSearchRange->setStart(rangeCompliantPosition.deprecatedNode(), r
angeCompliantPosition.deprecatedEditingOffset(), IGNORE_EXCEPTION); | 199 spellingSearchRange->setStart(rangeCompliantPosition.deprecatedNode(), r
angeCompliantPosition.deprecatedEditingOffset(), IGNORE_EXCEPTION); |
| 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); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 if (!badGrammarPhrase.isEmpty()) { | 293 if (!badGrammarPhrase.isEmpty()) { |
| 294 // We found bad grammar. Since we only searched for bad grammar up to th
e first misspelled word, the bad grammar | 294 // We found bad grammar. Since we only searched for bad grammar up to th
e first misspelled word, the bad grammar |
| 295 // takes precedence and we ignore any potential misspelled word. Select
the grammar detail, update the spelling | 295 // takes precedence and we ignore any potential misspelled word. Select
the grammar detail, update the spelling |
| 296 // panel, and store a marker so we draw the green squiggle later. | 296 // panel, and store a marker so we draw the green squiggle later. |
| 297 | 297 |
| 298 ASSERT(badGrammarPhrase.length() > 0); | 298 ASSERT(badGrammarPhrase.length() > 0); |
| 299 ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0); | 299 ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0); |
| 300 | 300 |
| 301 // FIXME 4859190: This gets confused with doubled punctuation at the end
of a paragraph | 301 // FIXME 4859190: This gets confused with doubled punctuation at the end
of a paragraph |
| 302 RefPtrWillBeRawPtr<Range> badGrammarRange = TextIterator::subrange(gramm
arSearchRange.get(), grammarPhraseOffset + grammarDetail.location, grammarDetail
.length); | 302 RefPtrWillBeRawPtr<Range> badGrammarRange = TextIterator::subrange(gramm
arSearchRange.get(), grammarPhraseOffset + grammarDetail.location, grammarDetail
.length); |
| 303 m_frame.selection().setSelection(VisibleSelection(badGrammarRange.get(),
SEL_DEFAULT_AFFINITY)); | 303 m_frame->selection().setSelection(VisibleSelection(badGrammarRange.get()
, SEL_DEFAULT_AFFINITY)); |
| 304 m_frame.selection().revealSelection(); | 304 m_frame->selection().revealSelection(); |
| 305 | 305 |
| 306 m_frame.document()->markers().addMarker(badGrammarRange.get(), DocumentM
arker::Grammar, grammarDetail.userDescription); | 306 m_frame->document()->markers().addMarker(badGrammarRange.get(), Document
Marker::Grammar, grammarDetail.userDescription); |
| 307 } else if (!misspelledWord.isEmpty()) { | 307 } else if (!misspelledWord.isEmpty()) { |
| 308 // We found a misspelling, but not any earlier bad grammar. Select the m
isspelling, update the spelling panel, and store | 308 // We found a misspelling, but not any earlier bad grammar. Select the m
isspelling, update the spelling panel, and store |
| 309 // a marker so we draw the red squiggle later. | 309 // a marker so we draw the red squiggle later. |
| 310 | 310 |
| 311 RefPtrWillBeRawPtr<Range> misspellingRange = TextIterator::subrange(spel
lingSearchRange.get(), misspellingOffset, misspelledWord.length()); | 311 RefPtrWillBeRawPtr<Range> misspellingRange = TextIterator::subrange(spel
lingSearchRange.get(), misspellingOffset, misspelledWord.length()); |
| 312 m_frame.selection().setSelection(VisibleSelection(misspellingRange.get()
, DOWNSTREAM)); | 312 m_frame->selection().setSelection(VisibleSelection(misspellingRange.get(
), DOWNSTREAM)); |
| 313 m_frame.selection().revealSelection(); | 313 m_frame->selection().revealSelection(); |
| 314 | 314 |
| 315 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); | 315 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); |
| 316 m_frame.document()->markers().addMarker(misspellingRange.get(), Document
Marker::Spelling); | 316 m_frame->document()->markers().addMarker(misspellingRange.get(), Documen
tMarker::Spelling); |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 | 319 |
| 320 void SpellChecker::showSpellingGuessPanel() | 320 void SpellChecker::showSpellingGuessPanel() |
| 321 { | 321 { |
| 322 if (spellCheckerClient().spellingUIIsShowing()) { | 322 if (spellCheckerClient().spellingUIIsShowing()) { |
| 323 spellCheckerClient().showSpellingUI(false); | 323 spellCheckerClient().showSpellingUI(false); |
| 324 return; | 324 return; |
| 325 } | 325 } |
| 326 | 326 |
| 327 advanceToNextMisspelling(true); | 327 advanceToNextMisspelling(true); |
| 328 spellCheckerClient().showSpellingUI(true); | 328 spellCheckerClient().showSpellingUI(true); |
| 329 } | 329 } |
| 330 | 330 |
| 331 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) | 331 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) |
| 332 { | 332 { |
| 333 RefPtrWillBeRawPtr<Range> selectedRange = movingSelection.toNormalizedRange(
); | 333 RefPtrWillBeRawPtr<Range> selectedRange = movingSelection.toNormalizedRange(
); |
| 334 if (selectedRange) | 334 if (selectedRange) |
| 335 m_frame.document()->markers().removeMarkers(selectedRange.get(), Documen
tMarker::MisspellingMarkers()); | 335 m_frame->document()->markers().removeMarkers(selectedRange.get(), Docume
ntMarker::MisspellingMarkers()); |
| 336 } | 336 } |
| 337 | 337 |
| 338 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingS
election) | 338 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingS
election) |
| 339 { | 339 { |
| 340 markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnab
led() && isGrammarCheckingEnabled(), movingSelection); | 340 markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnab
led() && isGrammarCheckingEnabled(), movingSelection); |
| 341 } | 341 } |
| 342 | 342 |
| 343 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe
lection) | 343 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe
lection) |
| 344 { | 344 { |
| 345 if (unifiedTextCheckerEnabled()) { | 345 if (unifiedTextCheckerEnabled()) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 if (!misspellingRange) | 399 if (!misspellingRange) |
| 400 return; | 400 return; |
| 401 | 401 |
| 402 // Get the misspelled word. | 402 // Get the misspelled word. |
| 403 const String misspelledWord = plainText(misspellingRange.get()); | 403 const String misspelledWord = plainText(misspellingRange.get()); |
| 404 String autocorrectedString = textChecker().getAutoCorrectSuggestionForMisspe
lledWord(misspelledWord); | 404 String autocorrectedString = textChecker().getAutoCorrectSuggestionForMisspe
lledWord(misspelledWord); |
| 405 | 405 |
| 406 // If autocorrected word is non empty, replace the misspelled word by this w
ord. | 406 // If autocorrected word is non empty, replace the misspelled word by this w
ord. |
| 407 if (!autocorrectedString.isEmpty()) { | 407 if (!autocorrectedString.isEmpty()) { |
| 408 VisibleSelection newSelection(misspellingRange.get(), DOWNSTREAM); | 408 VisibleSelection newSelection(misspellingRange.get(), DOWNSTREAM); |
| 409 if (newSelection != m_frame.selection().selection()) { | 409 if (newSelection != m_frame->selection().selection()) { |
| 410 m_frame.selection().setSelection(newSelection); | 410 m_frame->selection().setSelection(newSelection); |
| 411 } | 411 } |
| 412 | 412 |
| 413 m_frame.editor().replaceSelectionWithText(autocorrectedString, false, fa
lse); | 413 m_frame->editor().replaceSelectionWithText(autocorrectedString, false, f
alse); |
| 414 | 414 |
| 415 // Reset the charet one character further. | 415 // Reset the charet one character further. |
| 416 m_frame.selection().moveTo(m_frame.selection().selection().visibleEnd())
; | 416 m_frame->selection().moveTo(m_frame->selection().selection().visibleEnd(
)); |
| 417 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForw
ard, CharacterGranularity); | 417 m_frame->selection().modify(FrameSelection::AlterationMove, DirectionFor
ward, CharacterGranularity); |
| 418 } | 418 } |
| 419 | 419 |
| 420 if (!isGrammarCheckingEnabled()) | 420 if (!isGrammarCheckingEnabled()) |
| 421 return; | 421 return; |
| 422 | 422 |
| 423 // Check grammar of entire sentence | 423 // Check grammar of entire sentence |
| 424 markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wo
rdStart))); | 424 markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wo
rdStart))); |
| 425 } | 425 } |
| 426 | 426 |
| 427 void SpellChecker::markMisspellingsOrBadGrammar(const VisibleSelection& selectio
n, bool checkSpelling, RefPtrWillBeRawPtr<Range>& firstMisspellingRange) | 427 void SpellChecker::markMisspellingsOrBadGrammar(const VisibleSelection& selectio
n, bool checkSpelling, RefPtrWillBeRawPtr<Range>& firstMisspellingRange) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 458 if (!node) | 458 if (!node) |
| 459 return false; | 459 return false; |
| 460 const Element* focusedElement = node->isElementNode() ? toElement(node) : no
de->parentElement(); | 460 const Element* focusedElement = node->isElementNode() ? toElement(node) : no
de->parentElement(); |
| 461 if (!focusedElement) | 461 if (!focusedElement) |
| 462 return false; | 462 return false; |
| 463 return focusedElement->isSpellCheckingEnabled(); | 463 return focusedElement->isSpellCheckingEnabled(); |
| 464 } | 464 } |
| 465 | 465 |
| 466 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const | 466 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const |
| 467 { | 467 { |
| 468 return isSpellCheckingEnabledFor(m_frame.selection().start().deprecatedNode(
)); | 468 return isSpellCheckingEnabledFor(m_frame->selection().start().deprecatedNode
()); |
| 469 } | 469 } |
| 470 | 470 |
| 471 void SpellChecker::markMisspellings(const VisibleSelection& selection, RefPtrWil
lBeRawPtr<Range>& firstMisspellingRange) | 471 void SpellChecker::markMisspellings(const VisibleSelection& selection, RefPtrWil
lBeRawPtr<Range>& firstMisspellingRange) |
| 472 { | 472 { |
| 473 markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange); | 473 markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange); |
| 474 } | 474 } |
| 475 | 475 |
| 476 void SpellChecker::markBadGrammar(const VisibleSelection& selection) | 476 void SpellChecker::markBadGrammar(const VisibleSelection& selection) |
| 477 { | 477 { |
| 478 RefPtrWillBeRawPtr<Range> firstMisspellingRange = nullptr; | 478 RefPtrWillBeRawPtr<Range> firstMisspellingRange = nullptr; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 493 Node* editableNode = spellingRange->startContainer(); | 493 Node* editableNode = spellingRange->startContainer(); |
| 494 if (!editableNode || !editableNode->hasEditableStyle()) | 494 if (!editableNode || !editableNode->hasEditableStyle()) |
| 495 return; | 495 return; |
| 496 | 496 |
| 497 if (!isSpellCheckingEnabledFor(editableNode)) | 497 if (!isSpellCheckingEnabledFor(editableNode)) |
| 498 return; | 498 return; |
| 499 | 499 |
| 500 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; | 500 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; |
| 501 TextCheckingParagraph fullParagraphToCheck(rangeToCheck); | 501 TextCheckingParagraph fullParagraphToCheck(rangeToCheck); |
| 502 | 502 |
| 503 bool asynchronous = m_frame.settings() && m_frame.settings()->asynchronousSp
ellCheckingEnabled(); | 503 bool asynchronous = m_frame->settings() && m_frame->settings()->asynchronous
SpellCheckingEnabled(); |
| 504 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT
oCheck, asynchronous); | 504 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT
oCheck, asynchronous); |
| 505 } | 505 } |
| 506 | 506 |
| 507 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node) | 507 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node) |
| 508 { | 508 { |
| 509 if (!node) | 509 if (!node) |
| 510 return; | 510 return; |
| 511 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*m_frame.document(),
firstPositionInNode(node), lastPositionInNode(node)); | 511 RefPtrWillBeRawPtr<Range> rangeToCheck = Range::create(*m_frame->document(),
firstPositionInNode(node), lastPositionInNode(node)); |
| 512 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck); | 512 TextCheckingParagraph textToCheck(rangeToCheck, rangeToCheck); |
| 513 bool asynchronous = true; | 513 bool asynchronous = true; |
| 514 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe
ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous); | 514 chunkAndMarkAllMisspellingsAndBadGrammar(resolveTextCheckingTypeMask(TextChe
ckingTypeSpelling | TextCheckingTypeGrammar), textToCheck, asynchronous); |
| 515 } | 515 } |
| 516 | 516 |
| 517 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask
textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as
ynchronous) | 517 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(TextCheckingTypeMask
textCheckingOptions, const TextCheckingParagraph& fullParagraphToCheck, bool as
ynchronous) |
| 518 { | 518 { |
| 519 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) | 519 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) |
| 520 return; | 520 return; |
| 521 | 521 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 543 currentChunkStart += checkingLength; | 543 currentChunkStart += checkingLength; |
| 544 } | 544 } |
| 545 } | 545 } |
| 546 | 546 |
| 547 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask
textCheckingOptions, Range* checkRange, Range* paragraphRange, bool asynchronou
s, int requestNumber, int* checkingLength) | 547 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask
textCheckingOptions, Range* checkRange, Range* paragraphRange, bool asynchronou
s, int requestNumber, int* checkingLength) |
| 548 { | 548 { |
| 549 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange); | 549 TextCheckingParagraph sentenceToCheck(checkRange, paragraphRange); |
| 550 if (checkingLength) | 550 if (checkingLength) |
| 551 *checkingLength = sentenceToCheck.checkingLength(); | 551 *checkingLength = sentenceToCheck.checkingLength(); |
| 552 | 552 |
| 553 RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextChe
ckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkRange, paragr
aphRange, requestNumber); | 553 RefPtrWillBeRawPtr<SpellCheckRequest> request = SpellCheckRequest::create(re
solveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkR
ange, paragraphRange, requestNumber); |
| 554 | 554 |
| 555 if (asynchronous) { | 555 if (asynchronous) { |
| 556 m_spellCheckRequester->requestCheckingFor(request); | 556 m_spellCheckRequester->requestCheckingFor(request); |
| 557 } else { | 557 } else { |
| 558 Vector<TextCheckingResult> results; | 558 Vector<TextCheckingResult> results; |
| 559 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC
heckingTypeMask(textCheckingOptions), results); | 559 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC
heckingTypeMask(textCheckingOptions), results); |
| 560 markAndReplaceFor(request, results); | 560 markAndReplaceFor(request, results); |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 void SpellChecker::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, cons
t Vector<TextCheckingResult>& results) | 564 void SpellChecker::markAndReplaceFor(PassRefPtrWillBeRawPtr<SpellCheckRequest> r
equest, const Vector<TextCheckingResult>& results) |
| 565 { | 565 { |
| 566 ASSERT(request); | 566 ASSERT(request); |
| 567 | 567 |
| 568 TextCheckingTypeMask textCheckingOptions = request->data().mask(); | 568 TextCheckingTypeMask textCheckingOptions = request->data().mask(); |
| 569 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); | 569 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); |
| 570 | 570 |
| 571 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; | 571 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
| 572 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; | 572 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
| 573 | 573 |
| 574 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. | 574 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. |
| 575 int selectionOffset = 0; | 575 int selectionOffset = 0; |
| 576 int ambiguousBoundaryOffset = -1; | 576 int ambiguousBoundaryOffset = -1; |
| 577 bool selectionChanged = false; | 577 bool selectionChanged = false; |
| 578 bool restoreSelectionAfterChange = false; | 578 bool restoreSelectionAfterChange = false; |
| 579 bool adjustSelectionForParagraphBoundaries = false; | 579 bool adjustSelectionForParagraphBoundaries = false; |
| 580 | 580 |
| 581 if (shouldMarkSpelling) { | 581 if (shouldMarkSpelling) { |
| 582 if (m_frame.selection().isCaret()) { | 582 if (m_frame->selection().isCaret()) { |
| 583 // Attempt to save the caret position so we can restore it later if
needed | 583 // Attempt to save the caret position so we can restore it later if
needed |
| 584 Position caretPosition = m_frame.selection().end(); | 584 Position caretPosition = m_frame->selection().end(); |
| 585 selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPT
ION); | 585 selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPT
ION); |
| 586 restoreSelectionAfterChange = true; | 586 restoreSelectionAfterChange = true; |
| 587 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) | 587 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) |
| 588 adjustSelectionForParagraphBoundaries = true; | 588 adjustSelectionForParagraphBoundaries = true; |
| 589 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) | 589 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) |
| 590 ambiguousBoundaryOffset = selectionOffset - 1; | 590 ambiguousBoundaryOffset = selectionOffset - 1; |
| 591 } | 591 } |
| 592 } | 592 } |
| 593 | 593 |
| 594 for (unsigned i = 0; i < results.size(); i++) { | 594 for (unsigned i = 0; i < results.size(); i++) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 623 invisibleSpellcheckRange->startContainer()->document().markers().add
Marker(invisibleSpellcheckRange.get(), DocumentMarker::InvisibleSpellcheck, resu
lt->replacement, result->hash); | 623 invisibleSpellcheckRange->startContainer()->document().markers().add
Marker(invisibleSpellcheckRange.get(), DocumentMarker::InvisibleSpellcheck, resu
lt->replacement, result->hash); |
| 624 } | 624 } |
| 625 } | 625 } |
| 626 | 626 |
| 627 if (selectionChanged) { | 627 if (selectionChanged) { |
| 628 TextCheckingParagraph extendedParagraph(paragraph); | 628 TextCheckingParagraph extendedParagraph(paragraph); |
| 629 // Restore the caret position if we have made any replacements | 629 // Restore the caret position if we have made any replacements |
| 630 extendedParagraph.expandRangeToNextEnd(); | 630 extendedParagraph.expandRangeToNextEnd(); |
| 631 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs
et <= extendedParagraph.rangeLength()) { | 631 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs
et <= extendedParagraph.rangeLength()) { |
| 632 RefPtrWillBeRawPtr<Range> selectionRange = extendedParagraph.subrang
e(0, selectionOffset); | 632 RefPtrWillBeRawPtr<Range> selectionRange = extendedParagraph.subrang
e(0, selectionOffset); |
| 633 m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM
); | 633 m_frame->selection().moveTo(selectionRange->endPosition(), DOWNSTREA
M); |
| 634 if (adjustSelectionForParagraphBoundaries) | 634 if (adjustSelectionForParagraphBoundaries) |
| 635 m_frame.selection().modify(FrameSelection::AlterationMove, Direc
tionForward, CharacterGranularity); | 635 m_frame->selection().modify(FrameSelection::AlterationMove, Dire
ctionForward, CharacterGranularity); |
| 636 } else { | 636 } else { |
| 637 // If this fails for any reason, the fallback is to go one position
beyond the last replacement | 637 // If this fails for any reason, the fallback is to go one position
beyond the last replacement |
| 638 m_frame.selection().moveTo(m_frame.selection().selection().visibleEn
d()); | 638 m_frame->selection().moveTo(m_frame->selection().selection().visible
End()); |
| 639 m_frame.selection().modify(FrameSelection::AlterationMove, Direction
Forward, CharacterGranularity); | 639 m_frame->selection().modify(FrameSelection::AlterationMove, Directio
nForward, CharacterGranularity); |
| 640 } | 640 } |
| 641 } | 641 } |
| 642 } | 642 } |
| 643 | 643 |
| 644 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& spellin
gSelection, bool markGrammar, const VisibleSelection& grammarSelection) | 644 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& spellin
gSelection, bool markGrammar, const VisibleSelection& grammarSelection) |
| 645 { | 645 { |
| 646 if (unifiedTextCheckerEnabled()) { | 646 if (unifiedTextCheckerEnabled()) { |
| 647 if (!isContinuousSpellCheckingEnabled()) | 647 if (!isContinuousSpellCheckingEnabled()) |
| 648 return; | 648 return; |
| 649 | 649 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 669 // We want to remove the markers from a word if an editing command will chan
ge the word. This can happen in one of | 669 // We want to remove the markers from a word if an editing command will chan
ge the word. This can happen in one of |
| 670 // several scenarios: | 670 // several scenarios: |
| 671 // 1. Insert in the middle of a word. | 671 // 1. Insert in the middle of a word. |
| 672 // 2. Appending non whitespace at the beginning of word. | 672 // 2. Appending non whitespace at the beginning of word. |
| 673 // 3. Appending non whitespace at the end of word. | 673 // 3. Appending non whitespace at the end of word. |
| 674 // Note that, appending only whitespaces at the beginning or end of word won
't change the word, so we don't need to | 674 // Note that, appending only whitespaces at the beginning or end of word won
't change the word, so we don't need to |
| 675 // remove the markers on that word. | 675 // remove the markers on that word. |
| 676 // Of course, if current selection is a range, we potentially will edit two
words that fall on the boundaries of | 676 // Of course, if current selection is a range, we potentially will edit two
words that fall on the boundaries of |
| 677 // selection, and remove words between the selection boundaries. | 677 // selection, and remove words between the selection boundaries. |
| 678 // | 678 // |
| 679 VisiblePosition startOfSelection = m_frame.selection().selection().visibleSt
art(); | 679 VisiblePosition startOfSelection = m_frame->selection().selection().visibleS
tart(); |
| 680 VisiblePosition endOfSelection = m_frame.selection().selection().visibleEnd(
); | 680 VisiblePosition endOfSelection = m_frame->selection().selection().visibleEnd
(); |
| 681 if (startOfSelection.isNull()) | 681 if (startOfSelection.isNull()) |
| 682 return; | 682 return; |
| 683 // First word is the word that ends after or on the start of selection. | 683 // First word is the word that ends after or on the start of selection. |
| 684 VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfO
nBoundary); | 684 VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfO
nBoundary); |
| 685 VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBou
ndary); | 685 VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBou
ndary); |
| 686 // Last word is the word that begins before or on the end of selection | 686 // Last word is the word that begins before or on the end of selection |
| 687 VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnB
oundary); | 687 VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnB
oundary); |
| 688 VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBound
ary); | 688 VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBound
ary); |
| 689 | 689 |
| 690 if (startOfFirstWord.isNull()) { | 690 if (startOfFirstWord.isNull()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 717 | 717 |
| 718 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.
isNull() || endOfLastWord.isNull()) | 718 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.
isNull() || endOfLastWord.isNull()) |
| 719 return; | 719 return; |
| 720 | 720 |
| 721 // Now we remove markers on everything between startOfFirstWord and endOfLas
tWord. | 721 // Now we remove markers on everything between startOfFirstWord and endOfLas
tWord. |
| 722 // However, if an autocorrection change a single word to multiple words, we
want to remove correction mark from all the | 722 // However, if an autocorrection change a single word to multiple words, we
want to remove correction mark from all the |
| 723 // resulted words even we only edit one of them. For example, assuming autoc
orrection changes "avantgarde" to "avant | 723 // resulted words even we only edit one of them. For example, assuming autoc
orrection changes "avantgarde" to "avant |
| 724 // garde", we will have CorrectionIndicator marker on both words and on the
whitespace between them. If we then edit garde, | 724 // garde", we will have CorrectionIndicator marker on both words and on the
whitespace between them. If we then edit garde, |
| 725 // we would like to remove the marker from word "avant" and whitespace as we
ll. So we need to get the continous range of | 725 // we would like to remove the marker from word "avant" and whitespace as we
ll. So we need to get the continous range of |
| 726 // of marker that contains the word in question, and remove marker on that w
hole range. | 726 // of marker that contains the word in question, and remove marker on that w
hole range. |
| 727 Document* document = m_frame.document(); | 727 Document* document = m_frame->document(); |
| 728 ASSERT(document); | 728 ASSERT(document); |
| 729 RefPtrWillBeRawPtr<Range> wordRange = Range::create(*document, startOfFirstW
ord.deepEquivalent(), endOfLastWord.deepEquivalent()); | 729 RefPtrWillBeRawPtr<Range> wordRange = Range::create(*document, startOfFirstW
ord.deepEquivalent(), endOfLastWord.deepEquivalent()); |
| 730 | 730 |
| 731 document->markers().removeMarkers(wordRange.get(), DocumentMarker::Misspelli
ngMarkers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); | 731 document->markers().removeMarkers(wordRange.get(), DocumentMarker::Misspelli
ngMarkers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); |
| 732 } | 732 } |
| 733 | 733 |
| 734 void SpellChecker::didEndEditingOnTextField(Element* e) | 734 void SpellChecker::didEndEditingOnTextField(Element* e) |
| 735 { | 735 { |
| 736 // Remove markers when deactivating a selection in an <input type="text"/>. | 736 // Remove markers when deactivating a selection in an <input type="text"/>. |
| 737 // Prevent new ones from appearing too. | 737 // Prevent new ones from appearing too. |
| 738 m_spellCheckRequester->cancelCheck(); | 738 m_spellCheckRequester->cancelCheck(); |
| 739 HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlEl
ement(e); | 739 HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlEl
ement(e); |
| 740 HTMLElement* innerEditor = textFormControlElement->innerEditorElement(); | 740 HTMLElement* innerEditor = textFormControlElement->innerEditorElement(); |
| 741 DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling); | 741 DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling); |
| 742 if (isGrammarCheckingEnabled() || unifiedTextCheckerEnabled()) | 742 if (isGrammarCheckingEnabled() || unifiedTextCheckerEnabled()) |
| 743 markerTypes.add(DocumentMarker::Grammar); | 743 markerTypes.add(DocumentMarker::Grammar); |
| 744 for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, inner
Editor)) { | 744 for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, inner
Editor)) { |
| 745 m_frame.document()->markers().removeMarkers(node, markerTypes); | 745 m_frame->document()->markers().removeMarkers(node, markerTypes); |
| 746 } | 746 } |
| 747 } | 747 } |
| 748 | 748 |
| 749 void SpellChecker::replaceMisspelledRange(const String& text) | 749 void SpellChecker::replaceMisspelledRange(const String& text) |
| 750 { | 750 { |
| 751 RefPtrWillBeRawPtr<Range> caretRange = m_frame.selection().toNormalizedRange
(); | 751 RefPtrWillBeRawPtr<Range> caretRange = m_frame->selection().toNormalizedRang
e(); |
| 752 if (!caretRange) | 752 if (!caretRange) |
| 753 return; | 753 return; |
| 754 DocumentMarkerVector markers = m_frame.document()->markers().markersInRange(
caretRange.get(), DocumentMarker::MisspellingMarkers()); | 754 DocumentMarkerVector markers = m_frame->document()->markers().markersInRange
(caretRange.get(), DocumentMarker::MisspellingMarkers()); |
| 755 if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset
()) | 755 if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset
()) |
| 756 return; | 756 return; |
| 757 RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocum
ent(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endC
ontainer(), markers[0]->endOffset()); | 757 RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocum
ent(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endC
ontainer(), markers[0]->endOffset()); |
| 758 if (!markerRange) | 758 if (!markerRange) |
| 759 return; | 759 return; |
| 760 m_frame.selection().setSelection(VisibleSelection(markerRange.get()), Charac
terGranularity); | 760 m_frame->selection().setSelection(VisibleSelection(markerRange.get()), Chara
cterGranularity); |
| 761 m_frame.editor().replaceSelectionWithText(text, false, false); | 761 m_frame->editor().replaceSelectionWithText(text, false, false); |
| 762 } | 762 } |
| 763 | 763 |
| 764 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) | 764 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) |
| 765 { | 765 { |
| 766 bool closeTyping = options & FrameSelection::CloseTyping; | 766 bool closeTyping = options & FrameSelection::CloseTyping; |
| 767 bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabl
ed(); | 767 bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabl
ed(); |
| 768 bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled &
& isGrammarCheckingEnabled(); | 768 bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled &
& isGrammarCheckingEnabled(); |
| 769 if (isContinuousSpellCheckingEnabled) { | 769 if (isContinuousSpellCheckingEnabled) { |
| 770 VisibleSelection newAdjacentWords; | 770 VisibleSelection newAdjacentWords; |
| 771 VisibleSelection newSelectedSentence; | 771 VisibleSelection newSelectedSentence; |
| 772 bool caretBrowsing = m_frame.settings() && m_frame.settings()->caretBrow
singEnabled(); | 772 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr
owsingEnabled(); |
| 773 const VisibleSelection newSelection = m_frame.selection().selection(); | 773 const VisibleSelection newSelection = m_frame->selection().selection(); |
| 774 if (isSelectionInTextFormControl(newSelection)) { | 774 if (isSelectionInTextFormControl(newSelection)) { |
| 775 Position newStart = newSelection.start(); | 775 Position newStart = newSelection.start(); |
| 776 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::st
artOfWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); | 776 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::st
artOfWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); |
| 777 if (isContinuousGrammarCheckingEnabled) | 777 if (isContinuousGrammarCheckingEnabled) |
| 778 newSelectedSentence.setWithoutValidation(HTMLTextFormControlElem
ent::startOfSentence(newStart), HTMLTextFormControlElement::endOfSentence(newSta
rt)); | 778 newSelectedSentence.setWithoutValidation(HTMLTextFormControlElem
ent::startOfSentence(newStart), HTMLTextFormControlElement::endOfSentence(newSta
rt)); |
| 779 } else if (newSelection.isContentEditable() || caretBrowsing) { | 779 } else if (newSelection.isContentEditable() || caretBrowsing) { |
| 780 VisiblePosition newStart(newSelection.visibleStart()); | 780 VisiblePosition newStart(newSelection.visibleStart()); |
| 781 newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIf
OnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); | 781 newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIf
OnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); |
| 782 if (isContinuousGrammarCheckingEnabled) | 782 if (isContinuousGrammarCheckingEnabled) |
| 783 newSelectedSentence = VisibleSelection(startOfSentence(newStart)
, endOfSentence(newStart)); | 783 newSelectedSentence = VisibleSelection(startOfSentence(newStart)
, endOfSentence(newStart)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 798 && oldSelection.start().inDocument()) { | 798 && oldSelection.start().inDocument()) { |
| 799 spellCheckOldSelection(oldSelection, newAdjacentWords); | 799 spellCheckOldSelection(oldSelection, newAdjacentWords); |
| 800 } | 800 } |
| 801 | 801 |
| 802 // FIXME(http://crbug.com/382809): | 802 // FIXME(http://crbug.com/382809): |
| 803 // shouldEraseMarkersAfterChangeSelection is true, we cause synchronous | 803 // shouldEraseMarkersAfterChangeSelection is true, we cause synchronous |
| 804 // layout. | 804 // layout. |
| 805 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eSpelling)) { | 805 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eSpelling)) { |
| 806 Position start, end; | 806 Position start, end; |
| 807 if (newAdjacentWords.toNormalizedPositions(start, end)) | 807 if (newAdjacentWords.toNormalizedPositions(start, end)) |
| 808 m_frame.document()->markers().removeMarkers(start, end, Document
Marker::Spelling); | 808 m_frame->document()->markers().removeMarkers(start, end, Documen
tMarker::Spelling); |
| 809 } | 809 } |
| 810 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eGrammar)) { | 810 if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTyp
eGrammar)) { |
| 811 Position start, end; | 811 Position start, end; |
| 812 if (newSelectedSentence.toNormalizedPositions(start, end)) | 812 if (newSelectedSentence.toNormalizedPositions(start, end)) |
| 813 m_frame.document()->markers().removeMarkers(start, end, Document
Marker::Grammar); | 813 m_frame->document()->markers().removeMarkers(start, end, Documen
tMarker::Grammar); |
| 814 } | 814 } |
| 815 } | 815 } |
| 816 | 816 |
| 817 // When continuous spell checking is off, existing markers disappear after t
he selection changes. | 817 // When continuous spell checking is off, existing markers disappear after t
he selection changes. |
| 818 if (!isContinuousSpellCheckingEnabled) | 818 if (!isContinuousSpellCheckingEnabled) |
| 819 m_frame.document()->markers().removeMarkers(DocumentMarker::Spelling); | 819 m_frame->document()->markers().removeMarkers(DocumentMarker::Spelling); |
| 820 if (!isContinuousGrammarCheckingEnabled) | 820 if (!isContinuousGrammarCheckingEnabled) |
| 821 m_frame.document()->markers().removeMarkers(DocumentMarker::Grammar); | 821 m_frame->document()->markers().removeMarkers(DocumentMarker::Grammar); |
| 822 } | 822 } |
| 823 | 823 |
| 824 void SpellChecker::removeSpellingMarkers() | 824 void SpellChecker::removeSpellingMarkers() |
| 825 { | 825 { |
| 826 m_frame.document()->markers().removeMarkers(DocumentMarker::MisspellingMarke
rs()); | 826 m_frame->document()->markers().removeMarkers(DocumentMarker::MisspellingMark
ers()); |
| 827 } | 827 } |
| 828 | 828 |
| 829 void SpellChecker::removeSpellingMarkersUnderWords(const Vector<String>& words) | 829 void SpellChecker::removeSpellingMarkersUnderWords(const Vector<String>& words) |
| 830 { | 830 { |
| 831 MarkerRemoverPredicate removerPredicate(words); | 831 MarkerRemoverPredicate removerPredicate(words); |
| 832 | 832 |
| 833 DocumentMarkerController& markerController = m_frame.document()->markers(); | 833 DocumentMarkerController& markerController = m_frame->document()->markers(); |
| 834 markerController.removeMarkers(removerPredicate); | 834 markerController.removeMarkers(removerPredicate); |
| 835 markerController.repaintMarkers(); | 835 markerController.repaintMarkers(); |
| 836 } | 836 } |
| 837 | 837 |
| 838 void SpellChecker::spellCheckAfterBlur() | 838 void SpellChecker::spellCheckAfterBlur() |
| 839 { | 839 { |
| 840 if (!m_frame.selection().selection().isContentEditable()) | 840 if (!m_frame->selection().selection().isContentEditable()) |
| 841 return; | 841 return; |
| 842 | 842 |
| 843 if (isSelectionInTextField(m_frame.selection().selection())) { | 843 if (isSelectionInTextField(m_frame->selection().selection())) { |
| 844 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. | 844 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. |
| 845 return; | 845 return; |
| 846 } | 846 } |
| 847 | 847 |
| 848 VisibleSelection empty; | 848 VisibleSelection empty; |
| 849 spellCheckOldSelection(m_frame.selection().selection(), empty); | 849 spellCheckOldSelection(m_frame->selection().selection(), empty); |
| 850 } | 850 } |
| 851 | 851 |
| 852 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) | 852 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) |
| 853 { | 853 { |
| 854 VisiblePosition oldStart(oldSelection.visibleStart()); | 854 VisiblePosition oldStart(oldSelection.visibleStart()); |
| 855 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L
eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); | 855 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L
eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); |
| 856 if (oldAdjacentWords != newAdjacentWords) { | 856 if (oldAdjacentWords != newAdjacentWords) { |
| 857 if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) { | 857 if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) { |
| 858 VisibleSelection selectedSentence = VisibleSelection(startOfSentence
(oldStart), endOfSentence(oldStart)); | 858 VisibleSelection selectedSentence = VisibleSelection(startOfSentence
(oldStart), endOfSentence(oldStart)); |
| 859 markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSenten
ce); | 859 markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSenten
ce); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 876 node = node->firstChild(); | 876 node = node->firstChild(); |
| 877 else | 877 else |
| 878 node = node->nextSibling(); | 878 node = node->nextSibling(); |
| 879 } | 879 } |
| 880 | 880 |
| 881 return 0; | 881 return 0; |
| 882 } | 882 } |
| 883 | 883 |
| 884 bool SpellChecker::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerT
ype, int from, int length) const | 884 bool SpellChecker::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerT
ype, int from, int length) const |
| 885 { | 885 { |
| 886 Node* node = findFirstMarkable(m_frame.selection().start().deprecatedNode())
; | 886 Node* node = findFirstMarkable(m_frame->selection().start().deprecatedNode()
); |
| 887 if (!node) | 887 if (!node) |
| 888 return false; | 888 return false; |
| 889 | 889 |
| 890 unsigned startOffset = static_cast<unsigned>(from); | 890 unsigned startOffset = static_cast<unsigned>(from); |
| 891 unsigned endOffset = static_cast<unsigned>(from + length); | 891 unsigned endOffset = static_cast<unsigned>(from + length); |
| 892 DocumentMarkerVector markers = m_frame.document()->markers().markersFor(node
); | 892 DocumentMarkerVector markers = m_frame->document()->markers().markersFor(nod
e); |
| 893 for (size_t i = 0; i < markers.size(); ++i) { | 893 for (size_t i = 0; i < markers.size(); ++i) { |
| 894 DocumentMarker* marker = markers[i]; | 894 DocumentMarker* marker = markers[i]; |
| 895 if (marker->startOffset() <= startOffset && endOffset <= marker->endOffs
et() && marker->type() == markerType) | 895 if (marker->startOffset() <= startOffset && endOffset <= marker->endOffs
et() && marker->type() == markerType) |
| 896 return true; | 896 return true; |
| 897 } | 897 } |
| 898 | 898 |
| 899 return false; | 899 return false; |
| 900 } | 900 } |
| 901 | 901 |
| 902 bool SpellChecker::selectionStartHasSpellingMarkerFor(int from, int length) cons
t | 902 bool SpellChecker::selectionStartHasSpellingMarkerFor(int from, int length) cons
t |
| (...skipping 10 matching lines...) Expand all Loading... |
| 913 if (shouldMarkSpelling) | 913 if (shouldMarkSpelling) |
| 914 checkingTypes |= TextCheckingTypeSpelling; | 914 checkingTypes |= TextCheckingTypeSpelling; |
| 915 if (shouldMarkGrammar) | 915 if (shouldMarkGrammar) |
| 916 checkingTypes |= TextCheckingTypeGrammar; | 916 checkingTypes |= TextCheckingTypeGrammar; |
| 917 | 917 |
| 918 return checkingTypes; | 918 return checkingTypes; |
| 919 } | 919 } |
| 920 | 920 |
| 921 bool SpellChecker::unifiedTextCheckerEnabled() const | 921 bool SpellChecker::unifiedTextCheckerEnabled() const |
| 922 { | 922 { |
| 923 return blink::unifiedTextCheckerEnabled(&m_frame); | 923 return blink::unifiedTextCheckerEnabled(m_frame); |
| 924 } | 924 } |
| 925 | 925 |
| 926 void SpellChecker::cancelCheck() | 926 void SpellChecker::cancelCheck() |
| 927 { | 927 { |
| 928 m_spellCheckRequester->cancelCheck(); | 928 m_spellCheckRequester->cancelCheck(); |
| 929 } | 929 } |
| 930 | 930 |
| 931 void SpellChecker::requestTextChecking(const Element& element) | 931 void SpellChecker::requestTextChecking(const Element& element) |
| 932 { | 932 { |
| 933 RefPtrWillBeRawPtr<Range> rangeToCheck = rangeOfContents(const_cast<Element*
>(&element)); | 933 RefPtrWillBeRawPtr<Range> rangeToCheck = rangeOfContents(const_cast<Element*
>(&element)); |
| 934 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe
ck, rangeToCheck)); | 934 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToChe
ck, rangeToCheck)); |
| 935 } | 935 } |
| 936 | 936 |
| 937 void SpellChecker::trace(Visitor* visitor) |
| 938 { |
| 939 visitor->trace(m_frame); |
| 940 visitor->trace(m_spellCheckRequester); |
| 941 } |
| 937 | 942 |
| 938 } // namespace blink | 943 } // namespace blink |
| OLD | NEW |