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

Side by Side Diff: chrome/renderer/spellchecker/spellcheck.cc

Issue 1300213002: Offers suggestions for each language that marks a word misspelled. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@multi-spellcheck
Patch Set: Reworked the algorithm and refactored tests. Created 5 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 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/spellchecker/spellcheck.h" 5 #include "chrome/renderer/spellchecker/spellcheck.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 // report the word as correctly spelled.) 257 // report the word as correctly spelled.)
258 if (InitializeIfNeeded()) 258 if (InitializeIfNeeded())
259 return true; 259 return true;
260 260
261 // These are for holding misspelling or skippable word positions and lengths 261 // These are for holding misspelling or skippable word positions and lengths
262 // between calls to SpellcheckLanguage::SpellCheckWord. 262 // between calls to SpellcheckLanguage::SpellCheckWord.
263 int possible_misspelling_start; 263 int possible_misspelling_start;
264 int possible_misspelling_len; 264 int possible_misspelling_len;
265 // The longest sequence of text that all languages agree is skippable. 265 // The longest sequence of text that all languages agree is skippable.
266 int agreed_skippable_len; 266 int agreed_skippable_len;
267 // A vector of vectors containing spelling suggestions from different
268 // languages.
269 std::vector<std::vector<base::string16>> suggestions_list;
267 270
268 // This loop only advances if all languages agree that a sequence of text is 271 // This loop only advances if all languages agree that a sequence of text is
269 // skippable. 272 // skippable.
270 for (; position_in_text <= text_length; 273 for (; position_in_text <= text_length;
271 position_in_text += agreed_skippable_len) { 274 position_in_text += agreed_skippable_len) {
272 // Reseting |agreed_skippable_len| to the worst-case length each time 275 // Reseting |agreed_skippable_len| to the worst-case length each time
273 // prevents some unnecessary iterations. 276 // prevents some unnecessary iterations.
274 agreed_skippable_len = text_length; 277 agreed_skippable_len = text_length;
275 *misspelling_start = 0; 278 *misspelling_start = 0;
276 *misspelling_len = 0; 279 *misspelling_len = 0;
277 280 suggestions_list.clear();
278 if (optional_suggestions)
279 optional_suggestions->clear();
280 281
281 for (ScopedVector<SpellcheckLanguage>::iterator language = 282 for (ScopedVector<SpellcheckLanguage>::iterator language =
282 languages_.begin(); 283 languages_.begin();
283 language != languages_.end();) { 284 language != languages_.end();) {
285 std::vector<base::string16> language_suggestions;
284 SpellcheckLanguage::SpellcheckWordResult result = 286 SpellcheckLanguage::SpellcheckWordResult result =
285 (*language)->SpellCheckWord(text_begin, position_in_text, text_length, 287 (*language)->SpellCheckWord(
286 tag, &possible_misspelling_start, 288 text_begin, position_in_text, text_length, tag,
287 &possible_misspelling_len, 289 &possible_misspelling_start, &possible_misspelling_len,
288 optional_suggestions); 290 optional_suggestions ? &language_suggestions : nullptr);
289 291
290 switch (result) { 292 switch (result) {
291 case SpellcheckLanguage::SpellcheckWordResult::IS_CORRECT: 293 case SpellcheckLanguage::SpellcheckWordResult::IS_CORRECT:
292 *misspelling_start = 0; 294 *misspelling_start = 0;
293 *misspelling_len = 0; 295 *misspelling_len = 0;
294 return true; 296 return true;
295 case SpellcheckLanguage::SpellcheckWordResult::IS_SKIPPABLE: 297 case SpellcheckLanguage::SpellcheckWordResult::IS_SKIPPABLE:
296 agreed_skippable_len = 298 agreed_skippable_len =
297 std::min(agreed_skippable_len, possible_misspelling_len); 299 std::min(agreed_skippable_len, possible_misspelling_len);
298 // If true, this means the spellchecker moved past a word that was 300 // If true, this means the spellchecker moved past a word that was
299 // previously determined to be misspelled or skippable, which means 301 // previously determined to be misspelled or skippable, which means
300 // another spellcheck language marked it as correct. 302 // another spellcheck language marked it as correct.
301 if (position_in_text != possible_misspelling_start) { 303 if (position_in_text != possible_misspelling_start) {
302 *misspelling_len = 0; 304 *misspelling_len = 0;
303 position_in_text = possible_misspelling_start; 305 position_in_text = possible_misspelling_start;
306 if (optional_suggestions)
307 suggestions_list.clear();
please use gerrit instead 2015/08/20 18:40:23 If optional_suggestions is null, then suggestions_
Julius 2015/08/20 21:52:50 Done.
304 language = languages_.begin(); 308 language = languages_.begin();
305 } else { 309 } else {
306 language++; 310 language++;
307 } 311 }
308 break; 312 break;
309 case SpellcheckLanguage::SpellcheckWordResult::IS_MISSPELLED: 313 case SpellcheckLanguage::SpellcheckWordResult::IS_MISSPELLED:
310 *misspelling_start = possible_misspelling_start; 314 *misspelling_start = possible_misspelling_start;
311 *misspelling_len = possible_misspelling_len; 315 *misspelling_len = possible_misspelling_len;
312 // If true, this means the spellchecker moved past a word that was 316 // If true, this means the spellchecker moved past a word that was
313 // previously determined to be misspelled or skippable, which means 317 // previously determined to be misspelled or skippable, which means
314 // another spellcheck language marked it as correct. 318 // another spellcheck language marked it as correct.
315 language = position_in_text != *misspelling_start ? languages_.begin() 319 if (position_in_text != *misspelling_start) {
316 : language + 1; 320 suggestions_list.clear();
317 position_in_text = *misspelling_start; 321 language = languages_.begin();
322 position_in_text = *misspelling_start;
323 } else {
324 // Only add the language's suggestions if this is not a newly
325 // determined misspelling. This prevents adding a list of
326 // suggestions twice.
please use gerrit instead 2015/08/20 18:40:23 I don't think this comment explains much, although
Julius 2015/08/20 21:52:50 Done.
327 if (optional_suggestions)
please use gerrit instead 2015/08/20 18:40:23 Remove the if. Just push_back.
Julius 2015/08/20 21:52:50 Done.
328 suggestions_list.push_back(language_suggestions);
329 language++;
330 }
318 break; 331 break;
319 } 332 }
320 } 333 }
321 334
322 // If |*misspelling_len| is non-zero, that means at least one language 335 // If |*misspelling_len| is non-zero, that means at least one language
323 // marked a word misspelled and no other language considered it correct. 336 // marked a word misspelled and no other language considered it correct.
324 if (*misspelling_len != 0) 337 if (*misspelling_len != 0) {
338 FillSuggestions(suggestions_list, optional_suggestions);
325 return false; 339 return false;
340 }
326 } 341 }
327 342
328 NOTREACHED(); 343 NOTREACHED();
329 return true; 344 return true;
330 } 345 }
331 346
347 void SpellCheck::FillSuggestions(
please use gerrit instead 2015/08/20 18:40:23 Your function does nothing if |optional_suggestion
Julius 2015/08/20 21:52:51 Done.
348 std::vector<std::vector<base::string16>>& suggestions_list,
349 std::vector<base::string16>* optional_suggestions) {
350 if (!optional_suggestions)
351 return;
352
353 // A vector containing the indices of the current suggestion for each
354 // language's suggestion list.
355 std::vector<size_t> indices(suggestions_list.size(), 0);
356 // Take one suggestion at a time from each language's suggestions and add it
357 // to |optional_suggestions|.
358 for (size_t i = 0, num_empty = 0;
359 num_empty < suggestions_list.size() &&
360 optional_suggestions->size() <
361 chrome::spellcheck_common::kMaxSuggestions;
362 i = (i + 1) % suggestions_list.size()) {
363 if (indices[i] < suggestions_list[i].size()) {
364 base::string16 suggestion = suggestions_list[i][indices[i]];
please use gerrit instead 2015/08/20 18:40:23 Avoid copying |suggestion| by making it const-ref.
Julius 2015/08/20 21:52:51 Done.
365 // Only add the suggestion if it's unique.
366 if (std::find_if(optional_suggestions->begin(),
please use gerrit instead 2015/08/20 18:40:23 You don't need a lambda and std::find_if. Use std:
Julius 2015/08/20 21:52:51 Wow, duh.
367 optional_suggestions->end(),
368 [&suggestion](base::string16 word) {
369 return word == suggestion;
370 }) == optional_suggestions->end()) {
371 optional_suggestions->push_back(suggestion);
372 }
373 indices[i]++;
374 if (indices[i] == suggestions_list[i].size())
please use gerrit instead 2015/08/20 18:40:23 You can reduce lines 373-374 into a single line:
Julius 2015/08/20 21:52:50 Done.
375 num_empty++;
376 }
377 }
378 }
379
332 bool SpellCheck::SpellCheckParagraph( 380 bool SpellCheck::SpellCheckParagraph(
333 const base::string16& text, 381 const base::string16& text,
334 WebVector<WebTextCheckingResult>* results) { 382 WebVector<WebTextCheckingResult>* results) {
335 #if !defined(USE_BROWSER_SPELLCHECKER) 383 #if !defined(USE_BROWSER_SPELLCHECKER)
336 // Mac and Android have their own spell checkers,so this method won't be used 384 // Mac and Android have their own spell checkers,so this method won't be used
337 DCHECK(results); 385 DCHECK(results);
338 std::vector<WebTextCheckingResult> textcheck_results; 386 std::vector<WebTextCheckingResult> textcheck_results;
339 size_t length = text.length(); 387 size_t length = text.length();
340 size_t position_in_text = 0; 388 size_t position_in_text = 0;
341 389
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 601
554 bool SpellCheck::IsSpellcheckEnabled() { 602 bool SpellCheck::IsSpellcheckEnabled() {
555 #if defined(OS_ANDROID) 603 #if defined(OS_ANDROID)
556 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 604 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
557 switches::kEnableAndroidSpellChecker)) { 605 switches::kEnableAndroidSpellChecker)) {
558 return false; 606 return false;
559 } 607 }
560 #endif 608 #endif
561 return spellcheck_enabled_; 609 return spellcheck_enabled_;
562 } 610 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698