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

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

Issue 395007: Move Mac to using renderer spellchecker. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: ui test fix Created 11 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/histogram.h" 8 #include "base/histogram.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "chrome/common/render_messages.h"
11 #include "chrome/common/spellcheck_common.h"
10 #include "chrome/renderer/render_thread.h" 12 #include "chrome/renderer/render_thread.h"
11 #include "third_party/hunspell/src/hunspell/hunspell.hxx" 13 #include "third_party/hunspell/src/hunspell/hunspell.hxx"
12 14
13 static const int kMaxAutoCorrectWordSize = 8;
14 static const int kMaxSuggestions = 5;
15
16 using base::TimeTicks; 15 using base::TimeTicks;
17 16
18 SpellCheck::SpellCheck() 17 SpellCheck::SpellCheck()
19 : file_(base::kInvalidPlatformFileValue), 18 : file_(base::kInvalidPlatformFileValue),
20 auto_spell_correct_turned_on_(false), 19 auto_spell_correct_turned_on_(false),
21 // TODO(estade): initialize this properly.
22 is_using_platform_spelling_engine_(false), 20 is_using_platform_spelling_engine_(false),
23 initialized_(false) { 21 initialized_(false) {
24 // Wait till we check the first word before doing any initializing. 22 // Wait till we check the first word before doing any initializing.
25 } 23 }
26 24
27 SpellCheck::~SpellCheck() { 25 SpellCheck::~SpellCheck() {
28 } 26 }
29 27
30 void SpellCheck::Init(base::PlatformFile file, 28 void SpellCheck::Init(base::PlatformFile file,
31 const std::vector<std::string>& custom_words, 29 const std::vector<std::string>& custom_words,
32 const std::string language) { 30 const std::string language) {
33 initialized_ = true; 31 initialized_ = true;
34 hunspell_.reset(); 32 hunspell_.reset();
35 bdict_file_.reset(); 33 bdict_file_.reset();
36 file_ = file; 34 file_ = file;
35 is_using_platform_spelling_engine_ =
36 file == base::kInvalidPlatformFileValue && !language.empty();
37
37 character_attributes_.SetDefaultLanguage(language); 38 character_attributes_.SetDefaultLanguage(language);
38 39
39 custom_words_.insert(custom_words_.end(), 40 custom_words_.insert(custom_words_.end(),
40 custom_words.begin(), custom_words.end()); 41 custom_words.begin(), custom_words.end());
41 42
42 // We delay the actual initialization of hunspell until it is needed. 43 // We delay the actual initialization of hunspell until it is needed.
43 } 44 }
44 45
45 bool SpellCheck::SpellCheckWord( 46 bool SpellCheck::SpellCheckWord(
46 const char16* in_word, 47 const char16* in_word,
47 int in_word_len, 48 int in_word_len,
48 int tag, 49 int tag,
49 int* misspelling_start, 50 int* misspelling_start,
50 int* misspelling_len, 51 int* misspelling_len,
51 std::vector<string16>* optional_suggestions) { 52 std::vector<string16>* optional_suggestions) {
52 DCHECK(in_word_len >= 0); 53 DCHECK(in_word_len >= 0);
53 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given."; 54 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given.";
54 55
55 // Do nothing if we need to delay initialization. (Rather than blocking, 56 // Do nothing if we need to delay initialization. (Rather than blocking,
56 // report the word as correctly spelled.) 57 // report the word as correctly spelled.)
57 if (InitializeIfNeeded()) 58 if (InitializeIfNeeded())
58 return true; 59 return true;
59 60
60 // Do nothing if spell checking is disabled. 61 // Do nothing if spell checking is disabled.
61 if (initialized_ && file_ == base::kInvalidPlatformFileValue) 62 if (initialized_ && file_ == base::kInvalidPlatformFileValue &&
63 !is_using_platform_spelling_engine_) {
62 return true; 64 return true;
65 }
63 66
64 *misspelling_start = 0; 67 *misspelling_start = 0;
65 *misspelling_len = 0; 68 *misspelling_len = 0;
66 if (in_word_len == 0) 69 if (in_word_len == 0)
67 return true; // No input means always spelled correctly. 70 return true; // No input means always spelled correctly.
68 71
69 SpellcheckWordIterator word_iterator; 72 SpellcheckWordIterator word_iterator;
70 string16 word; 73 string16 word;
71 int word_start; 74 int word_start;
72 int word_length; 75 int word_length;
(...skipping 20 matching lines...) Expand all
93 96
94 return true; 97 return true;
95 } 98 }
96 99
97 string16 SpellCheck::GetAutoCorrectionWord(const string16& word, int tag) { 100 string16 SpellCheck::GetAutoCorrectionWord(const string16& word, int tag) {
98 string16 autocorrect_word; 101 string16 autocorrect_word;
99 if (!auto_spell_correct_turned_on_) 102 if (!auto_spell_correct_turned_on_)
100 return autocorrect_word; // Return the empty string. 103 return autocorrect_word; // Return the empty string.
101 104
102 int word_length = static_cast<int>(word.size()); 105 int word_length = static_cast<int>(word.size());
103 if (word_length < 2 || word_length > kMaxAutoCorrectWordSize) 106 if (word_length < 2 || word_length > SpellCheckCommon::kMaxAutoCorrectWordSize )
104 return autocorrect_word; 107 return autocorrect_word;
105 108
106 if (InitializeIfNeeded()) 109 if (InitializeIfNeeded())
107 return autocorrect_word; 110 return autocorrect_word;
108 111
109 char16 misspelled_word[kMaxAutoCorrectWordSize + 1]; 112 char16 misspelled_word[SpellCheckCommon::kMaxAutoCorrectWordSize + 1];
110 const char16* word_char = word.c_str(); 113 const char16* word_char = word.c_str();
111 for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) { 114 for (int i = 0; i <= SpellCheckCommon::kMaxAutoCorrectWordSize; i++) {
112 if (i >= word_length) 115 if (i >= word_length)
113 misspelled_word[i] = NULL; 116 misspelled_word[i] = NULL;
114 else 117 else
115 misspelled_word[i] = word_char[i]; 118 misspelled_word[i] = word_char[i];
116 } 119 }
117 120
118 // Swap adjacent characters and spellcheck. 121 // Swap adjacent characters and spellcheck.
119 int misspelling_start, misspelling_len; 122 int misspelling_start, misspelling_len;
120 for (int i = 0; i < word_length - 1; i++) { 123 for (int i = 0; i < word_length - 1; i++) {
121 // Swap. 124 // Swap.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 TimeTicks::Now() - start_time); 184 TimeTicks::Now() - start_time);
182 } 185 }
183 } 186 }
184 187
185 void SpellCheck::AddWordToHunspell(const std::string& word) { 188 void SpellCheck::AddWordToHunspell(const std::string& word) {
186 if (!word.empty() && word.length() < MAXWORDUTF8LEN) 189 if (!word.empty() && word.length() < MAXWORDUTF8LEN)
187 hunspell_->add(word.c_str()); 190 hunspell_->add(word.c_str());
188 } 191 }
189 192
190 bool SpellCheck::InitializeIfNeeded() { 193 bool SpellCheck::InitializeIfNeeded() {
194 if (is_using_platform_spelling_engine_)
195 return false;
196
191 if (!initialized_) { 197 if (!initialized_) {
192 RenderThread::current()->RequestSpellCheckDictionary(); 198 RenderThread::current()->Send(
199 new ViewHostMsg_SpellChecker_RequestDictionary);
193 initialized_ = true; 200 initialized_ = true;
194 return true; 201 return true;
195 } 202 }
196 203
197 // Check if the platform spellchecker is being used. 204 // Check if the platform spellchecker is being used.
198 if (!is_using_platform_spelling_engine_ && 205 if (file_ != base::kInvalidPlatformFileValue) {
199 file_ != base::kInvalidPlatformFileValue) {
200 // If it isn't, init hunspell. 206 // If it isn't, init hunspell.
201 InitializeHunspell(); 207 InitializeHunspell();
202 } 208 }
203 209
204 return false; 210 return false;
205 } 211 }
206 212
207 // When called, relays the request to check the spelling to the proper 213 // When called, relays the request to check the spelling to the proper
208 // backend, either hunspell or a platform-specific backend. 214 // backend, either hunspell or a platform-specific backend.
209 bool SpellCheck::CheckSpelling(const string16& word_to_check, int tag) { 215 bool SpellCheck::CheckSpelling(const string16& word_to_check, int tag) {
210 bool word_correct = false; 216 bool word_correct = false;
211 217
212 if (is_using_platform_spelling_engine_) { 218 if (is_using_platform_spelling_engine_) {
213 // TODO(estade): sync IPC to browser. 219 RenderThread::current()->Send(
214 word_correct = true; 220 new ViewHostMsg_SpellChecker_PlatformCheckSpelling(word_to_check, tag,
221 &word_correct));
215 } else { 222 } else {
216 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check)); 223 std::string word_to_check_utf8(UTF16ToUTF8(word_to_check));
217 // Hunspell shouldn't let us exceed its max, but check just in case 224 // Hunspell shouldn't let us exceed its max, but check just in case
218 if (word_to_check_utf8.length() < MAXWORDUTF8LEN) { 225 if (word_to_check_utf8.length() < MAXWORDUTF8LEN) {
219 // |hunspell_->spell| returns 0 if the word is spelled correctly and 226 // |hunspell_->spell| returns 0 if the word is spelled correctly and
220 // non-zero otherwsie. 227 // non-zero otherwsie.
221 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0); 228 word_correct = (hunspell_->spell(word_to_check_utf8.c_str()) != 0);
222 } 229 }
223 } 230 }
224 231
225 return word_correct; 232 return word_correct;
226 } 233 }
227 234
228 void SpellCheck::FillSuggestionList( 235 void SpellCheck::FillSuggestionList(
229 const string16& wrong_word, 236 const string16& wrong_word,
230 std::vector<string16>* optional_suggestions) { 237 std::vector<string16>* optional_suggestions) {
231 if (is_using_platform_spelling_engine_) { 238 if (is_using_platform_spelling_engine_) {
232 // TODO(estade): sync IPC to browser. 239 RenderThread::current()->Send(
240 new ViewHostMsg_SpellChecker_PlatformFillSuggestionList(
241 wrong_word, optional_suggestions));
233 return; 242 return;
234 } 243 }
235 char** suggestions; 244 char** suggestions;
236 int number_of_suggestions = 245 int number_of_suggestions =
237 hunspell_->suggest(&suggestions, UTF16ToUTF8(wrong_word).c_str()); 246 hunspell_->suggest(&suggestions, UTF16ToUTF8(wrong_word).c_str());
238 247
239 // Populate the vector of WideStrings. 248 // Populate the vector of WideStrings.
240 for (int i = 0; i < number_of_suggestions; i++) { 249 for (int i = 0; i < number_of_suggestions; i++) {
241 if (i < kMaxSuggestions) 250 if (i < SpellCheckCommon::kMaxSuggestions)
242 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i])); 251 optional_suggestions->push_back(UTF8ToUTF16(suggestions[i]));
243 free(suggestions[i]); 252 free(suggestions[i]);
244 } 253 }
245 if (suggestions != NULL) 254 if (suggestions != NULL)
246 free(suggestions); 255 free(suggestions);
247 } 256 }
248 257
249 // Returns whether or not the given string is a valid contraction. 258 // Returns whether or not the given string is a valid contraction.
250 // This function is a fall-back when the SpellcheckWordIterator class 259 // This function is a fall-back when the SpellcheckWordIterator class
251 // returns a concatenated word which is not in the selected dictionary 260 // returns a concatenated word which is not in the selected dictionary
252 // (e.g. "in'n'out") but each word is valid. 261 // (e.g. "in'n'out") but each word is valid.
253 bool SpellCheck::IsValidContraction(const string16& contraction, int tag) { 262 bool SpellCheck::IsValidContraction(const string16& contraction, int tag) {
254 SpellcheckWordIterator word_iterator; 263 SpellcheckWordIterator word_iterator;
255 word_iterator.Initialize(&character_attributes_, contraction.c_str(), 264 word_iterator.Initialize(&character_attributes_, contraction.c_str(),
256 contraction.length(), false); 265 contraction.length(), false);
257 266
258 string16 word; 267 string16 word;
259 int word_start; 268 int word_start;
260 int word_length; 269 int word_length;
261 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { 270 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
262 if (!CheckSpelling(word, tag)) 271 if (!CheckSpelling(word, tag))
263 return false; 272 return false;
264 } 273 }
265 return true; 274 return true;
266 } 275 }
OLDNEW
« no previous file with comments | « chrome/renderer/spellchecker/spellcheck.h ('k') | chrome/renderer/spellchecker/spellcheck_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698