| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/renderer/spellchecker/spellcheck_language.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "chrome/renderer/spellchecker/spellcheck_worditerator.h" | |
| 11 #include "chrome/renderer/spellchecker/spelling_engine.h" | |
| 12 | |
| 13 | |
| 14 SpellcheckLanguage::SpellcheckLanguage() | |
| 15 : platform_spelling_engine_(CreateNativeSpellingEngine()) { | |
| 16 } | |
| 17 | |
| 18 SpellcheckLanguage::~SpellcheckLanguage() { | |
| 19 } | |
| 20 | |
| 21 void SpellcheckLanguage::Init(base::File file, const std::string& language) { | |
| 22 DCHECK(platform_spelling_engine_.get()); | |
| 23 platform_spelling_engine_->Init(std::move(file)); | |
| 24 | |
| 25 character_attributes_.SetDefaultLanguage(language); | |
| 26 text_iterator_.Reset(); | |
| 27 contraction_iterator_.Reset(); | |
| 28 } | |
| 29 | |
| 30 bool SpellcheckLanguage::InitializeIfNeeded() { | |
| 31 DCHECK(platform_spelling_engine_.get()); | |
| 32 return platform_spelling_engine_->InitializeIfNeeded(); | |
| 33 } | |
| 34 | |
| 35 SpellcheckLanguage::SpellcheckWordResult SpellcheckLanguage::SpellCheckWord( | |
| 36 const base::char16* text_begin, | |
| 37 int position_in_text, | |
| 38 int text_length, | |
| 39 int tag, | |
| 40 int* skip_or_misspelling_start, | |
| 41 int* skip_or_misspelling_len, | |
| 42 std::vector<base::string16>* optional_suggestions) { | |
| 43 int remaining_text_len = text_length - position_in_text; | |
| 44 DCHECK(remaining_text_len >= 0); | |
| 45 DCHECK(skip_or_misspelling_start && skip_or_misspelling_len) | |
| 46 << "Out vars must be given."; | |
| 47 | |
| 48 // Do nothing if we need to delay initialization. (Rather than blocking, | |
| 49 // report the word as correctly spelled.) | |
| 50 if (InitializeIfNeeded()) | |
| 51 return IS_CORRECT; | |
| 52 | |
| 53 // Do nothing if spell checking is disabled. | |
| 54 if (!platform_spelling_engine_.get() || | |
| 55 !platform_spelling_engine_->IsEnabled()) | |
| 56 return IS_CORRECT; | |
| 57 | |
| 58 *skip_or_misspelling_start = 0; | |
| 59 *skip_or_misspelling_len = 0; | |
| 60 if (remaining_text_len == 0) | |
| 61 return IS_CORRECT; // No input means always spelled correctly. | |
| 62 | |
| 63 base::string16 word; | |
| 64 int word_start; | |
| 65 int word_length; | |
| 66 if (!text_iterator_.IsInitialized() && | |
| 67 !text_iterator_.Initialize(&character_attributes_, true)) { | |
| 68 // We failed to initialize text_iterator_, return as spelled correctly. | |
| 69 VLOG(1) << "Failed to initialize SpellcheckWordIterator"; | |
| 70 return IS_CORRECT; | |
| 71 } | |
| 72 | |
| 73 text_iterator_.SetText(text_begin + position_in_text, remaining_text_len); | |
| 74 DCHECK(platform_spelling_engine_.get()); | |
| 75 for (SpellcheckWordIterator::WordIteratorStatus status = | |
| 76 text_iterator_.GetNextWord(&word, &word_start, &word_length); | |
| 77 status != SpellcheckWordIterator::IS_END_OF_TEXT; | |
| 78 status = text_iterator_.GetNextWord(&word, &word_start, &word_length)) { | |
| 79 // Found a character that is not able to be spellchecked so determine how | |
| 80 // long the sequence of uncheckable characters is and then return. | |
| 81 if (status == SpellcheckWordIterator::IS_SKIPPABLE) { | |
| 82 *skip_or_misspelling_start = position_in_text + word_start; | |
| 83 while (status == SpellcheckWordIterator::IS_SKIPPABLE) { | |
| 84 *skip_or_misspelling_len += word_length; | |
| 85 status = text_iterator_.GetNextWord(&word, &word_start, &word_length); | |
| 86 } | |
| 87 return IS_SKIPPABLE; | |
| 88 } | |
| 89 | |
| 90 // Found a word (or a contraction) that the spellchecker can check the | |
| 91 // spelling of. | |
| 92 if (platform_spelling_engine_->CheckSpelling(word, tag)) | |
| 93 continue; | |
| 94 | |
| 95 // If the given word is a concatenated word of two or more valid words | |
| 96 // (e.g. "hello:hello"), we should treat it as a valid word. | |
| 97 if (IsValidContraction(word, tag)) | |
| 98 continue; | |
| 99 | |
| 100 *skip_or_misspelling_start = position_in_text + word_start; | |
| 101 *skip_or_misspelling_len = word_length; | |
| 102 | |
| 103 // Get the list of suggested words. | |
| 104 if (optional_suggestions) { | |
| 105 platform_spelling_engine_->FillSuggestionList(word, | |
| 106 optional_suggestions); | |
| 107 } | |
| 108 return IS_MISSPELLED; | |
| 109 } | |
| 110 | |
| 111 return IS_CORRECT; | |
| 112 } | |
| 113 | |
| 114 // Returns whether or not the given string is a valid contraction. | |
| 115 // This function is a fall-back when the SpellcheckWordIterator class | |
| 116 // returns a concatenated word which is not in the selected dictionary | |
| 117 // (e.g. "in'n'out") but each word is valid. | |
| 118 bool SpellcheckLanguage::IsValidContraction(const base::string16& contraction, | |
| 119 int tag) { | |
| 120 if (!contraction_iterator_.IsInitialized() && | |
| 121 !contraction_iterator_.Initialize(&character_attributes_, false)) { | |
| 122 // We failed to initialize the word iterator, return as spelled correctly. | |
| 123 VLOG(1) << "Failed to initialize contraction_iterator_"; | |
| 124 return true; | |
| 125 } | |
| 126 | |
| 127 contraction_iterator_.SetText(contraction.c_str(), contraction.length()); | |
| 128 | |
| 129 base::string16 word; | |
| 130 int word_start; | |
| 131 int word_length; | |
| 132 | |
| 133 DCHECK(platform_spelling_engine_.get()); | |
| 134 for (SpellcheckWordIterator::WordIteratorStatus status = | |
| 135 contraction_iterator_.GetNextWord(&word, &word_start, &word_length); | |
| 136 status != SpellcheckWordIterator::IS_END_OF_TEXT; | |
| 137 status = contraction_iterator_.GetNextWord(&word, &word_start, | |
| 138 &word_length)) { | |
| 139 if (status == SpellcheckWordIterator::IS_SKIPPABLE) | |
| 140 continue; | |
| 141 | |
| 142 if (!platform_spelling_engine_->CheckSpelling(word, tag)) | |
| 143 return false; | |
| 144 } | |
| 145 return true; | |
| 146 } | |
| 147 | |
| 148 bool SpellcheckLanguage::IsEnabled() { | |
| 149 DCHECK(platform_spelling_engine_.get()); | |
| 150 return platform_spelling_engine_->IsEnabled(); | |
| 151 } | |
| OLD | NEW |