OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |