| 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 244 |
| 245 if (spellingSearchStart == spellingSearchEnd) | 245 if (spellingSearchStart == spellingSearchEnd) |
| 246 return; // nothing to search in | 246 return; // nothing to search in |
| 247 | 247 |
| 248 // We go to the end of our first range instead of the start of it, just to b
e sure | 248 // We go to the end of our first range instead of the start of it, just to b
e sure |
| 249 // we don't get foiled by any word boundary problems at the start. It means
we might | 249 // we don't get foiled by any word boundary problems at the start. It means
we might |
| 250 // do a tiny bit more searching. | 250 // do a tiny bit more searching. |
| 251 Node* searchEndNodeAfterWrap = spellingSearchEnd.computeContainerNode(); | 251 Node* searchEndNodeAfterWrap = spellingSearchEnd.computeContainerNode(); |
| 252 int searchEndOffsetAfterWrap = spellingSearchEnd.offsetInContainerNode(); | 252 int searchEndOffsetAfterWrap = spellingSearchEnd.offsetInContainerNode(); |
| 253 | 253 |
| 254 int misspellingOffset = 0; | 254 std::pair<String, int> misspelledItem(String(), 0); |
| 255 String misspelledWord = findFirstMisspellingOrBadGrammar(spellingSearchStart
, spellingSearchEnd, misspellingOffset); | 255 String& misspelledWord = misspelledItem.first; |
| 256 int& misspellingOffset = misspelledItem.second; |
| 257 misspelledItem = findFirstMisspelling(spellingSearchStart, spellingSearchEnd
); |
| 256 | 258 |
| 257 // If we did not find a misspelled word, wrap and try again (but don't bothe
r if we started at the beginning of the | 259 // If we did not find a misspelled word, wrap and try again (but don't bothe
r if we started at the beginning of the |
| 258 // block rather than at a selection). | 260 // block rather than at a selection). |
| 259 if (startedWithSelection && !misspelledWord) { | 261 if (startedWithSelection && !misspelledWord) { |
| 260 spellingSearchStart = Position::editingPositionOf(topNode, 0); | 262 spellingSearchStart = Position::editingPositionOf(topNode, 0); |
| 261 // going until the end of the very first chunk we tested is far enough | 263 // going until the end of the very first chunk we tested is far enough |
| 262 spellingSearchEnd = Position::editingPositionOf(searchEndNodeAfterWrap,
searchEndOffsetAfterWrap); | 264 spellingSearchEnd = Position::editingPositionOf(searchEndNodeAfterWrap,
searchEndOffsetAfterWrap); |
| 263 misspelledWord = findFirstMisspellingOrBadGrammar(spellingSearchStart, s
pellingSearchEnd, misspellingOffset); | 265 misspelledItem = findFirstMisspelling(spellingSearchStart, spellingSearc
hEnd); |
| 264 } | 266 } |
| 265 | 267 |
| 266 if (!misspelledWord.isEmpty()) { | 268 if (!misspelledWord.isEmpty()) { |
| 267 // We found a misspelling. Select the misspelling, update the spelling p
anel, and store | 269 // We found a misspelling. Select the misspelling, update the spelling p
anel, and store |
| 268 // a marker so we draw the red squiggle later. | 270 // a marker so we draw the red squiggle later. |
| 269 | 271 |
| 270 const EphemeralRange misspellingRange = calculateCharacterSubrange(Ephem
eralRange(spellingSearchStart, spellingSearchEnd), misspellingOffset, misspelled
Word.length()); | 272 const EphemeralRange misspellingRange = calculateCharacterSubrange(Ephem
eralRange(spellingSearchStart, spellingSearchEnd), misspellingOffset, misspelled
Word.length()); |
| 271 frame().selection().setSelection(VisibleSelection(misspellingRange)); | 273 frame().selection().setSelection(VisibleSelection(misspellingRange)); |
| 272 frame().selection().revealSelection(); | 274 frame().selection().revealSelection(); |
| 273 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); | 275 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 { | 782 { |
| 781 visitor->trace(m_frame); | 783 visitor->trace(m_frame); |
| 782 visitor->trace(m_spellCheckRequester); | 784 visitor->trace(m_spellCheckRequester); |
| 783 } | 785 } |
| 784 | 786 |
| 785 void SpellChecker::prepareForLeakDetection() | 787 void SpellChecker::prepareForLeakDetection() |
| 786 { | 788 { |
| 787 m_spellCheckRequester->prepareForLeakDetection(); | 789 m_spellCheckRequester->prepareForLeakDetection(); |
| 788 } | 790 } |
| 789 | 791 |
| 790 void SpellChecker::findMisspellings(const String& text, Vector<TextCheckingResul
t>& results) | 792 Vector<TextCheckingResult> SpellChecker::findMisspellings(const String& text) |
| 791 { | 793 { |
| 792 Vector<UChar> characters; | 794 Vector<UChar> characters; |
| 793 text.appendTo(characters); | 795 text.appendTo(characters); |
| 794 unsigned length = text.length(); | 796 unsigned length = text.length(); |
| 795 | 797 |
| 796 TextBreakIterator* iterator = wordBreakIterator(characters.data(), length); | 798 TextBreakIterator* iterator = wordBreakIterator(characters.data(), length); |
| 797 if (!iterator) | 799 if (!iterator) |
| 798 return; | 800 return Vector<TextCheckingResult>(); |
| 799 | 801 |
| 802 Vector<TextCheckingResult> results; |
| 800 int wordStart = iterator->current(); | 803 int wordStart = iterator->current(); |
| 801 while (0 <= wordStart) { | 804 while (wordStart >= 0) { |
| 802 int wordEnd = iterator->next(); | 805 int wordEnd = iterator->next(); |
| 803 if (wordEnd < 0) | 806 if (wordEnd < 0) |
| 804 break; | 807 break; |
| 805 int wordLength = wordEnd - wordStart; | 808 int wordLength = wordEnd - wordStart; |
| 806 int misspellingLocation = -1; | 809 int misspellingLocation = -1; |
| 807 int misspellingLength = 0; | 810 int misspellingLength = 0; |
| 808 textChecker().checkSpellingOfString(String(characters.data() + wordStart
, wordLength), &misspellingLocation, &misspellingLength); | 811 textChecker().checkSpellingOfString(String(characters.data() + wordStart
, wordLength), &misspellingLocation, &misspellingLength); |
| 809 if (0 < misspellingLength) { | 812 if (misspellingLength > 0) { |
| 810 DCHECK_LE(0, misspellingLocation); | 813 DCHECK_GE(misspellingLocation, 0); |
| 811 DCHECK_LE(misspellingLocation, wordLength); | |
| 812 DCHECK_LT(0, misspellingLength); | |
| 813 DCHECK_LE(misspellingLocation + misspellingLength, wordLength); | 814 DCHECK_LE(misspellingLocation + misspellingLength, wordLength); |
| 814 TextCheckingResult misspelling; | 815 TextCheckingResult misspelling; |
| 815 misspelling.decoration = TextDecorationTypeSpelling; | 816 misspelling.decoration = TextDecorationTypeSpelling; |
| 816 misspelling.location = wordStart + misspellingLocation; | 817 misspelling.location = wordStart + misspellingLocation; |
| 817 misspelling.length = misspellingLength; | 818 misspelling.length = misspellingLength; |
| 818 results.append(misspelling); | 819 results.append(misspelling); |
| 819 } | 820 } |
| 820 | |
| 821 wordStart = wordEnd; | 821 wordStart = wordEnd; |
| 822 } | 822 } |
| 823 return results; |
| 823 } | 824 } |
| 824 | 825 |
| 825 String SpellChecker::findFirstMisspellingOrBadGrammar(const Position& start, con
st Position& end, int& outFirstFoundOffset) | 826 std::pair<String, int> SpellChecker::findFirstMisspelling(const Position& start,
const Position& end) |
| 826 { | 827 { |
| 827 String firstFoundItem; | |
| 828 String misspelledWord; | 828 String misspelledWord; |
| 829 | 829 |
| 830 // Initialize out parameter; it will be updated if we find something to retu
rn. | 830 // Initialize out parameters; they will be updated if we find something to r
eturn. |
| 831 outFirstFoundOffset = 0; | 831 String firstFoundItem; |
| 832 int firstFoundOffset = 0; |
| 832 | 833 |
| 833 // Expand the search range to encompass entire paragraphs, since text checki
ng needs that much context. | 834 // Expand the search range to encompass entire paragraphs, since text checki
ng needs that much context. |
| 834 // Determine the character offset from the start of the paragraph to the sta
rt of the original search range, | 835 // Determine the character offset from the start of the paragraph to the sta
rt of the original search range, |
| 835 // since we will want to ignore results in this area. | 836 // since we will want to ignore results in this area. |
| 836 Position paragraphStart = startOfParagraph(createVisiblePosition(start)).toP
arentAnchoredPosition(); | 837 Position paragraphStart = startOfParagraph(createVisiblePosition(start)).toP
arentAnchoredPosition(); |
| 837 Position paragraphEnd = end; | 838 Position paragraphEnd = end; |
| 838 int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEn
d); | 839 int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEn
d); |
| 839 paragraphEnd = endOfParagraph(createVisiblePosition(start)).toParentAnchored
Position(); | 840 paragraphEnd = endOfParagraph(createVisiblePosition(start)).toParentAnchored
Position(); |
| 840 | 841 |
| 841 int rangeStartOffset = TextIterator::rangeLength(paragraphStart, start); | 842 int rangeStartOffset = TextIterator::rangeLength(paragraphStart, start); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 852 // Determine the character offset from the end of the original searc
h range to the end of the paragraph, | 853 // Determine the character offset from the end of the original searc
h range to the end of the paragraph, |
| 853 // since we will want to ignore results in this area. | 854 // since we will want to ignore results in this area. |
| 854 currentEndOffset = TextIterator::rangeLength(paragraphStart, end); | 855 currentEndOffset = TextIterator::rangeLength(paragraphStart, end); |
| 855 lastIteration = true; | 856 lastIteration = true; |
| 856 } | 857 } |
| 857 if (currentStartOffset < currentEndOffset) { | 858 if (currentStartOffset < currentEndOffset) { |
| 858 String paragraphString = plainText(EphemeralRange(paragraphStart, pa
ragraphEnd)); | 859 String paragraphString = plainText(EphemeralRange(paragraphStart, pa
ragraphEnd)); |
| 859 if (paragraphString.length() > 0) { | 860 if (paragraphString.length() > 0) { |
| 860 int spellingLocation = 0; | 861 int spellingLocation = 0; |
| 861 | 862 |
| 862 Vector<TextCheckingResult> results; | 863 Vector<TextCheckingResult> results = findMisspellings(paragraphS
tring); |
| 863 findMisspellings(paragraphString, results); | |
| 864 | 864 |
| 865 for (unsigned i = 0; i < results.size(); i++) { | 865 for (unsigned i = 0; i < results.size(); i++) { |
| 866 const TextCheckingResult* result = &results[i]; | 866 const TextCheckingResult* result = &results[i]; |
| 867 if (result->decoration == TextDecorationTypeSpelling && resu
lt->location >= currentStartOffset && result->location + result->length <= curre
ntEndOffset) { | 867 if (result->location >= currentStartOffset && result->locati
on + result->length <= currentEndOffset) { |
| 868 DCHECK_GT(result->length, 0); | 868 DCHECK_GT(result->length, 0); |
| 869 DCHECK_GE(result->location, 0); | 869 DCHECK_GE(result->location, 0); |
| 870 spellingLocation = result->location; | 870 spellingLocation = result->location; |
| 871 misspelledWord = paragraphString.substring(result->locat
ion, result->length); | 871 misspelledWord = paragraphString.substring(result->locat
ion, result->length); |
| 872 DCHECK(misspelledWord.length()); | 872 DCHECK(misspelledWord.length()); |
| 873 break; | 873 break; |
| 874 } | 874 } |
| 875 } | 875 } |
| 876 | 876 |
| 877 if (!misspelledWord.isEmpty()) { | 877 if (!misspelledWord.isEmpty()) { |
| 878 int spellingOffset = spellingLocation - currentStartOffset; | 878 int spellingOffset = spellingLocation - currentStartOffset; |
| 879 if (!firstIteration) | 879 if (!firstIteration) |
| 880 spellingOffset += TextIterator::rangeLength(start, parag
raphStart); | 880 spellingOffset += TextIterator::rangeLength(start, parag
raphStart); |
| 881 outFirstFoundOffset = spellingOffset; | 881 firstFoundOffset = spellingOffset; |
| 882 firstFoundItem = misspelledWord; | 882 firstFoundItem = misspelledWord; |
| 883 break; | 883 break; |
| 884 } | 884 } |
| 885 } | 885 } |
| 886 } | 886 } |
| 887 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL
ength) | 887 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL
ength) |
| 888 break; | 888 break; |
| 889 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); | 889 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); |
| 890 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | 890 paragraphStart = newParagraphStart.toParentAnchoredPosition(); |
| 891 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); | 891 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); |
| 892 firstIteration = false; | 892 firstIteration = false; |
| 893 totalLengthProcessed += currentLength; | 893 totalLengthProcessed += currentLength; |
| 894 } | 894 } |
| 895 return firstFoundItem; | 895 return std::make_pair(firstFoundItem, firstFoundOffset); |
| 896 } | 896 } |
| 897 | 897 |
| 898 } // namespace blink | 898 } // namespace blink |
| OLD | NEW |