| 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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 for (Node& node : NodeTraversal::startsAt(toLocalFrame(frame)->document(
)->rootNode())) | 164 for (Node& node : NodeTraversal::startsAt(toLocalFrame(frame)->document(
)->rootNode())) |
| 165 node.setAlreadySpellChecked(false); | 165 node.setAlreadySpellChecked(false); |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 void SpellChecker::didBeginEditing(Element* element) | 169 void SpellChecker::didBeginEditing(Element* element) |
| 170 { | 170 { |
| 171 if (!isSpellCheckingEnabled()) | 171 if (!isSpellCheckingEnabled()) |
| 172 return; | 172 return; |
| 173 | 173 |
| 174 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 175 // needs to be audited. See http://crbug.com/590369 for more details. |
| 176 // In the long term we should use idle time spell checker to prevent |
| 177 // synchronous layout caused by spell checking (see crbug.com/517298). |
| 178 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 179 |
| 180 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle()); |
| 181 |
| 174 bool isTextField = false; | 182 bool isTextField = false; |
| 175 HTMLTextFormControlElement* enclosingHTMLTextFormControlElement = 0; | 183 HTMLTextFormControlElement* enclosingHTMLTextFormControlElement = 0; |
| 176 if (!isHTMLTextFormControlElement(*element)) | 184 if (!isHTMLTextFormControlElement(*element)) |
| 177 enclosingHTMLTextFormControlElement = enclosingTextFormControl(Position:
:firstPositionInNode(element)); | 185 enclosingHTMLTextFormControlElement = enclosingTextFormControl(Position:
:firstPositionInNode(element)); |
| 178 element = enclosingHTMLTextFormControlElement ? enclosingHTMLTextFormControl
Element : element; | 186 element = enclosingHTMLTextFormControlElement ? enclosingHTMLTextFormControl
Element : element; |
| 179 Element* parent = element; | 187 Element* parent = element; |
| 180 if (isHTMLTextFormControlElement(*element)) { | 188 if (isHTMLTextFormControlElement(*element)) { |
| 181 HTMLTextFormControlElement* textControl = toHTMLTextFormControlElement(e
lement); | 189 HTMLTextFormControlElement* textControl = toHTMLTextFormControlElement(e
lement); |
| 182 parent = textControl; | 190 parent = textControl; |
| 183 element = textControl->innerEditorElement(); | 191 element = textControl->innerEditorElement(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 spellCheckerClient().showSpellingUI(true); | 316 spellCheckerClient().showSpellingUI(true); |
| 309 } | 317 } |
| 310 | 318 |
| 311 void SpellChecker::clearMisspellingsAndBadGrammarForMovingParagraphs(const Visib
leSelection& movingSelection) | 319 void SpellChecker::clearMisspellingsAndBadGrammarForMovingParagraphs(const Visib
leSelection& movingSelection) |
| 312 { | 320 { |
| 313 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); | 321 removeMarkers(movingSelection, DocumentMarker::MisspellingMarkers()); |
| 314 } | 322 } |
| 315 | 323 |
| 316 void SpellChecker::markMisspellingsAndBadGrammarForMovingParagraphs(const Visibl
eSelection& movingSelection) | 324 void SpellChecker::markMisspellingsAndBadGrammarForMovingParagraphs(const Visibl
eSelection& movingSelection) |
| 317 { | 325 { |
| 326 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 327 // needs to be audited. See http://crbug.com/590369 for more details. |
| 328 // In the long term we should use idle time spell checker to prevent |
| 329 // synchronous layout caused by spell checking (see crbug.com/517298). |
| 330 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 331 |
| 332 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle()); |
| 333 |
| 318 markMisspellingsAndBadGrammar(movingSelection); | 334 markMisspellingsAndBadGrammar(movingSelection); |
| 319 } | 335 } |
| 320 | 336 |
| 321 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& selecti
on) | 337 void SpellChecker::markMisspellingsAndBadGrammar(const VisibleSelection& selecti
on) |
| 322 { | 338 { |
| 323 if (!isSpellCheckingEnabled() || !isSpellCheckingEnabledFor(selection)) | 339 if (!isSpellCheckingEnabled() || !isSpellCheckingEnabledFor(selection)) |
| 324 return; | 340 return; |
| 325 | 341 |
| 326 const EphemeralRange& range = selection.toNormalizedEphemeralRange(); | 342 const EphemeralRange& range = selection.toNormalizedEphemeralRange(); |
| 327 if (range.isNull()) | 343 if (range.isNull()) |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 return; | 496 return; |
| 481 } | 497 } |
| 482 if (!request->isValid()) | 498 if (!request->isValid()) |
| 483 return; | 499 return; |
| 484 if (request->rootEditableElement()->document() != frame().selection().docume
nt()) { | 500 if (request->rootEditableElement()->document() != frame().selection().docume
nt()) { |
| 485 // we ignore |request| made for another document. | 501 // we ignore |request| made for another document. |
| 486 // "editing/spelling/spellcheck-sequencenum.html" and others reach here. | 502 // "editing/spelling/spellcheck-sequencenum.html" and others reach here. |
| 487 return; | 503 return; |
| 488 } | 504 } |
| 489 | 505 |
| 506 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
needs to be audited. |
| 507 // see http://crbug.com/590369 for more details. |
| 508 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 509 |
| 490 TextCheckingParagraph paragraph(request->checkingRange(), request->checkingR
ange()); | 510 TextCheckingParagraph paragraph(request->checkingRange(), request->checkingR
ange()); |
| 491 | 511 |
| 492 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. | 512 // Expand the range to encompass entire paragraphs, since text checking need
s that much context. |
| 493 int selectionOffset = 0; | 513 int selectionOffset = 0; |
| 494 int ambiguousBoundaryOffset = -1; | 514 int ambiguousBoundaryOffset = -1; |
| 495 bool selectionChanged = false; | 515 bool selectionChanged = false; |
| 496 bool restoreSelectionAfterChange = false; | 516 bool restoreSelectionAfterChange = false; |
| 497 bool adjustSelectionForParagraphBoundaries = false; | 517 bool adjustSelectionForParagraphBoundaries = false; |
| 498 | 518 |
| 499 if (frame().selection().isCaret()) { | |
| 500 // Attempt to save the caret position so we can restore it later if need
ed | |
| 501 Position caretPosition = frame().selection().end(); | |
| 502 selectionOffset = paragraph.offsetTo(caretPosition); | |
| 503 restoreSelectionAfterChange = true; | |
| 504 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) > par
agraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newlineCh
aracter)) | |
| 505 adjustSelectionForParagraphBoundaries = true; | |
| 506 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <= par
agraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(sele
ctionOffset - 1))) | |
| 507 ambiguousBoundaryOffset = selectionOffset - 1; | |
| 508 } | |
| 509 | |
| 510 // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets n
eeds to be audited. | |
| 511 // see http://crbug.com/590369 for more details. | |
| 512 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 513 | |
| 514 { | 519 { |
| 515 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle
()); | 520 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle
()); |
| 516 | 521 |
| 522 if (frame().selection().isCaret()) { |
| 523 // Attempt to save the caret position so we can restore it later if
needed |
| 524 Position caretPosition = frame().selection().end(); |
| 525 selectionOffset = paragraph.offsetTo(caretPosition); |
| 526 restoreSelectionAfterChange = true; |
| 527 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) |
| 528 adjustSelectionForParagraphBoundaries = true; |
| 529 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) |
| 530 ambiguousBoundaryOffset = selectionOffset - 1; |
| 531 } |
| 532 |
| 517 for (unsigned i = 0; i < results.size(); i++) { | 533 for (unsigned i = 0; i < results.size(); i++) { |
| 518 int spellingRangeEndOffset = paragraph.checkingEnd(); | 534 int spellingRangeEndOffset = paragraph.checkingEnd(); |
| 519 const TextCheckingResult* result = &results[i]; | 535 const TextCheckingResult* result = &results[i]; |
| 520 int resultLocation = result->location + paragraph.checkingStart(); | 536 int resultLocation = result->location + paragraph.checkingStart(); |
| 521 int resultLength = result->length; | 537 int resultLength = result->length; |
| 522 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 &&
resultLocation + resultLength == ambiguousBoundaryOffset; | 538 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 &&
resultLocation + resultLength == ambiguousBoundaryOffset; |
| 523 | 539 |
| 524 // Only mark misspelling if: | 540 // Only mark misspelling if: |
| 525 // 1. Current text checking isn't done for autocorrection. | 541 // 1. Current text checking isn't done for autocorrection. |
| 526 // 2. Result falls within spellingRange. | 542 // 2. Result falls within spellingRange. |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 682 } | 698 } |
| 683 | 699 |
| 684 static bool shouldCheckOldSelection(const VisibleSelection& oldSelection) | 700 static bool shouldCheckOldSelection(const VisibleSelection& oldSelection) |
| 685 { | 701 { |
| 686 if (!oldSelection.start().isConnected()) | 702 if (!oldSelection.start().isConnected()) |
| 687 return false; | 703 return false; |
| 688 if (isSelectionInTextField(oldSelection)) | 704 if (isSelectionInTextField(oldSelection)) |
| 689 return false; | 705 return false; |
| 690 if (isSelectionInTextArea(oldSelection)) | 706 if (isSelectionInTextArea(oldSelection)) |
| 691 return true; | 707 return true; |
| 708 |
| 709 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 710 // needs to be audited. See http://crbug.com/590369 for more details. |
| 711 // In the long term we should use idle time spell checker to prevent |
| 712 // synchronous layout caused by spell checking (see crbug.com/517298). |
| 692 oldSelection.start().document()->updateStyleAndLayoutIgnorePendingStylesheet
s(); | 713 oldSelection.start().document()->updateStyleAndLayoutIgnorePendingStylesheet
s(); |
| 714 |
| 693 return oldSelection.isContentEditable(); | 715 return oldSelection.isContentEditable(); |
| 694 } | 716 } |
| 695 | 717 |
| 696 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) | 718 void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelectio
n, FrameSelection::SetSelectionOptions options) |
| 697 { | 719 { |
| 698 TRACE_EVENT0("blink", "SpellChecker::respondToChangedSelection"); | 720 TRACE_EVENT0("blink", "SpellChecker::respondToChangedSelection"); |
| 699 if (!isSpellCheckingEnabledFor(oldSelection)) | 721 if (!isSpellCheckingEnabledFor(oldSelection)) |
| 700 return; | 722 return; |
| 701 | 723 |
| 702 // When spell checking is off, existing markers disappear after the selectio
n changes. | 724 // When spell checking is off, existing markers disappear after the selectio
n changes. |
| 703 if (!isSpellCheckingEnabled()) { | 725 if (!isSpellCheckingEnabled()) { |
| 704 frame().document()->markers().removeMarkers(DocumentMarker::Spelling); | 726 frame().document()->markers().removeMarkers(DocumentMarker::Spelling); |
| 705 frame().document()->markers().removeMarkers(DocumentMarker::Grammar); | 727 frame().document()->markers().removeMarkers(DocumentMarker::Grammar); |
| 706 return; | 728 return; |
| 707 } | 729 } |
| 708 | 730 |
| 709 if (!(options & FrameSelection::CloseTyping)) | 731 if (!(options & FrameSelection::CloseTyping)) |
| 710 return; | 732 return; |
| 711 if (!shouldCheckOldSelection(oldSelection)) | 733 if (!shouldCheckOldSelection(oldSelection)) |
| 712 return; | 734 return; |
| 713 | 735 |
| 736 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle()); |
| 737 |
| 714 VisibleSelection newAdjacentWords; | 738 VisibleSelection newAdjacentWords; |
| 715 const VisibleSelection newSelection = frame().selection().selection(); | 739 const VisibleSelection newSelection = frame().selection().selection(); |
| 716 if (isSelectionInTextFormControl(newSelection)) { | 740 if (isSelectionInTextFormControl(newSelection)) { |
| 717 const Position newStart = newSelection.start(); | 741 const Position newStart = newSelection.start(); |
| 718 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::startO
fWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); | 742 newAdjacentWords.setWithoutValidation(HTMLTextFormControlElement::startO
fWord(newStart), HTMLTextFormControlElement::endOfWord(newStart)); |
| 719 } else { | 743 } else { |
| 720 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 744 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 721 const bool caretBrowsing = frame().settings() && frame().settings()->car
etBrowsingEnabled(); | 745 const bool caretBrowsing = frame().settings() && frame().settings()->car
etBrowsingEnabled(); |
| 722 if (newSelection.isContentEditable() || caretBrowsing) { | 746 if (newSelection.isContentEditable() || caretBrowsing) { |
| 723 const VisiblePosition newStart(newSelection.visibleStart()); | 747 const VisiblePosition newStart(newSelection.visibleStart()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 750 void SpellChecker::spellCheckAfterBlur() | 774 void SpellChecker::spellCheckAfterBlur() |
| 751 { | 775 { |
| 752 if (!frame().selection().selection().isContentEditable()) | 776 if (!frame().selection().selection().isContentEditable()) |
| 753 return; | 777 return; |
| 754 | 778 |
| 755 if (isSelectionInTextField(frame().selection().selection())) { | 779 if (isSelectionInTextField(frame().selection().selection())) { |
| 756 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. | 780 // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this. |
| 757 return; | 781 return; |
| 758 } | 782 } |
| 759 | 783 |
| 784 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 785 // needs to be audited. See http://crbug.com/590369 for more details. |
| 786 // In the long term we should use idle time spell checker to prevent |
| 787 // synchronous layout caused by spell checking (see crbug.com/517298). |
| 788 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 789 |
| 790 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle()); |
| 791 |
| 760 VisibleSelection empty; | 792 VisibleSelection empty; |
| 761 spellCheckOldSelection(frame().selection().selection(), empty); | 793 spellCheckOldSelection(frame().selection().selection(), empty); |
| 762 } | 794 } |
| 763 | 795 |
| 764 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) | 796 void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection,
const VisibleSelection& newAdjacentWords) |
| 765 { | 797 { |
| 766 if (!isSpellCheckingEnabled()) | 798 if (!isSpellCheckingEnabled()) |
| 767 return; | 799 return; |
| 768 | 800 |
| 769 TRACE_EVENT0("blink", "SpellChecker::spellCheckOldSelection"); | 801 TRACE_EVENT0("blink", "SpellChecker::spellCheckOldSelection"); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); | 980 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); |
| 949 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | 981 paragraphStart = newParagraphStart.toParentAnchoredPosition(); |
| 950 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); | 982 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); |
| 951 firstIteration = false; | 983 firstIteration = false; |
| 952 totalLengthProcessed += currentLength; | 984 totalLengthProcessed += currentLength; |
| 953 } | 985 } |
| 954 return std::make_pair(firstFoundItem, firstFoundOffset); | 986 return std::make_pair(firstFoundItem, firstFoundOffset); |
| 955 } | 987 } |
| 956 | 988 |
| 957 } // namespace blink | 989 } // namespace blink |
| OLD | NEW |