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