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

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: Fixed final nits. 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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 // values. 165 // values.
166 // TODO(groby): Simplify this. 166 // TODO(groby): Simplify this.
167 SpellCheck::SpellCheck() 167 SpellCheck::SpellCheck()
168 : auto_spell_correct_turned_on_(false), 168 : auto_spell_correct_turned_on_(false),
169 spellcheck_enabled_(true) { 169 spellcheck_enabled_(true) {
170 } 170 }
171 171
172 SpellCheck::~SpellCheck() { 172 SpellCheck::~SpellCheck() {
173 } 173 }
174 174
175 void SpellCheck::FillSuggestions(
176 const std::vector<std::vector<base::string16>>& suggestions_list,
177 std::vector<base::string16>* optional_suggestions) {
178 // A vector containing the indices of the current suggestion for each
179 // language's suggestion list.
180 std::vector<size_t> indices(suggestions_list.size(), 0);
181 // Take one suggestion at a time from each language's suggestions and add it
182 // to |optional_suggestions|.
183 for (size_t i = 0, num_empty = 0;
184 num_empty < suggestions_list.size() &&
185 optional_suggestions->size() <
186 chrome::spellcheck_common::kMaxSuggestions;
187 i = (i + 1) % suggestions_list.size()) {
188 if (indices[i] < suggestions_list[i].size()) {
189 const base::string16& suggestion = suggestions_list[i][indices[i]];
190 // Only add the suggestion if it's unique.
191 if (std::find(optional_suggestions->begin(), optional_suggestions->end(),
192 suggestion) == optional_suggestions->end()) {
193 optional_suggestions->push_back(suggestion);
194 }
195 if (++indices[i] == suggestions_list[i].size())
196 num_empty++;
197 }
198 }
199 }
200
175 bool SpellCheck::OnControlMessageReceived(const IPC::Message& message) { 201 bool SpellCheck::OnControlMessageReceived(const IPC::Message& message) {
176 bool handled = true; 202 bool handled = true;
177 IPC_BEGIN_MESSAGE_MAP(SpellCheck, message) 203 IPC_BEGIN_MESSAGE_MAP(SpellCheck, message)
178 IPC_MESSAGE_HANDLER(SpellCheckMsg_Init, OnInit) 204 IPC_MESSAGE_HANDLER(SpellCheckMsg_Init, OnInit)
179 IPC_MESSAGE_HANDLER(SpellCheckMsg_CustomDictionaryChanged, 205 IPC_MESSAGE_HANDLER(SpellCheckMsg_CustomDictionaryChanged,
180 OnCustomDictionaryChanged) 206 OnCustomDictionaryChanged)
181 IPC_MESSAGE_HANDLER(SpellCheckMsg_EnableAutoSpellCorrect, 207 IPC_MESSAGE_HANDLER(SpellCheckMsg_EnableAutoSpellCorrect,
182 OnEnableAutoSpellCorrect) 208 OnEnableAutoSpellCorrect)
183 IPC_MESSAGE_HANDLER(SpellCheckMsg_EnableSpellCheck, OnEnableSpellCheck) 209 IPC_MESSAGE_HANDLER(SpellCheckMsg_EnableSpellCheck, OnEnableSpellCheck)
184 IPC_MESSAGE_HANDLER(SpellCheckMsg_RequestDocumentMarkers, 210 IPC_MESSAGE_HANDLER(SpellCheckMsg_RequestDocumentMarkers,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 // report the word as correctly spelled.) 283 // report the word as correctly spelled.)
258 if (InitializeIfNeeded()) 284 if (InitializeIfNeeded())
259 return true; 285 return true;
260 286
261 // These are for holding misspelling or skippable word positions and lengths 287 // These are for holding misspelling or skippable word positions and lengths
262 // between calls to SpellcheckLanguage::SpellCheckWord. 288 // between calls to SpellcheckLanguage::SpellCheckWord.
263 int possible_misspelling_start; 289 int possible_misspelling_start;
264 int possible_misspelling_len; 290 int possible_misspelling_len;
265 // The longest sequence of text that all languages agree is skippable. 291 // The longest sequence of text that all languages agree is skippable.
266 int agreed_skippable_len; 292 int agreed_skippable_len;
293 // A vector of vectors containing spelling suggestions from different
294 // languages.
295 std::vector<std::vector<base::string16>> suggestions_list;
296 // A vector to hold a language's misspelling suggestions between spellcheck
297 // calls.
298 std::vector<base::string16> language_suggestions;
267 299
268 // This loop only advances if all languages agree that a sequence of text is 300 // This loop only advances if all languages agree that a sequence of text is
269 // skippable. 301 // skippable.
270 for (; position_in_text <= text_length; 302 for (; position_in_text <= text_length;
271 position_in_text += agreed_skippable_len) { 303 position_in_text += agreed_skippable_len) {
272 // Reseting |agreed_skippable_len| to the worst-case length each time 304 // Reseting |agreed_skippable_len| to the worst-case length each time
273 // prevents some unnecessary iterations. 305 // prevents some unnecessary iterations.
274 agreed_skippable_len = text_length; 306 agreed_skippable_len = text_length;
275 *misspelling_start = 0; 307 *misspelling_start = 0;
276 *misspelling_len = 0; 308 *misspelling_len = 0;
277 309 suggestions_list.clear();
278 if (optional_suggestions)
279 optional_suggestions->clear();
280 310
281 for (ScopedVector<SpellcheckLanguage>::iterator language = 311 for (ScopedVector<SpellcheckLanguage>::iterator language =
282 languages_.begin(); 312 languages_.begin();
283 language != languages_.end();) { 313 language != languages_.end();) {
314 language_suggestions.clear();
284 SpellcheckLanguage::SpellcheckWordResult result = 315 SpellcheckLanguage::SpellcheckWordResult result =
285 (*language)->SpellCheckWord(text_begin, position_in_text, text_length, 316 (*language)->SpellCheckWord(
286 tag, &possible_misspelling_start, 317 text_begin, position_in_text, text_length, tag,
287 &possible_misspelling_len, 318 &possible_misspelling_start, &possible_misspelling_len,
288 optional_suggestions); 319 optional_suggestions ? &language_suggestions : nullptr);
289 320
290 switch (result) { 321 switch (result) {
291 case SpellcheckLanguage::SpellcheckWordResult::IS_CORRECT: 322 case SpellcheckLanguage::SpellcheckWordResult::IS_CORRECT:
292 *misspelling_start = 0; 323 *misspelling_start = 0;
293 *misspelling_len = 0; 324 *misspelling_len = 0;
294 return true; 325 return true;
295 case SpellcheckLanguage::SpellcheckWordResult::IS_SKIPPABLE: 326 case SpellcheckLanguage::SpellcheckWordResult::IS_SKIPPABLE:
296 agreed_skippable_len = 327 agreed_skippable_len =
297 std::min(agreed_skippable_len, possible_misspelling_len); 328 std::min(agreed_skippable_len, possible_misspelling_len);
298 // If true, this means the spellchecker moved past a word that was 329 // If true, this means the spellchecker moved past a word that was
299 // previously determined to be misspelled or skippable, which means 330 // previously determined to be misspelled or skippable, which means
300 // another spellcheck language marked it as correct. 331 // another spellcheck language marked it as correct.
301 if (position_in_text != possible_misspelling_start) { 332 if (position_in_text != possible_misspelling_start) {
302 *misspelling_len = 0; 333 *misspelling_len = 0;
303 position_in_text = possible_misspelling_start; 334 position_in_text = possible_misspelling_start;
335 suggestions_list.clear();
304 language = languages_.begin(); 336 language = languages_.begin();
305 } else { 337 } else {
306 language++; 338 language++;
307 } 339 }
308 break; 340 break;
309 case SpellcheckLanguage::SpellcheckWordResult::IS_MISSPELLED: 341 case SpellcheckLanguage::SpellcheckWordResult::IS_MISSPELLED:
310 *misspelling_start = possible_misspelling_start; 342 *misspelling_start = possible_misspelling_start;
311 *misspelling_len = possible_misspelling_len; 343 *misspelling_len = possible_misspelling_len;
312 // If true, this means the spellchecker moved past a word that was 344 // If true, this means the spellchecker moved past a word that was
313 // previously determined to be misspelled or skippable, which means 345 // previously determined to be misspelled or skippable, which means
314 // another spellcheck language marked it as correct. 346 // another spellcheck language marked it as correct.
315 language = position_in_text != *misspelling_start ? languages_.begin() 347 if (position_in_text != *misspelling_start) {
316 : language + 1; 348 suggestions_list.clear();
317 position_in_text = *misspelling_start; 349 language = languages_.begin();
350 position_in_text = *misspelling_start;
351 } else {
352 suggestions_list.push_back(language_suggestions);
353 language++;
354 }
318 break; 355 break;
319 } 356 }
320 } 357 }
321 358
322 // If |*misspelling_len| is non-zero, that means at least one language 359 // If |*misspelling_len| is non-zero, that means at least one language
323 // marked a word misspelled and no other language considered it correct. 360 // marked a word misspelled and no other language considered it correct.
324 if (*misspelling_len != 0) 361 if (*misspelling_len != 0) {
362 if (optional_suggestions)
363 FillSuggestions(suggestions_list, optional_suggestions);
325 return false; 364 return false;
365 }
326 } 366 }
327 367
328 NOTREACHED(); 368 NOTREACHED();
329 return true; 369 return true;
330 } 370 }
331 371
332 bool SpellCheck::SpellCheckParagraph( 372 bool SpellCheck::SpellCheckParagraph(
333 const base::string16& text, 373 const base::string16& text,
334 WebVector<WebTextCheckingResult>* results) { 374 WebVector<WebTextCheckingResult>* results) {
335 #if !defined(USE_BROWSER_SPELLCHECKER) 375 #if !defined(USE_BROWSER_SPELLCHECKER)
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 593
554 bool SpellCheck::IsSpellcheckEnabled() { 594 bool SpellCheck::IsSpellcheckEnabled() {
555 #if defined(OS_ANDROID) 595 #if defined(OS_ANDROID)
556 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 596 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
557 switches::kEnableAndroidSpellChecker)) { 597 switches::kEnableAndroidSpellChecker)) {
558 return false; 598 return false;
559 } 599 }
560 #endif 600 #endif
561 return spellcheck_enabled_; 601 return spellcheck_enabled_;
562 } 602 }
OLDNEW
« no previous file with comments | « chrome/renderer/spellchecker/spellcheck.h ('k') | chrome/renderer/spellchecker/spellcheck_multilingual_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698