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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 { | 69 { |
70 HTMLTextFormControlElement* textControl = enclosingTextFormControl(selection
.start()); | 70 HTMLTextFormControlElement* textControl = enclosingTextFormControl(selection
.start()); |
71 return isHTMLTextAreaElement(textControl); | 71 return isHTMLTextAreaElement(textControl); |
72 } | 72 } |
73 | 73 |
74 bool isSelectionInTextFormControl(const VisibleSelection& selection) | 74 bool isSelectionInTextFormControl(const VisibleSelection& selection) |
75 { | 75 { |
76 return !!enclosingTextFormControl(selection.start()); | 76 return !!enclosingTextFormControl(selection.start()); |
77 } | 77 } |
78 | 78 |
| 79 static bool isSpellCheckingEnabledFor(const VisibleSelection& selection) |
| 80 { |
| 81 if (selection.isNone()) |
| 82 return false; |
| 83 // TODO(tkent): The following password type check should be done in |
| 84 // HTMLElement::spellcheck(). crbug.com/371567 |
| 85 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(selec
tion.start())) { |
| 86 if (isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->
type() == InputTypeNames::password) |
| 87 return false; |
| 88 } |
| 89 if (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sele
ction.start().anchorNode())) { |
| 90 if (element->isSpellCheckingEnabled()) |
| 91 return true; |
| 92 } |
| 93 return false; |
| 94 } |
| 95 |
79 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) | 96 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) |
80 { | 97 { |
81 DCHECK(range.isNotNull()); | 98 DCHECK(range.isNotNull()); |
82 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition(
)); | 99 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition(
)); |
83 DCHECK(visibleEnd.isNotNull()); | 100 DCHECK(visibleEnd.isNotNull()); |
84 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); | 101 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); |
85 // TODO(xiaochengh): |sentenceEnd < range.startPosition()| seems possible, | 102 // TODO(xiaochengh): |sentenceEnd < range.startPosition()| seems possible, |
86 // which would trigger a DCHECK in EphemeralRange's constructor. Need more | 103 // which would trigger a DCHECK in EphemeralRange's constructor. Need more |
87 // investigation, and if that is really the case, fix it. | 104 // investigation, and if that is really the case, fix it. |
88 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente
nceEnd : range.endPosition()); | 105 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente
nceEnd : range.endPosition()); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 spellCheckerClient().showSpellingUI(true); | 308 spellCheckerClient().showSpellingUI(true); |
292 } | 309 } |
293 | 310 |
294 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) | 311 void SpellChecker::clearMisspellingsAndBadGrammar(const VisibleSelection &moving
Selection) |
295 { | 312 { |
296 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); | 313 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); |
297 } | 314 } |
298 | 315 |
299 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& selecti
on) | 316 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& selecti
on) |
300 { | 317 { |
301 if (!isSpellCheckingEnabled()) | 318 if (!isSpellCheckingEnabled() || !isSpellCheckingEnabledFor(selection)) |
302 return; | 319 return; |
303 | 320 |
304 const EphemeralRange& range = selection.toNormalizedEphemeralRange(); | 321 const EphemeralRange& range = selection.toNormalizedEphemeralRange(); |
305 if (range.isNull()) | 322 if (range.isNull()) |
306 return; | 323 return; |
307 | 324 |
308 // If we're not in an editable node, bail. | 325 // If we're not in an editable node, bail. |
309 Node* editableNode = range.startPosition().computeContainerNode(); | 326 Node* editableNode = range.startPosition().computeContainerNode(); |
310 if (!editableNode || !hasEditableStyle(*editableNode)) | 327 if (!editableNode || !hasEditableStyle(*editableNode)) |
311 return; | 328 return; |
312 | 329 |
313 if (!isSpellCheckingEnabledFor(editableNode)) | |
314 return; | |
315 | |
316 chunkAndMarkAllMisspellingsAndBadGrammar(range); | 330 chunkAndMarkAllMisspellingsAndBadGrammar(range); |
317 } | 331 } |
318 | 332 |
319 void SpellChecker::markMisspellingsAfterApplyingCommand(const CompositeEditComma
nd& cmd) | 333 void SpellChecker::markMisspellingsAfterApplyingCommand(const CompositeEditComma
nd& cmd) |
320 { | 334 { |
321 if (!isSpellCheckingEnabled()) | 335 if (!isSpellCheckingEnabled()) |
322 return; | 336 return; |
323 if (!isSpellCheckingEnabledFor(cmd.endingSelection())) | 337 if (!isSpellCheckingEnabledFor(cmd.endingSelection())) |
324 return; | 338 return; |
325 | 339 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 393 } |
380 | 394 |
381 void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word
Start) | 395 void SpellChecker::markMisspellingsAfterTypingToWord(const VisiblePosition &word
Start) |
382 { | 396 { |
383 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterTypingToWord"); | 397 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterTypingToWord"); |
384 | 398 |
385 VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, Lef
tWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)); | 399 VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, Lef
tWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)); |
386 markMisspellingsAndBadGrammar(adjacentWords); | 400 markMisspellingsAndBadGrammar(adjacentWords); |
387 } | 401 } |
388 | 402 |
389 bool SpellChecker::isSpellCheckingEnabledFor(const Node* node) const | 403 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const |
390 { | 404 { |
391 if (!node) | 405 Node* focusedNode = frame().selection().start().anchorNode(); |
| 406 if (!focusedNode) |
392 return false; | 407 return false; |
393 const Element* focusedElement = node->isElementNode() ? toElement(node) : no
de->parentElement(); | 408 const Element* focusedElement = focusedNode->isElementNode() ? toElement(foc
usedNode) : focusedNode->parentElement(); |
394 if (!focusedElement) | 409 if (!focusedElement) |
395 return false; | 410 return false; |
396 return focusedElement->isSpellCheckingEnabled(); | 411 return focusedElement->isSpellCheckingEnabled(); |
397 } | 412 } |
398 | 413 |
399 bool SpellChecker::isSpellCheckingEnabledInFocusedNode() const | |
400 { | |
401 return isSpellCheckingEnabledFor(frame().selection().start().anchorNode()); | |
402 } | |
403 | |
404 bool SpellChecker::isSpellCheckingEnabledFor(const VisibleSelection& selection) | |
405 { | |
406 if (selection.isNone()) | |
407 return false; | |
408 // TODO(tkent): The following password type check should be done in | |
409 // HTMLElement::spellcheck(). crbug.com/371567 | |
410 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(selec
tion.start())) { | |
411 if (isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->
type() == InputTypeNames::password) | |
412 return false; | |
413 } | |
414 if (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sele
ction.start().anchorNode())) { | |
415 if (element->spellcheck()) | |
416 return true; | |
417 } | |
418 return false; | |
419 } | |
420 | |
421 void SpellChecker::markMisspellingsAfterReplaceSelectionCommand(const ReplaceSel
ectionCommand& cmd) | 414 void SpellChecker::markMisspellingsAfterReplaceSelectionCommand(const ReplaceSel
ectionCommand& cmd) |
422 { | 415 { |
423 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterReplaceSelectionCo
mmand"); | 416 TRACE_EVENT0("blink", "SpellChecker::markMisspellingsAfterReplaceSelectionCo
mmand"); |
424 | 417 |
425 chunkAndMarkAllMisspellingsAndBadGrammar(cmd.insertedRange()); | 418 chunkAndMarkAllMisspellingsAndBadGrammar(cmd.insertedRange()); |
426 } | 419 } |
427 | 420 |
428 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(const EphemeralRange
& range) | 421 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(const EphemeralRange
& range) |
429 { | 422 { |
430 if (range.isNull()) | 423 if (range.isNull()) |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 frame().document()->markers().removeMarkers(range, markerTypes); | 816 frame().document()->markers().removeMarkers(range, markerTypes); |
824 } | 817 } |
825 | 818 |
826 void SpellChecker::cancelCheck() | 819 void SpellChecker::cancelCheck() |
827 { | 820 { |
828 m_spellCheckRequester->cancelCheck(); | 821 m_spellCheckRequester->cancelCheck(); |
829 } | 822 } |
830 | 823 |
831 void SpellChecker::requestTextChecking(const Element& element) | 824 void SpellChecker::requestTextChecking(const Element& element) |
832 { | 825 { |
833 if (!isSpellCheckingEnabledFor(&element)) | 826 if (!element.isSpellCheckingEnabled()) |
834 return; | 827 return; |
835 const EphemeralRange rangeToCheck = EphemeralRange::rangeOfContents(element)
; | 828 const EphemeralRange rangeToCheck = EphemeralRange::rangeOfContents(element)
; |
836 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingProcessBatch, rangeToCheck)); | 829 m_spellCheckRequester->requestCheckingFor(SpellCheckRequest::create(TextChec
kingProcessBatch, rangeToCheck)); |
837 } | 830 } |
838 | 831 |
839 DEFINE_TRACE(SpellChecker) | 832 DEFINE_TRACE(SpellChecker) |
840 { | 833 { |
841 visitor->trace(m_frame); | 834 visitor->trace(m_frame); |
842 visitor->trace(m_spellCheckRequester); | 835 visitor->trace(m_spellCheckRequester); |
843 } | 836 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); | 940 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); |
948 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | 941 paragraphStart = newParagraphStart.toParentAnchoredPosition(); |
949 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); | 942 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); |
950 firstIteration = false; | 943 firstIteration = false; |
951 totalLengthProcessed += currentLength; | 944 totalLengthProcessed += currentLength; |
952 } | 945 } |
953 return std::make_pair(firstFoundItem, firstFoundOffset); | 946 return std::make_pair(firstFoundItem, firstFoundOffset); |
954 } | 947 } |
955 | 948 |
956 } // namespace blink | 949 } // namespace blink |
OLD | NEW |