Chromium Code Reviews| 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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 | 291 |
| 292 badGrammarPhrase = TextCheckingHelper(spellCheckerClient(), grammarS earchStart, grammarSearchEnd).findFirstBadGrammar(grammarDetail, grammarPhraseOf fset, false); | 292 badGrammarPhrase = TextCheckingHelper(spellCheckerClient(), grammarS earchStart, grammarSearchEnd).findFirstBadGrammar(grammarDetail, grammarPhraseOf fset, false); |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 | 295 |
| 296 if (!badGrammarPhrase.isEmpty()) { | 296 if (!badGrammarPhrase.isEmpty()) { |
| 297 // We found bad grammar. Since we only searched for bad grammar up to th e first misspelled word, the bad grammar | 297 // We found bad grammar. Since we only searched for bad grammar up to th e first misspelled word, the bad grammar |
| 298 // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling | 298 // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling |
| 299 // panel, and store a marker so we draw the green squiggle later. | 299 // panel, and store a marker so we draw the green squiggle later. |
| 300 | 300 |
| 301 ASSERT(badGrammarPhrase.length() > 0); | 301 DCHECK_GT(badGrammarPhrase.length(), 0u); |
| 302 ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0); | 302 DCHECK(grammarDetail.location != -1 && grammarDetail.length > 0); |
| 303 | 303 |
| 304 // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph | 304 // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph |
| 305 const EphemeralRange badGrammarRange = calculateCharacterSubrange(Epheme ralRange(grammarSearchStart, grammarSearchEnd), grammarPhraseOffset + grammarDet ail.location, grammarDetail.length); | 305 const EphemeralRange badGrammarRange = calculateCharacterSubrange(Epheme ralRange(grammarSearchStart, grammarSearchEnd), grammarPhraseOffset + grammarDet ail.location, grammarDetail.length); |
| 306 frame().selection().setSelection(VisibleSelection(badGrammarRange)); | 306 frame().selection().setSelection(VisibleSelection(badGrammarRange)); |
| 307 frame().selection().revealSelection(); | 307 frame().selection().revealSelection(); |
| 308 | 308 |
| 309 frame().document()->markers().addMarker(badGrammarRange.startPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, grammarDetail.userDescr iption); | 309 frame().document()->markers().addMarker(badGrammarRange.startPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, grammarDetail.userDescr iption); |
| 310 } else if (!misspelledWord.isEmpty()) { | 310 } else if (!misspelledWord.isEmpty()) { |
| 311 // We found a misspelling, but not any earlier bad grammar. Select the m isspelling, update the spelling panel, and store | 311 // We found a misspelling, but not any earlier bad grammar. Select the m isspelling, update the spelling panel, and store |
| 312 // a marker so we draw the red squiggle later. | 312 // a marker so we draw the red squiggle later. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 return markMisspellingsOrBadGrammar(selection, true); | 471 return markMisspellingsOrBadGrammar(selection, true); |
| 472 } | 472 } |
| 473 | 473 |
| 474 void SpellChecker::markBadGrammar(const VisibleSelection& selection) | 474 void SpellChecker::markBadGrammar(const VisibleSelection& selection) |
| 475 { | 475 { |
| 476 markMisspellingsOrBadGrammar(selection, false); | 476 markMisspellingsOrBadGrammar(selection, false); |
| 477 } | 477 } |
| 478 | 478 |
| 479 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, const EphemeralRange& spellingRange, const EphemeralRange& grammarRange) | 479 void SpellChecker::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, const EphemeralRange& spellingRange, const EphemeralRange& grammarRange) |
| 480 { | 480 { |
| 481 ASSERT(unifiedTextCheckerEnabled()); | 481 DCHECK(unifiedTextCheckerEnabled()); |
| 482 | 482 |
| 483 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; | 483 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
| 484 | 484 |
| 485 // This function is called with selections already expanded to word boundari es. | 485 // This function is called with selections already expanded to word boundari es. |
| 486 if (spellingRange.isNull() || (shouldMarkGrammar && grammarRange.isNull())) | 486 if (spellingRange.isNull() || (shouldMarkGrammar && grammarRange.isNull())) |
| 487 return; | 487 return; |
| 488 | 488 |
| 489 // If we're not in an editable node, bail. | 489 // If we're not in an editable node, bail. |
| 490 Node* editableNode = spellingRange.startPosition().computeContainerNode(); | 490 Node* editableNode = spellingRange.startPosition().computeContainerNode(); |
| 491 if (!editableNode || !editableNode->hasEditableStyle()) | 491 if (!editableNode || !editableNode->hasEditableStyle()) |
| 492 return; | 492 return; |
| 493 | 493 |
| 494 if (!isSpellCheckingEnabledFor(editableNode)) | 494 if (!isSpellCheckingEnabledFor(editableNode)) |
| 495 return; | 495 return; |
| 496 | 496 |
| 497 TextCheckingParagraph fullParagraphToCheck(shouldMarkGrammar ? grammarRange : spellingRange); | 497 TextCheckingParagraph fullParagraphToCheck(shouldMarkGrammar ? grammarRange : spellingRange); |
| 498 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT oCheck); | 498 chunkAndMarkAllMisspellingsAndBadGrammar(textCheckingOptions, fullParagraphT oCheck); |
| 499 } | 499 } |
| 500 | 500 |
| 501 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) | 501 static EphemeralRange expandEndToSentenceBoundary(const EphemeralRange& range) |
| 502 { | 502 { |
| 503 ASSERT(range.isNotNull()); | 503 DCHECK(range.isNotNull()); |
| 504 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition( )); | 504 const VisiblePosition& visibleEnd = createVisiblePosition(range.endPosition( )); |
| 505 ASSERT(visibleEnd.isNotNull()); | 505 DCHECK(visibleEnd.isNotNull()); |
| 506 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); | 506 const Position& sentenceEnd = endOfSentence(visibleEnd).deepEquivalent(); |
| 507 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente nceEnd : range.endPosition()); | 507 return EphemeralRange(range.startPosition(), sentenceEnd.isNotNull() ? sente nceEnd : range.endPosition()); |
| 508 } | 508 } |
| 509 | 509 |
| 510 static EphemeralRange expandRangeToSentenceBoundary(const EphemeralRange& range) | 510 static EphemeralRange expandRangeToSentenceBoundary(const EphemeralRange& range) |
| 511 { | 511 { |
| 512 ASSERT(range.isNotNull()); | 512 DCHECK(range.isNotNull()); |
| 513 const VisiblePosition& visibleStart = createVisiblePosition(range.startPosit ion()); | 513 const VisiblePosition& visibleStart = createVisiblePosition(range.startPosit ion()); |
| 514 ASSERT(visibleStart.isNotNull()); | 514 DCHECK(visibleStart.isNotNull()); |
| 515 const Position& sentenceStart = startOfSentence(visibleStart).deepEquivalent (); | 515 const Position& sentenceStart = startOfSentence(visibleStart).deepEquivalent (); |
| 516 return expandEndToSentenceBoundary(EphemeralRange(sentenceStart.isNull() ? r ange.startPosition() : sentenceStart, range.endPosition())); | 516 return expandEndToSentenceBoundary(EphemeralRange(sentenceStart.isNull() ? r ange.startPosition() : sentenceStart, range.endPosition())); |
| 517 } | 517 } |
| 518 | 518 |
| 519 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node, const Ep hemeralRange& insertedRange) | 519 void SpellChecker::chunkAndMarkAllMisspellingsAndBadGrammar(Node* node, const Ep hemeralRange& insertedRange) |
| 520 { | 520 { |
| 521 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r"); | 521 TRACE_EVENT0("blink", "SpellChecker::chunkAndMarkAllMisspellingsAndBadGramma r"); |
| 522 if (!node) | 522 if (!node) |
| 523 return; | 523 return; |
| 524 EphemeralRange paragraphRange(firstPositionInNode(node), lastPositionInNode( node)); | 524 EphemeralRange paragraphRange(firstPositionInNode(node), lastPositionInNode( node)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 // so comparePositions can be directly called. | 559 // so comparePositions can be directly called. |
| 560 if (comparePositions(chunkRange.endPosition(), checkRange.endPositio n()) < 0) | 560 if (comparePositions(chunkRange.endPosition(), checkRange.endPositio n()) < 0) |
| 561 checkRangeIterator.advance(TextIterator::rangeLength(chunkRange. endPosition(), checkRange.endPosition())); | 561 checkRangeIterator.advance(TextIterator::rangeLength(chunkRange. endPosition(), checkRange.endPosition())); |
| 562 } | 562 } |
| 563 } | 563 } |
| 564 } | 564 } |
| 565 | 565 |
| 566 void SpellChecker::markAndReplaceFor(RawPtr<SpellCheckRequest> request, const Ve ctor<TextCheckingResult>& results) | 566 void SpellChecker::markAndReplaceFor(RawPtr<SpellCheckRequest> request, const Ve ctor<TextCheckingResult>& results) |
| 567 { | 567 { |
| 568 TRACE_EVENT0("blink", "SpellChecker::markAndReplaceFor"); | 568 TRACE_EVENT0("blink", "SpellChecker::markAndReplaceFor"); |
| 569 ASSERT(request); | 569 DCHECK(request); |
| 570 if (!request->isValid()) | 570 if (!request->isValid()) |
| 571 return; | 571 return; |
| 572 | 572 |
| 573 TextCheckingTypeMask textCheckingOptions = request->data().mask(); | 573 TextCheckingTypeMask textCheckingOptions = request->data().mask(); |
| 574 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph Range()); | 574 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph Range()); |
| 575 | 575 |
| 576 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; | 576 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
| 577 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; | 577 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; |
| 578 | 578 |
| 579 // Expand the range to encompass entire paragraphs, since text checking need s that much context. | 579 // Expand the range to encompass entire paragraphs, since text checking need s that much context. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 602 int resultLocation = result->location + paragraph.checkingStart(); | 602 int resultLocation = result->location + paragraph.checkingStart(); |
| 603 int resultLength = result->length; | 603 int resultLength = result->length; |
| 604 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res ultLocation + resultLength == ambiguousBoundaryOffset; | 604 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res ultLocation + resultLength == ambiguousBoundaryOffset; |
| 605 | 605 |
| 606 // Only mark misspelling if: | 606 // Only mark misspelling if: |
| 607 // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false. | 607 // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false. |
| 608 // 2. Result falls within spellingRange. | 608 // 2. Result falls within spellingRange. |
| 609 // 3. The word in question doesn't end at an ambiguous boundary. For ins tance, we would not mark | 609 // 3. The word in question doesn't end at an ambiguous boundary. For ins tance, we would not mark |
| 610 // "wouldn'" as misspelled right after apostrophe is typed. | 610 // "wouldn'" as misspelled right after apostrophe is typed. |
| 611 if (shouldMarkSpelling && result->decoration == TextDecorationTypeSpelli ng && resultLocation >= paragraph.checkingStart() && resultLocation + resultLeng th <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) { | 611 if (shouldMarkSpelling && result->decoration == TextDecorationTypeSpelli ng && resultLocation >= paragraph.checkingStart() && resultLocation + resultLeng th <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) { |
| 612 ASSERT(resultLength > 0 && resultLocation >= 0); | 612 DCHECK(resultLength > 0 && resultLocation >= 0); |
| 613 const EphemeralRange misspellingRange = calculateCharacterSubrange(p aragraph.paragraphRange(), resultLocation, resultLength); | 613 const EphemeralRange misspellingRange = calculateCharacterSubrange(p aragraph.paragraphRange(), resultLocation, resultLength); |
| 614 frame().document()->markers().addMarker(misspellingRange.startPositi on(), misspellingRange.endPosition(), DocumentMarker::Spelling, result->replacem ent, result->hash); | 614 frame().document()->markers().addMarker(misspellingRange.startPositi on(), misspellingRange.endPosition(), DocumentMarker::Spelling, result->replacem ent, result->hash); |
| 615 } else if (shouldMarkGrammar && result->decoration == TextDecorationType Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) { | 615 } else if (shouldMarkGrammar && result->decoration == TextDecorationType Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) { |
| 616 ASSERT(resultLength > 0 && resultLocation >= 0); | 616 DCHECK(resultLength > 0 && resultLocation >= 0); |
|
yosin_UTC9
2016/04/11 04:09:10
Could you split this |DCHECK()| to two |DCHECK_XX(
| |
| 617 for (unsigned j = 0; j < result->details.size(); j++) { | 617 for (unsigned j = 0; j < result->details.size(); j++) { |
| 618 const GrammarDetail* detail = &result->details[j]; | 618 const GrammarDetail* detail = &result->details[j]; |
| 619 ASSERT(detail->length > 0 && detail->location >= 0); | 619 DCHECK(detail->length > 0 && detail->location >= 0); |
|
yosin_UTC9
2016/04/11 04:09:10
Could you split this |DCHECK()| to two |DCHECK_XX(
| |
| 620 if (paragraph.checkingRangeCovers(resultLocation + detail->locat ion, detail->length)) { | 620 if (paragraph.checkingRangeCovers(resultLocation + detail->locat ion, detail->length)) { |
| 621 const EphemeralRange badGrammarRange = calculateCharacterSub range(paragraph.paragraphRange(), resultLocation + detail->location, detail->len gth); | 621 const EphemeralRange badGrammarRange = calculateCharacterSub range(paragraph.paragraphRange(), resultLocation + detail->location, detail->len gth); |
| 622 frame().document()->markers().addMarker(badGrammarRange.star tPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->use rDescription, result->hash); | 622 frame().document()->markers().addMarker(badGrammarRange.star tPosition(), badGrammarRange.endPosition(), DocumentMarker::Grammar, detail->use rDescription, result->hash); |
| 623 } | 623 } |
| 624 } | 624 } |
| 625 } else if (result->decoration == TextDecorationTypeInvisibleSpellcheck & & resultLocation >= paragraph.checkingStart() && resultLocation + resultLength < = spellingRangeEndOffset) { | 625 } else if (result->decoration == TextDecorationTypeInvisibleSpellcheck & & resultLocation >= paragraph.checkingStart() && resultLocation + resultLength < = spellingRangeEndOffset) { |
| 626 ASSERT(resultLength > 0 && resultLocation >= 0); | 626 DCHECK(resultLength > 0 && resultLocation >= 0); |
|
yosin_UTC9
2016/04/11 04:09:11
Could you split this |DCHECK()| to two |DCHECK_XX(
| |
| 627 const EphemeralRange invisibleSpellcheckRange = calculateCharacterSu brange(paragraph.paragraphRange(), resultLocation, resultLength); | 627 const EphemeralRange invisibleSpellcheckRange = calculateCharacterSu brange(paragraph.paragraphRange(), resultLocation, resultLength); |
| 628 frame().document()->markers().addMarker(invisibleSpellcheckRange.sta rtPosition(), invisibleSpellcheckRange.endPosition(), DocumentMarker::InvisibleS pellcheck, result->replacement, result->hash); | 628 frame().document()->markers().addMarker(invisibleSpellcheckRange.sta rtPosition(), invisibleSpellcheckRange.endPosition(), DocumentMarker::InvisibleS pellcheck, result->replacement, result->hash); |
| 629 } | 629 } |
| 630 } | 630 } |
| 631 | 631 |
| 632 if (selectionChanged) { | 632 if (selectionChanged) { |
| 633 TextCheckingParagraph extendedParagraph(paragraph); | 633 TextCheckingParagraph extendedParagraph(paragraph); |
| 634 // Restore the caret position if we have made any replacements | 634 // Restore the caret position if we have made any replacements |
| 635 extendedParagraph.expandRangeToNextEnd(); | 635 extendedParagraph.expandRangeToNextEnd(); |
| 636 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs et <= extendedParagraph.rangeLength()) { | 636 if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffs et <= extendedParagraph.rangeLength()) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord. isNull() || endOfLastWord.isNull()) | 723 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord. isNull() || endOfLastWord.isNull()) |
| 724 return; | 724 return; |
| 725 | 725 |
| 726 // Now we remove markers on everything between startOfFirstWord and endOfLas tWord. | 726 // Now we remove markers on everything between startOfFirstWord and endOfLas tWord. |
| 727 // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the | 727 // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the |
| 728 // resulted words even we only edit one of them. For example, assuming autoc orrection changes "avantgarde" to "avant | 728 // resulted words even we only edit one of them. For example, assuming autoc orrection changes "avantgarde" to "avant |
| 729 // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde, | 729 // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde, |
| 730 // we would like to remove the marker from word "avant" and whitespace as we ll. So we need to get the continous range of | 730 // we would like to remove the marker from word "avant" and whitespace as we ll. So we need to get the continous range of |
| 731 // of marker that contains the word in question, and remove marker on that w hole range. | 731 // of marker that contains the word in question, and remove marker on that w hole range. |
| 732 Document* document = frame().document(); | 732 Document* document = frame().document(); |
| 733 ASSERT(document); | 733 DCHECK(document); |
| 734 const EphemeralRange wordRange(startOfFirstWord.deepEquivalent(), endOfLastW ord.deepEquivalent()); | 734 const EphemeralRange wordRange(startOfFirstWord.deepEquivalent(), endOfLastW ord.deepEquivalent()); |
| 735 document->markers().removeMarkers(wordRange, DocumentMarker::MisspellingMark ers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); | 735 document->markers().removeMarkers(wordRange, DocumentMarker::MisspellingMark ers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); |
| 736 } | 736 } |
| 737 | 737 |
| 738 void SpellChecker::didEndEditingOnTextField(Element* e) | 738 void SpellChecker::didEndEditingOnTextField(Element* e) |
| 739 { | 739 { |
| 740 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); | 740 TRACE_EVENT0("blink", "SpellChecker::didEndEditingOnTextField"); |
| 741 | 741 |
| 742 // Remove markers when deactivating a selection in an <input type="text"/>. | 742 // Remove markers when deactivating a selection in an <input type="text"/>. |
| 743 // Prevent new ones from appearing too. | 743 // Prevent new ones from appearing too. |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 visitor->trace(m_frame); | 944 visitor->trace(m_frame); |
| 945 visitor->trace(m_spellCheckRequester); | 945 visitor->trace(m_spellCheckRequester); |
| 946 } | 946 } |
| 947 | 947 |
| 948 void SpellChecker::prepareForLeakDetection() | 948 void SpellChecker::prepareForLeakDetection() |
| 949 { | 949 { |
| 950 m_spellCheckRequester->prepareForLeakDetection(); | 950 m_spellCheckRequester->prepareForLeakDetection(); |
| 951 } | 951 } |
| 952 | 952 |
| 953 } // namespace blink | 953 } // namespace blink |
| OLD | NEW |