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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 { | 65 { |
66 HTMLTextFormControlElement* textControl = enclosingTextFormControl(selection .start()); | 66 HTMLTextFormControlElement* textControl = enclosingTextFormControl(selection .start()); |
67 return isHTMLTextAreaElement(textControl); | 67 return isHTMLTextAreaElement(textControl); |
68 } | 68 } |
69 | 69 |
70 bool isSelectionInTextFormControl(const VisibleSelection& selection) | 70 bool isSelectionInTextFormControl(const VisibleSelection& selection) |
71 { | 71 { |
72 return !!enclosingTextFormControl(selection.start()); | 72 return !!enclosingTextFormControl(selection.start()); |
73 } | 73 } |
74 | 74 |
75 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) | |
76 { | |
77 DCHECK(range.isNotNull()); | |
78 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition( )); | |
79 DCHECK(visibleEnd.isNotNull()); | |
80 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); | |
81 // TODO(xiaochengh): |sentenceEnd < range.startPosition()| seems possible, | |
82 // which would trigger a DCHECK in EphemeralRange's constructor. Need more | |
83 // investigation, and if that is really the case, fix it. | |
84 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente nceEnd : range.endPosition()); | |
85 } | |
86 | |
87 static EphemeralRange expandRangeToSentenceBoundary(const EphemeralRange& range) | |
88 { | |
89 DCHECK(range.isNotNull()); | |
90 const VisiblePosition& visibleStart = createVisiblePosition(range.startPosit ion()); | |
91 DCHECK(visibleStart.isNotNull()); | |
92 const Position& sentenceStart = startOfSentence(visibleStart).deepEquivalent (); | |
93 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition( )); | |
94 DCHECK(visibleStart.isNotNull()); | |
95 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); | |
96 return EphemeralRange(sentenceStart.isNull() ? range.startPosition() : sente nceStart, sentenceEnd.isNull() ? range.endPosition() : sentenceEnd); | |
97 } | |
98 | |
75 } // namespace | 99 } // namespace |
76 | 100 |
77 SpellChecker* SpellChecker::create(LocalFrame& frame) | 101 SpellChecker* SpellChecker::create(LocalFrame& frame) |
78 { | 102 { |
79 return new SpellChecker(frame); | 103 return new SpellChecker(frame); |
80 } | 104 } |
81 | 105 |
82 static SpellCheckerClient& emptySpellCheckerClient() | 106 static SpellCheckerClient& emptySpellCheckerClient() |
83 { | 107 { |
84 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); | 108 DEFINE_STATIC_LOCAL(EmptySpellCheckerClient, client, ()); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 | 283 |
260 advanceToNextMisspelling(true); | 284 advanceToNextMisspelling(true); |
261 spellCheckerClient().showSpellingUI(true); | 285 spellCheckerClient().showSpellingUI(true); |
262 } | 286 } |
263 | 287 |
264 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving Selection) | 288 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving Selection) |
265 { | 289 { |
266 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); | 290 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); |
267 } | 291 } |
268 | 292 |
269 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection &movingS election) | 293 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& selecti on) |
270 { | 294 { |
271 markAllMisspellingsAndBadGrammar(movingSelection, movingSelection); | 295 if (!isContinuousSpellCheckingEnabled()) |
yosin_UTC9
2016/08/16 02:28:47
BTW, Could you rename |isContinuousSpellCheckingEn
| |
296 return; | |
297 | |
298 const EphemeralRange& range = selection.toNormalizedEphemeralRange(); | |
299 if (range.isNull()) | |
300 return; | |
301 | |
302 // If we're not in an editable node, bail. | |
303 Node* editableNode = range.startPosition().computeContainerNode(); | |
304 if (!editableNode || !hasEditableStyle(*editableNode)) | |
305 return; | |
306 | |
307 if (!isSpellCheckingEnabledFor(editableNode)) | |
308 return; | |
309 | |
310 TextCheckingParagraph fullParagraphToCheck(expandRangeToSentenceBoundary(ran ge)); | |
311 chunkAndMarkAllMisspellingsAndBadGrammar(fullParagraphToCheck); | |
272 } | 312 } |
273 | 313 |
274 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe lection) | 314 void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSe lection) |
275 { | 315 { |
276 if (!isContinuousSpellCheckingEnabled()) | 316 if (!isContinuousSpellCheckingEnabled()) |
277 return; | 317 return; |
278 | 318 |
279 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterLineBreak"); | 319 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterLineBreak"); |
280 | 320 |
281 VisibleSelection wholeParagraph( | 321 markMisspellingsAndBadGrammar(wordSelection); |
282 startOfParagraph(wordSelection.visibleStart()), | |
283 endOfParagraph(wordSelection.visibleEnd())); | |
284 | |
285 markAllMisspellingsAndBadGrammar(wordSelection, wholeParagraph); | |
286 } | 322 } |
287 | 323 |
288 void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word Start, const VisibleSelection& selectionAfterTyping) | 324 void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word Start, const VisibleSelection& selectionAfterTyping) |
289 { | 325 { |
290 if (!isContinuousSpellCheckingEnabled()) | 326 if (!isContinuousSpellCheckingEnabled()) |
291 return; | 327 return; |
292 | 328 |
293 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterTypingToWord"); | 329 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterTypingToWord"); |
294 | 330 |
295 VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, Lef tWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)); | 331 VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, Lef tWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)); |
296 VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordSta rt), endOfSentence(wordStart)); | 332 markMisspellingsAndBadGrammar(adjacentWords); |
297 markAllMisspellingsAndBadGrammar(adjacentWords, selectedSentence); | |
298 } | 333 } |
299 | 334 |
300 bool SpellChecker::isSpellCheckingEnabledFor(Node* node) const | 335 bool SpellChecker::isSpellCheckingEnabledFor(Node* node) const |
301 { | 336 { |
302 if (!node) | 337 if (!node) |
303 return false; | 338 return false; |
304 const Element* focusedElement = node->isElementNode() ? toElement(node) : no de->parentElement(); | 339 const Element* focusedElement = node->isElementNode() ? toElement(node) : no de->parentElement(); |
305 if (!focusedElement) | 340 if (!focusedElement) |
306 return false; | 341 return false; |
307 return focusedElement->isSpellCheckingEnabled(); | 342 return focusedElement->isSpellCheckingEnabled(); |
(...skipping 14 matching lines...) Expand all Loading... | |
322 if (isHTMLInputElement(textControl) && toHTMLInputElement(textControl)-> type() == InputTypeNames::password) | 357 if (isHTMLInputElement(textControl) && toHTMLInputElement(textControl)-> type() == InputTypeNames::password) |
323 return false; | 358 return false; |
324 } | 359 } |
325 if (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sele ction.start().anchorNode())) { | 360 if (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sele ction.start().anchorNode())) { |
326 if (element->spellcheck()) | 361 if (element->spellcheck()) |
327 return true; | 362 return true; |
328 } | 363 } |
329 return false; | 364 return false; |
330 } | 365 } |
331 | 366 |
332 void SpellChecker::markAllMisspellingsAndBadGrammar(const VisibleSelection& spel lingSelection, const VisibleSelection& grammarSelection) | |
333 { | |
334 if (!isContinuousSpellCheckingEnabled()) | |
335 return; | |
336 | |
337 // This function is called with selections already expanded to word boundari es. | |
338 // This function is triggered by selection change, in which case we check | |
339 // spelling and grammar, but don't autocorrect misspellings. | |
340 | |
341 const EphemeralRange& spellingRange = spellingSelection.toNormalizedEphemera lRange(); | |
342 const EphemeralRange& grammarRange = grammarSelection.toNormalizedEphemeralR ange(); | |
343 if (spellingRange.isNull() || grammarRange.isNull()) | |
344 return; | |
345 | |
346 // If we're not in an editable node, bail. | |
347 Node* editableNode = spellingRange.startPosition().computeContainerNode(); | |
348 if (!editableNode || !hasEditableStyle(*editableNode)) | |
349 return; | |
350 | |
351 if (!isSpellCheckingEnabledFor(editableNode)) | |
352 return; | |
353 | |
354 TextCheckingParagraph fullParagraphToCheck(grammarRange); | |
355 chunkAndMarkAllMisspellingsAndBadGrammar(fullParagraphToCheck); | |
356 } | |
357 | |
358 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) | |
359 { | |
360 DCHECK(range.isNotNull()); | |
361 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition( )); | |
362 DCHECK(visibleEnd.isNotNull()); | |
363 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); | |
364 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente nceEnd : range.endPosition()); | |
365 } | |
366 | |
367 static EphemeralRange expandRangeToSentenceBoundary(const EphemeralRange& range) | |
368 { | |
369 DCHECK(range.isNotNull()); | |
370 const VisiblePosition& visibleStart = createVisiblePosition(range.startPosit ion()); | |
371 DCHECK(visibleStart.isNotNull()); | |
372 const Position& sentenceStart = startOfSentence(visibleStart).deepEquivalent (); | |
373 return expandEndToSentenceBoundary(EphemeralRange(sentenceStart.isNull() ? r ange.startPosition() : sentenceStart, range.endPosition())); | |
374 } | |
375 | |
376 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node, const Ep hemeralRange& insertedRange) | 367 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node, const Ep hemeralRange& insertedRange) |
377 { | 368 { |
378 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r"); | 369 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r"); |
379 if (!node) | 370 if (!node) |
380 return; | 371 return; |
381 EphemeralRange paragraphRange(Position::firstPositionInNode(node), Position: :lastPositionInNode(node)); | 372 EphemeralRange paragraphRange(Position::firstPositionInNode(node), Position: :lastPositionInNode(node)); |
382 TextCheckingParagraph textToCheck(insertedRange, paragraphRange); | 373 TextCheckingParagraph textToCheck(insertedRange, paragraphRange); |
383 chunkAndMarkAllMisspellingsAndBadGrammar(textToCheck); | 374 chunkAndMarkAllMisspellingsAndBadGrammar(textToCheck); |
384 } | 375 } |
385 | 376 |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
714 { | 705 { |
715 if (!isContinuousSpellCheckingEnabled()) | 706 if (!isContinuousSpellCheckingEnabled()) |
716 return; | 707 return; |
717 | 708 |
718 TRACE_EVENT0("blink", "SpellChecker::spellCheckOldSelection"); | 709 TRACE_EVENT0("blink", "SpellChecker::spellCheckOldSelection"); |
719 | 710 |
720 VisiblePosition oldStart(oldSelection.visibleStart()); | 711 VisiblePosition oldStart(oldSelection.visibleStart()); |
721 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); | 712 VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, L eftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); |
722 if (oldAdjacentWords == newAdjacentWords) | 713 if (oldAdjacentWords == newAdjacentWords) |
723 return; | 714 return; |
724 VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStar t), endOfSentence(oldStart)); | 715 markMisspellingsAndBadGrammar(oldAdjacentWords); |
725 markAllMisspellingsAndBadGrammar(oldAdjacentWords, selectedSentence); | |
726 } | 716 } |
727 | 717 |
728 static Node* findFirstMarkable(Node* node) | 718 static Node* findFirstMarkable(Node* node) |
729 { | 719 { |
730 while (node) { | 720 while (node) { |
731 if (!node->layoutObject()) | 721 if (!node->layoutObject()) |
732 return 0; | 722 return 0; |
733 if (node->layoutObject()->isText()) | 723 if (node->layoutObject()->isText()) |
734 return node; | 724 return node; |
735 if (node->layoutObject()->isTextControl()) | 725 if (node->layoutObject()->isTextControl()) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
790 visitor->trace(m_frame); | 780 visitor->trace(m_frame); |
791 visitor->trace(m_spellCheckRequester); | 781 visitor->trace(m_spellCheckRequester); |
792 } | 782 } |
793 | 783 |
794 void SpellChecker::prepareForLeakDetection() | 784 void SpellChecker::prepareForLeakDetection() |
795 { | 785 { |
796 m_spellCheckRequester->prepareForLeakDetection(); | 786 m_spellCheckRequester->prepareForLeakDetection(); |
797 } | 787 } |
798 | 788 |
799 } // namespace blink | 789 } // namespace blink |
OLD | NEW |