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 |