Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp

Issue 2247003005: Eliminate class TextCheckingHelper (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@CleanupUnifiedTextChecker
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 21 matching lines...) Expand all
32 #include "core/dom/Element.h" 32 #include "core/dom/Element.h"
33 #include "core/dom/ElementTraversal.h" 33 #include "core/dom/ElementTraversal.h"
34 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
35 #include "core/editing/EditingUtilities.h" 35 #include "core/editing/EditingUtilities.h"
36 #include "core/editing/Editor.h" 36 #include "core/editing/Editor.h"
37 #include "core/editing/EphemeralRange.h" 37 #include "core/editing/EphemeralRange.h"
38 #include "core/editing/VisibleUnits.h" 38 #include "core/editing/VisibleUnits.h"
39 #include "core/editing/iterators/CharacterIterator.h" 39 #include "core/editing/iterators/CharacterIterator.h"
40 #include "core/editing/markers/DocumentMarkerController.h" 40 #include "core/editing/markers/DocumentMarkerController.h"
41 #include "core/editing/spellcheck/SpellCheckRequester.h" 41 #include "core/editing/spellcheck/SpellCheckRequester.h"
42 #include "core/editing/spellcheck/TextCheckingHelper.h" 42 #include "core/editing/spellcheck/TextCheckingParagraph.h"
43 #include "core/frame/LocalFrame.h" 43 #include "core/frame/LocalFrame.h"
44 #include "core/frame/Settings.h" 44 #include "core/frame/Settings.h"
45 #include "core/html/HTMLInputElement.h" 45 #include "core/html/HTMLInputElement.h"
46 #include "core/layout/LayoutTextControl.h" 46 #include "core/layout/LayoutTextControl.h"
47 #include "core/loader/EmptyClients.h" 47 #include "core/loader/EmptyClients.h"
48 #include "core/page/Page.h" 48 #include "core/page/Page.h"
49 #include "core/page/SpellCheckerClient.h" 49 #include "core/page/SpellCheckerClient.h"
50 #include "platform/text/TextBreakIterator.h"
50 #include "platform/text/TextCheckerClient.h" 51 #include "platform/text/TextCheckerClient.h"
51 52
52 namespace blink { 53 namespace blink {
53 54
54 using namespace HTMLNames; 55 using namespace HTMLNames;
55 56
56 namespace { 57 namespace {
57 58
58 bool isSelectionInTextField(const VisibleSelection& selection) 59 bool isSelectionInTextField(const VisibleSelection& selection)
59 { 60 {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 if (!isTextField) 151 if (!isTextField)
151 parent->setAlreadySpellChecked(true); 152 parent->setAlreadySpellChecked(true);
152 } 153 }
153 } 154 }
154 155
155 void SpellChecker::ignoreSpelling() 156 void SpellChecker::ignoreSpelling()
156 { 157 {
157 removeMarkers(frame().selection().selection(), DocumentMarker::Spelling); 158 removeMarkers(frame().selection().selection(), DocumentMarker::Spelling);
158 } 159 }
159 160
161 void SpellChecker::findMisspellings(const String& text, Vector<TextCheckingResul t>* results)
yosin_UTC9 2016/08/16 06:04:06 Since WTF::Vector is now movable[1], let's return
Xiaocheng 2016/08/16 06:21:35 Didn't know that. Done.
162 {
163 Vector<UChar> characters;
164 text.appendTo(characters);
165 unsigned length = text.length();
166
167 TextBreakIterator* iterator = wordBreakIterator(characters.data(), length);
168 if (!iterator)
169 return;
170
171 int wordStart = iterator->current();
172 while (0 <= wordStart) {
173 int wordEnd = iterator->next();
174 if (wordEnd < 0)
175 break;
176 int wordLength = wordEnd - wordStart;
177 int misspellingLocation = -1;
178 int misspellingLength = 0;
179 textChecker().checkSpellingOfString(String(characters.data() + wordStart , wordLength), &misspellingLocation, &misspellingLength);
180 if (0 < misspellingLength) {
yosin_UTC9 2016/08/16 06:04:06 I prefer |misspellingLength > 0|
Xiaocheng 2016/08/16 06:21:36 Done.
181 DCHECK_LE(0, misspellingLocation);
yosin_UTC9 2016/08/16 06:04:06 I prefer DCHECK_GE(misspellingLocation, 0);
Xiaocheng 2016/08/16 06:21:35 Done.
182 DCHECK_LE(misspellingLocation, wordLength);
183 DCHECK_LT(0, misspellingLength);
yosin_UTC9 2016/08/16 06:04:06 I prefer DCHECK_GT(misspellingLength, 0)
Xiaocheng 2016/08/16 06:21:35 Done.
184 DCHECK_LE(misspellingLocation + misspellingLength, wordLength);
185 TextCheckingResult misspelling;
186 misspelling.decoration = TextDecorationTypeSpelling;
187 misspelling.location = wordStart + misspellingLocation;
188 misspelling.length = misspellingLength;
189 results->append(misspelling);
190 }
191
yosin_UTC9 2016/08/16 06:04:06 nit: Please remove an extra blank line.
Xiaocheng 2016/08/16 06:21:36 Done.
192 wordStart = wordEnd;
193 }
194 }
195
196 std::pair<String, int> SpellChecker::findFirstMisspelling(const Position& start, const Position& end)
197 {
198 String misspelledWord;
199
200 // Initialize out parameter; it will be updated if we find something to retu rn.
201 String firstFoundItem;
202 int firstFoundOffset = 0;
203
204 // Expand the search range to encompass entire paragraphs, since text checki ng needs that much context.
205 // Determine the character offset from the start of the paragraph to the sta rt of the original search range,
206 // since we will want to ignore results in this area.
207 Position paragraphStart = startOfParagraph(createVisiblePosition(start)).toP arentAnchoredPosition();
208 Position paragraphEnd = end;
209 int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEn d);
210 paragraphEnd = endOfParagraph(createVisiblePosition(start)).toParentAnchored Position();
211
212 int rangeStartOffset = TextIterator::rangeLength(paragraphStart, start);
213 int totalLengthProcessed = 0;
214
215 bool firstIteration = true;
216 bool lastIteration = false;
217 while (totalLengthProcessed < totalRangeLength) {
218 // Iterate through the search range by paragraphs, checking each one for spelling.
219 int currentLength = TextIterator::rangeLength(paragraphStart, paragraphE nd);
220 int currentStartOffset = firstIteration ? rangeStartOffset : 0;
221 int currentEndOffset = currentLength;
222 if (inSameParagraph(createVisiblePosition(paragraphStart), createVisible Position(end))) {
223 // Determine the character offset from the end of the original searc h range to the end of the paragraph,
224 // since we will want to ignore results in this area.
225 currentEndOffset = TextIterator::rangeLength(paragraphStart, end);
226 lastIteration = true;
227 }
228 if (currentStartOffset < currentEndOffset) {
229 String paragraphString = plainText(EphemeralRange(paragraphStart, pa ragraphEnd));
230 if (paragraphString.length() > 0) {
231 int spellingLocation = 0;
232
233 Vector<TextCheckingResult> results;
234 findMisspellings(paragraphString, &results);
235
236 for (unsigned i = 0; i < results.size(); i++) {
237 const TextCheckingResult* result = &results[i];
238 if (result->decoration == TextDecorationTypeSpelling && resu lt->location >= currentStartOffset && result->location + result->length <= curre ntEndOffset) {
239 DCHECK_GT(result->length, 0);
240 DCHECK_GE(result->location, 0);
241 spellingLocation = result->location;
242 misspelledWord = paragraphString.substring(result->locat ion, result->length);
243 DCHECK(misspelledWord.length());
244 break;
245 }
246 }
247
248 if (!misspelledWord.isEmpty()) {
249 int spellingOffset = spellingLocation - currentStartOffset;
250 if (!firstIteration)
251 spellingOffset += TextIterator::rangeLength(start, parag raphStart);
252 firstFoundOffset = spellingOffset;
253 firstFoundItem = misspelledWord;
254 break;
255 }
256 }
257 }
258 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL ength)
259 break;
260 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo sition(paragraphEnd));
261 paragraphStart = newParagraphStart.toParentAnchoredPosition();
262 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio n();
263 firstIteration = false;
264 totalLengthProcessed += currentLength;
265 }
266 return std::make_pair(firstFoundItem, firstFoundOffset);
267 }
268
160 void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) 269 void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection)
161 { 270 {
162 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle()); 271 DocumentLifecycle::DisallowTransitionScope(frame().document()->lifecycle());
163 272
164 // The basic approach is to search in two phases - from the selection end to the end of the doc, and 273 // The basic approach is to search in two phases - from the selection end to the end of the doc, and
165 // then we wrap and search from the doc start to (approximately) where we st arted. 274 // then we wrap and search from the doc start to (approximately) where we st arted.
166 275
167 // Start at the end of the selection, search to edge of document. Starting a t the selection end makes 276 // Start at the end of the selection, search to edge of document. Starting a t the selection end makes
168 // repeated "check spelling" commands work. 277 // repeated "check spelling" commands work.
169 VisibleSelection selection(frame().selection().selection()); 278 VisibleSelection selection(frame().selection().selection());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 328
220 if (spellingSearchStart == spellingSearchEnd) 329 if (spellingSearchStart == spellingSearchEnd)
221 return; // nothing to search in 330 return; // nothing to search in
222 331
223 // We go to the end of our first range instead of the start of it, just to b e sure 332 // We go to the end of our first range instead of the start of it, just to b e sure
224 // we don't get foiled by any word boundary problems at the start. It means we might 333 // we don't get foiled by any word boundary problems at the start. It means we might
225 // do a tiny bit more searching. 334 // do a tiny bit more searching.
226 Node* searchEndNodeAfterWrap = spellingSearchEnd.computeContainerNode(); 335 Node* searchEndNodeAfterWrap = spellingSearchEnd.computeContainerNode();
227 int searchEndOffsetAfterWrap = spellingSearchEnd.offsetInContainerNode(); 336 int searchEndOffsetAfterWrap = spellingSearchEnd.offsetInContainerNode();
228 337
229 int misspellingOffset = 0; 338 std::pair<String, int> misspelledItem("", 0);
230 String misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSea rchStart, spellingSearchEnd).findFirstMisspellingOrBadGrammar(misspellingOffset) ; 339 String& misspelledWord = misspelledItem.first;
340 int& misspellingOffset = misspelledItem.second;
341 misspelledItem = findFirstMisspelling(spellingSearchStart, spellingSearchEnd );
231 342
232 // 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 343 // 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
233 // block rather than at a selection). 344 // block rather than at a selection).
234 if (startedWithSelection && !misspelledWord) { 345 if (startedWithSelection && !misspelledWord) {
235 spellingSearchStart = Position::editingPositionOf(topNode, 0); 346 spellingSearchStart = Position::editingPositionOf(topNode, 0);
236 // going until the end of the very first chunk we tested is far enough 347 // going until the end of the very first chunk we tested is far enough
237 spellingSearchEnd = Position::editingPositionOf(searchEndNodeAfterWrap, searchEndOffsetAfterWrap); 348 spellingSearchEnd = Position::editingPositionOf(searchEndNodeAfterWrap, searchEndOffsetAfterWrap);
238 misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearch Start, spellingSearchEnd).findFirstMisspellingOrBadGrammar(misspellingOffset); 349 misspelledItem = findFirstMisspelling(spellingSearchStart, spellingSearc hEnd);
239 } 350 }
240 351
241 if (!misspelledWord.isEmpty()) { 352 if (!misspelledWord.isEmpty()) {
242 // We found a misspelling. Select the misspelling, update the spelling p anel, and store 353 // We found a misspelling. Select the misspelling, update the spelling p anel, and store
243 // a marker so we draw the red squiggle later. 354 // a marker so we draw the red squiggle later.
244 355
245 const EphemeralRange misspellingRange = calculateCharacterSubrange(Ephem eralRange(spellingSearchStart, spellingSearchEnd), misspellingOffset, misspelled Word.length()); 356 const EphemeralRange misspellingRange = calculateCharacterSubrange(Ephem eralRange(spellingSearchStart, spellingSearchEnd), misspellingOffset, misspelled Word.length());
246 frame().selection().setSelection(VisibleSelection(misspellingRange)); 357 frame().selection().setSelection(VisibleSelection(misspellingRange));
247 frame().selection().revealSelection(); 358 frame().selection().revealSelection();
248 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord); 359 spellCheckerClient().updateSpellingUIWithMisspelledWord(misspelledWord);
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 visitor->trace(m_frame); 901 visitor->trace(m_frame);
791 visitor->trace(m_spellCheckRequester); 902 visitor->trace(m_spellCheckRequester);
792 } 903 }
793 904
794 void SpellChecker::prepareForLeakDetection() 905 void SpellChecker::prepareForLeakDetection()
795 { 906 {
796 m_spellCheckRequester->prepareForLeakDetection(); 907 m_spellCheckRequester->prepareForLeakDetection();
797 } 908 }
798 909
799 } // namespace blink 910 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698