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

Side by Side Diff: chrome/browser/spellchecker.cc

Issue 14408: Port the spell checker to posix. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years 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
« no previous file with comments | « chrome/browser/spellchecker.h ('k') | chrome/common/render_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <io.h>
6
7 #include "chrome/browser/spellchecker.h" 5 #include "chrome/browser/spellchecker.h"
8 #include "base/basictypes.h" 6 #include "base/basictypes.h"
7 #include "base/compiler_specific.h"
9 #include "base/file_util.h" 8 #include "base/file_util.h"
10 #include "base/histogram.h" 9 #include "base/histogram.h"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/path_service.h" 11 #include "base/path_service.h"
13 #include "base/string_util.h" 12 #include "base/string_util.h"
14 #include "base/thread.h" 13 #include "base/thread.h"
15 #include "base/win_util.h"
16 #include "chrome/app/locales/locale_settings.h" 14 #include "chrome/app/locales/locale_settings.h"
17 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/profile.h" 16 #include "chrome/browser/profile.h"
19 #include "chrome/browser/url_fetcher.h" 17 #include "chrome/browser/url_fetcher.h"
20 #include "chrome/common/chrome_constants.h" 18 #include "chrome/common/chrome_constants.h"
21 #include "chrome/common/chrome_counters.h" 19 #include "chrome/common/chrome_counters.h"
22 #include "chrome/common/chrome_paths.h" 20 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/l10n_util.h" 21 #include "chrome/common/l10n_util.h"
24 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
25 #include "chrome/common/pref_service.h" 23 #include "chrome/common/pref_service.h"
26 #include "chrome/common/render_messages.h"
27 #include "chrome/common/win_util.h"
28 #include "chrome/third_party/hunspell/src/hunspell/hunspell.hxx" 24 #include "chrome/third_party/hunspell/src/hunspell/hunspell.hxx"
29 #include "net/url_request/url_request.h" 25 #include "net/url_request/url_request.h"
30 26
31 #include "generated_resources.h" 27 #include "generated_resources.h"
32 28
33 using base::TimeTicks; 29 using base::TimeTicks;
34 30
35 static const int kMaxSuggestions = 5; // Max number of dictionary suggestions. 31 static const int kMaxSuggestions = 5; // Max number of dictionary suggestions.
36 32
37 namespace { 33 namespace {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 } 71 }
76 72
77 void SpellChecker::SpellCheckLanguages(Languages* languages) { 73 void SpellChecker::SpellCheckLanguages(Languages* languages) {
78 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); ++i) 74 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); ++i)
79 languages->push_back(g_supported_spellchecker_languages[i]); 75 languages->push_back(g_supported_spellchecker_languages[i]);
80 } 76 }
81 77
82 SpellChecker::Language SpellChecker::GetCorrespondingSpellCheckLanguage( 78 SpellChecker::Language SpellChecker::GetCorrespondingSpellCheckLanguage(
83 const Language& language) { 79 const Language& language) {
84 // Look for exact match in the Spell Check language list. 80 // Look for exact match in the Spell Check language list.
85 for (int i = 0; i < arraysize(g_supported_spellchecker_languages); ++i) { 81 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); ++i) {
86 Language spellcheck_language(g_supported_spellchecker_languages[i]); 82 Language spellcheck_language(g_supported_spellchecker_languages[i]);
87 if (spellcheck_language == language) 83 if (spellcheck_language == language)
88 return language; 84 return language;
89 } 85 }
90 86
91 // Look for a match by comparing only language parts. All the 'en-RR' 87 // Look for a match by comparing only language parts. All the 'en-RR'
92 // except for 'en-GB' exactly matched in the above loop, will match 88 // except for 'en-GB' exactly matched in the above loop, will match
93 // 'en-US'. This is not ideal because 'en-AU', 'en-ZA', 'en-NZ' had 89 // 'en-US'. This is not ideal because 'en-AU', 'en-ZA', 'en-NZ' had
94 // better be matched with 'en-GB'. This does not handle cases like 90 // better be matched with 'en-GB'. This does not handle cases like
95 // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part 91 // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part
96 // locale ids with a script code in the middle, yet. 92 // locale ids with a script code in the middle, yet.
97 // TODO(jungshik): Add a better fallback. 93 // TODO(jungshik): Add a better fallback.
98 Language language_part(language, 0, language.find(L'-')); 94 Language language_part(language, 0, language.find(L'-'));
99 for (int i = 0; i < arraysize(g_supported_spellchecker_languages); ++i) { 95 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); ++i) {
100 Language spellcheck_language(g_supported_spellchecker_languages[i]); 96 Language spellcheck_language(g_supported_spellchecker_languages[i]);
101 if (spellcheck_language.substr(0, spellcheck_language.find(L'-')) == 97 if (spellcheck_language.substr(0, spellcheck_language.find(L'-')) ==
102 language_part) 98 language_part)
103 return spellcheck_language; 99 return spellcheck_language;
104 } 100 }
105 101
106 // No match found - return blank. 102 // No match found - return blank.
107 return Language(); 103 return Language();
108 } 104 }
109 105
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 // disk using file_util::WriteFile. 201 // disk using file_util::WriteFile.
206 class SpellChecker::DictionaryDownloadController 202 class SpellChecker::DictionaryDownloadController
207 : public URLFetcher::Delegate, 203 : public URLFetcher::Delegate,
208 public base::RefCountedThreadSafe<DictionaryDownloadController> { 204 public base::RefCountedThreadSafe<DictionaryDownloadController> {
209 public: 205 public:
210 DictionaryDownloadController( 206 DictionaryDownloadController(
211 Task* spellchecker_flag_set_task, 207 Task* spellchecker_flag_set_task,
212 const std::wstring& dic_file_path, 208 const std::wstring& dic_file_path,
213 URLRequestContext* url_request_context, 209 URLRequestContext* url_request_context,
214 MessageLoop* ui_loop) 210 MessageLoop* ui_loop)
215 : url_request_context_(url_request_context), 211 : spellchecker_flag_set_task_(spellchecker_flag_set_task),
212 url_request_context_(url_request_context),
216 download_server_url_( 213 download_server_url_(
217 L"http://cache.pack.google.com/chrome/dict/"), 214 L"http://cache.pack.google.com/chrome/dict/"),
218 ui_loop_(ui_loop), 215 ui_loop_(ui_loop) {
219 spellchecker_flag_set_task_(spellchecker_flag_set_task) {
220 // Determine dictionary file path and name. 216 // Determine dictionary file path and name.
221 fetcher_.reset(NULL); 217 fetcher_.reset(NULL);
222 dic_zip_file_path_ = file_util::GetDirectoryFromPath(dic_file_path); 218 dic_zip_file_path_ = file_util::GetDirectoryFromPath(dic_file_path);
223 file_name_ = file_util::GetFilenameFromPath(dic_file_path); 219 file_name_ = file_util::GetFilenameFromPath(dic_file_path);
224 220
225 name_of_file_to_download_ = l10n_util::ToLower(file_name_); 221 name_of_file_to_download_ = l10n_util::ToLower(file_name_);
226 } 222 }
227 223
228 // Save the file in memory buffer to the designated dictionary file. 224 // Save the file in memory buffer to the designated dictionary file.
229 // returns the number of bytes it could save. 225 // returns the number of bytes it could save.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 295 }
300 296
301 // ################################################################ 297 // ################################################################
302 // This part of the code is used for spell checking. 298 // This part of the code is used for spell checking.
303 // ################################################################ 299 // ################################################################
304 300
305 std::wstring SpellChecker::GetVersionedFileName(const Language& language, 301 std::wstring SpellChecker::GetVersionedFileName(const Language& language,
306 const std::wstring& dict_dir) { 302 const std::wstring& dict_dir) {
307 // The default version string currently in use. 303 // The default version string currently in use.
308 static const wchar_t kDefaultVersionString[] = L"-1-1"; 304 static const wchar_t kDefaultVersionString[] = L"-1-1";
309 305
310 // Use this struct to insert version strings for dictionary files which have 306 // Use this struct to insert version strings for dictionary files which have
311 // special version strings, other than the default version string. 307 // special version strings, other than the default version string.
312 // For de-DE, we are currently using de-DE-1-1-1 for versioning, because 308 // For de-DE, we are currently using de-DE-1-1-1 for versioning, because
313 // de-DE-1-1.bdic, in the download server, corresponds to a less used 309 // de-DE-1-1.bdic, in the download server, corresponds to a less used
314 // dictionary. This version, i.e., de-DE-1-1-1.bdic, is actually renamed 310 // dictionary. This version, i.e., de-DE-1-1-1.bdic, is actually renamed
315 // from de-DE-neu-1-1.bic. 311 // from de-DE-neu-1-1.bic.
316 static const struct { 312 static const struct {
317 // The language input. 313 // The language input.
318 const char* language; 314 const char* language;
319 315
320 // The corresponding version. 316 // The corresponding version.
321 const char* version; 317 const char* version;
322 } special_version_string[] = { 318 } special_version_string[] = {
323 "de-DE", "-1-1-1", 319 {"de-DE", "-1-1-1"},
324 }; 320 };
325 321
326 // Generate the bdict file name using default version string or special 322 // Generate the bdict file name using default version string or special
327 // version string, depending on the language. 323 // version string, depending on the language.
328 std::wstring versioned_bdict_file_name(language + kDefaultVersionString + 324 std::wstring versioned_bdict_file_name(language + kDefaultVersionString +
329 L".bdic"); 325 L".bdic");
330 std::string language_string(WideToUTF8(language)); 326 std::string language_string(WideToUTF8(language));
331 for (int i = 0; i < arraysize(special_version_string); ++i) { 327 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
332 if (language_string == special_version_string[i].language) { 328 if (language_string == special_version_string[i].language) {
333 versioned_bdict_file_name = 329 versioned_bdict_file_name =
334 language + UTF8ToWide(special_version_string[i].version) + L".bdic"; 330 language + UTF8ToWide(special_version_string[i].version) + L".bdic";
335 break; 331 break;
336 } 332 }
337 } 333 }
338 334
339 std::wstring bdict_file_name(dict_dir); 335 std::wstring bdict_file_name(dict_dir);
340 file_util::AppendToPath(&bdict_file_name, versioned_bdict_file_name); 336 file_util::AppendToPath(&bdict_file_name, versioned_bdict_file_name);
341 return bdict_file_name; 337 return bdict_file_name;
342 } 338 }
343 339
344 SpellChecker::SpellChecker(const std::wstring& dict_dir, 340 SpellChecker::SpellChecker(const std::wstring& dict_dir,
345 const std::wstring& language, 341 const std::wstring& language,
346 URLRequestContext* request_context, 342 URLRequestContext* request_context,
347 const std::wstring& custom_dictionary_file_name) 343 const std::wstring& custom_dictionary_file_name)
348 : custom_dictionary_file_name_(custom_dictionary_file_name), 344 : custom_dictionary_file_name_(custom_dictionary_file_name),
349 tried_to_init_(false), 345 tried_to_init_(false),
350 #ifndef NDEBUG 346 #ifndef NDEBUG
351 worker_loop_(NULL), 347 worker_loop_(NULL),
352 #endif 348 #endif
353 tried_to_download_(false), 349 tried_to_download_(false),
350 file_loop_(NULL),
354 url_request_context_(request_context), 351 url_request_context_(request_context),
355 file_loop_(NULL), 352 dic_is_downloading_(false),
356 #pragma warning(suppress: 4355) // Okay to pass "this" here. 353 ALLOW_THIS_IN_INTIALIZER_LIST(dic_download_state_changer_factory_(this)) {
357 dic_download_state_changer_factory_(this),
358 dic_is_downloading_(false) {
359 // Remember UI loop to later use this as a proxy to get IO loop. 354 // Remember UI loop to later use this as a proxy to get IO loop.
360 ui_loop_ = MessageLoop::current(); 355 ui_loop_ = MessageLoop::current();
361 356
362 // Get File Loop - hunspell gets initialized here. 357 // Get File Loop - hunspell gets initialized here.
363 base::Thread* file_thread = g_browser_process->file_thread(); 358 base::Thread* file_thread = g_browser_process->file_thread();
364 if (file_thread) 359 if (file_thread)
365 file_loop_ = file_thread->message_loop(); 360 file_loop_ = file_thread->message_loop();
366 361
367 // Get the path to the spellcheck file. 362 // Get the path to the spellcheck file.
368 bdict_file_name_ = GetVersionedFileName(language, dict_dir); 363 bdict_file_name_ = GetVersionedFileName(language, dict_dir);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 it != list_of_words.end(); ++it) { 448 it != list_of_words.end(); ++it) {
454 hunspell_->put_word(it->c_str()); 449 hunspell_->put_word(it->c_str());
455 } 450 }
456 } 451 }
457 } 452 }
458 453
459 // Returns whether or not the given string is a valid contraction. 454 // Returns whether or not the given string is a valid contraction.
460 // This function is a fall-back when the SpellcheckWordIterator class 455 // This function is a fall-back when the SpellcheckWordIterator class
461 // returns a concatenated word which is not in the selected dictionary 456 // returns a concatenated word which is not in the selected dictionary
462 // (e.g. "in'n'out") but each word is valid. 457 // (e.g. "in'n'out") but each word is valid.
463 bool SpellChecker::IsValidContraction(const std::wstring& contraction) { 458 bool SpellChecker::IsValidContraction(const string16& contraction) {
464 SpellcheckWordIterator word_iterator; 459 SpellcheckWordIterator word_iterator;
465 word_iterator.Initialize(&character_attributes_, contraction.c_str(), 460 word_iterator.Initialize(&character_attributes_, contraction.c_str(),
466 contraction.length(), false); 461 contraction.length(), false);
467 462
468 std::wstring word; 463 string16 word;
469 int word_start; 464 int word_start;
470 int word_length; 465 int word_length;
471 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { 466 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
472 if (!hunspell_->spell(WideToUTF8(word).c_str())) 467 if (!hunspell_->spell(UTF16ToUTF8(word).c_str()))
473 return false; 468 return false;
474 } 469 }
475 return true; 470 return true;
476 } 471 }
477 472
478 bool SpellChecker::SpellCheckWord( 473 bool SpellChecker::SpellCheckWord(
479 const wchar_t* in_word, 474 const wchar_t* in_word,
480 int in_word_len, 475 int in_word_len,
481 int* misspelling_start, 476 int* misspelling_start,
482 int* misspelling_len, 477 int* misspelling_len,
(...skipping 15 matching lines...) Expand all
498 493
499 *misspelling_start = 0; 494 *misspelling_start = 0;
500 *misspelling_len = 0; 495 *misspelling_len = 0;
501 if (in_word_len == 0) 496 if (in_word_len == 0)
502 return true; // no input means always spelled correctly 497 return true; // no input means always spelled correctly
503 498
504 if (!hunspell_.get()) 499 if (!hunspell_.get())
505 return true; // unable to spellcheck, return word is OK 500 return true; // unable to spellcheck, return word is OK
506 501
507 SpellcheckWordIterator word_iterator; 502 SpellcheckWordIterator word_iterator;
508 std::wstring word; 503 string16 word;
504 string16 in_word_utf16;
505 WideToUTF16(in_word, in_word_len, &in_word_utf16);
509 int word_start; 506 int word_start;
510 int word_length; 507 int word_length;
511 word_iterator.Initialize(&character_attributes_, in_word, in_word_len, true); 508 word_iterator.Initialize(&character_attributes_, in_word_utf16.c_str(),
509 in_word_len, true);
512 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { 510 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) {
513 // Found a word (or a contraction) that hunspell can check its spelling. 511 // Found a word (or a contraction) that hunspell can check its spelling.
514 std::string encoded_word = WideToUTF8(word); 512 std::string encoded_word = UTF16ToUTF8(word);
515 513
516 { 514 {
517 TimeTicks begin_time = TimeTicks::Now(); 515 TimeTicks begin_time = TimeTicks::Now();
518 bool word_ok = !!hunspell_->spell(encoded_word.c_str()); 516 bool word_ok = !!hunspell_->spell(encoded_word.c_str());
519 DHISTOGRAM_TIMES(L"Spellcheck.CheckTime", TimeTicks::Now() - begin_time); 517 DHISTOGRAM_TIMES(L"Spellcheck.CheckTime", TimeTicks::Now() - begin_time);
520 if (word_ok) 518 if (word_ok)
521 continue; 519 continue;
522 } 520 }
523 521
524 // If the given word is a concatenated word of two or more valid words 522 // If the given word is a concatenated word of two or more valid words
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 hunspell_->put_word(word_to_add.c_str()); 587 hunspell_->put_word(word_to_add.c_str());
590 588
591 // Now add the word to the custom dictionary file. 589 // Now add the word to the custom dictionary file.
592 Task* write_word_task = 590 Task* write_word_task =
593 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word); 591 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word);
594 if (file_loop_) 592 if (file_loop_)
595 file_loop_->PostTask(FROM_HERE, write_word_task); 593 file_loop_->PostTask(FROM_HERE, write_word_task);
596 else 594 else
597 write_word_task->Run(); 595 write_word_task->Run();
598 } 596 }
OLDNEW
« no previous file with comments | « chrome/browser/spellchecker.h ('k') | chrome/common/render_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698