OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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 "app/l10n_util.h" | 5 #include "app/l10n_util.h" |
6 #include "chrome/browser/spellchecker.h" | 6 #include "chrome/browser/spellchecker.h" |
7 #include "chrome/browser/spellchecker_common.h" | 7 #include "chrome/browser/spellchecker_common.h" |
8 #include "chrome/browser/spellchecker_platform_engine.h" | 8 #include "chrome/browser/spellchecker_platform_engine.h" |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 if (bdict_file_->Initialize(bdic_file_name)) { | 526 if (bdict_file_->Initialize(bdic_file_name)) { |
527 hunspell_.reset(new Hunspell(bdict_file_->data(), bdict_file_->length())); | 527 hunspell_.reset(new Hunspell(bdict_file_->data(), bdict_file_->length())); |
528 AddCustomWordsToHunspell(); | 528 AddCustomWordsToHunspell(); |
529 } | 529 } |
530 DHISTOGRAM_TIMES("Spellcheck.InitTime", TimeTicks::Now() - begin_time); | 530 DHISTOGRAM_TIMES("Spellcheck.InitTime", TimeTicks::Now() - begin_time); |
531 | 531 |
532 tried_to_init_ = true; | 532 tried_to_init_ = true; |
533 return false; | 533 return false; |
534 } | 534 } |
535 | 535 |
536 void SpellChecker::GetAutoCorrectionWord(const std::wstring& word, | 536 void SpellChecker::GetAutoCorrectionWord(const std::wstring& word, int tag, |
537 std::wstring* autocorrect_word) { | 537 std::wstring* autocorrect_word) { |
538 autocorrect_word->clear(); | 538 autocorrect_word->clear(); |
539 if (!auto_spell_correct_turned_on_) | 539 if (!auto_spell_correct_turned_on_) |
540 return; | 540 return; |
541 | 541 |
542 int word_length = static_cast<int>(word.size()); | 542 int word_length = static_cast<int>(word.size()); |
543 if (word_length < 2 || word_length > kMaxAutoCorrectWordSize) | 543 if (word_length < 2 || word_length > kMaxAutoCorrectWordSize) |
544 return; | 544 return; |
545 | 545 |
546 wchar_t misspelled_word[kMaxAutoCorrectWordSize + 1]; | 546 wchar_t misspelled_word[kMaxAutoCorrectWordSize + 1]; |
547 const wchar_t* word_char = word.c_str(); | 547 const wchar_t* word_char = word.c_str(); |
548 for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) { | 548 for (int i = 0; i <= kMaxAutoCorrectWordSize; i++) { |
549 if (i >= word_length) | 549 if (i >= word_length) |
550 misspelled_word[i] = NULL; | 550 misspelled_word[i] = NULL; |
551 else | 551 else |
552 misspelled_word[i] = word_char[i]; | 552 misspelled_word[i] = word_char[i]; |
553 } | 553 } |
554 | 554 |
555 // Swap adjacent characters and spellcheck. | 555 // Swap adjacent characters and spellcheck. |
556 int misspelling_start, misspelling_len; | 556 int misspelling_start, misspelling_len; |
557 for (int i = 0; i < word_length - 1; i++) { | 557 for (int i = 0; i < word_length - 1; i++) { |
558 // Swap. | 558 // Swap. |
559 std::swap(misspelled_word[i], misspelled_word[i + 1]); | 559 std::swap(misspelled_word[i], misspelled_word[i + 1]); |
560 | 560 |
561 // Check spelling. | 561 // Check spelling. |
562 misspelling_start = misspelling_len = 0; | 562 misspelling_start = misspelling_len = 0; |
563 SpellCheckWord(misspelled_word, word_length, &misspelling_start, | 563 SpellCheckWord(misspelled_word, word_length, tag, &misspelling_start, |
564 &misspelling_len, NULL); | 564 &misspelling_len, NULL); |
565 | 565 |
566 // Make decision: if only one swap produced a valid word, then we want to | 566 // Make decision: if only one swap produced a valid word, then we want to |
567 // return it. If we found two or more, we don't do autocorrection. | 567 // return it. If we found two or more, we don't do autocorrection. |
568 if (misspelling_len == 0) { | 568 if (misspelling_len == 0) { |
569 if (autocorrect_word->empty()) { | 569 if (autocorrect_word->empty()) { |
570 autocorrect_word->assign(misspelled_word); | 570 autocorrect_word->assign(misspelled_word); |
571 } else { | 571 } else { |
572 autocorrect_word->clear(); | 572 autocorrect_word->clear(); |
573 return; | 573 return; |
(...skipping 23 matching lines...) Expand all Loading... |
597 it != list_of_words.end(); ++it) { | 597 it != list_of_words.end(); ++it) { |
598 hunspell_->add(it->c_str()); | 598 hunspell_->add(it->c_str()); |
599 } | 599 } |
600 } | 600 } |
601 } | 601 } |
602 | 602 |
603 // Returns whether or not the given string is a valid contraction. | 603 // Returns whether or not the given string is a valid contraction. |
604 // This function is a fall-back when the SpellcheckWordIterator class | 604 // This function is a fall-back when the SpellcheckWordIterator class |
605 // returns a concatenated word which is not in the selected dictionary | 605 // returns a concatenated word which is not in the selected dictionary |
606 // (e.g. "in'n'out") but each word is valid. | 606 // (e.g. "in'n'out") but each word is valid. |
607 bool SpellChecker::IsValidContraction(const string16& contraction) { | 607 bool SpellChecker::IsValidContraction(const string16& contraction, int tag) { |
608 SpellcheckWordIterator word_iterator; | 608 SpellcheckWordIterator word_iterator; |
609 word_iterator.Initialize(&character_attributes_, contraction.c_str(), | 609 word_iterator.Initialize(&character_attributes_, contraction.c_str(), |
610 contraction.length(), false); | 610 contraction.length(), false); |
611 | 611 |
612 string16 word; | 612 string16 word; |
613 int word_start; | 613 int word_start; |
614 int word_length; | 614 int word_length; |
615 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { | 615 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { |
616 if (!CheckSpelling(UTF16ToUTF8(word))) | 616 if (!CheckSpelling(UTF16ToUTF8(word), tag)) |
617 return false; | 617 return false; |
618 } | 618 } |
619 return true; | 619 return true; |
620 } | 620 } |
621 | 621 |
622 bool SpellChecker::SpellCheckWord( | 622 bool SpellChecker::SpellCheckWord( |
623 const wchar_t* in_word, | 623 const wchar_t* in_word, |
624 int in_word_len, | 624 int in_word_len, |
| 625 int tag, |
625 int* misspelling_start, | 626 int* misspelling_start, |
626 int* misspelling_len, | 627 int* misspelling_len, |
627 std::vector<std::wstring>* optional_suggestions) { | 628 std::vector<std::wstring>* optional_suggestions) { |
628 DCHECK(in_word_len >= 0); | 629 DCHECK(in_word_len >= 0); |
629 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given."; | 630 DCHECK(misspelling_start && misspelling_len) << "Out vars must be given."; |
630 | 631 |
631 #ifndef NDEBUG | 632 #ifndef NDEBUG |
632 // This must always be called on the same thread (normally the I/O thread). | 633 // This must always be called on the same thread (normally the I/O thread). |
633 if (worker_loop_) | 634 if (worker_loop_) |
634 DCHECK(MessageLoop::current() == worker_loop_); | 635 DCHECK(MessageLoop::current() == worker_loop_); |
(...skipping 23 matching lines...) Expand all Loading... |
658 string16 in_word_utf16; | 659 string16 in_word_utf16; |
659 WideToUTF16(in_word, in_word_len, &in_word_utf16); | 660 WideToUTF16(in_word, in_word_len, &in_word_utf16); |
660 int word_start; | 661 int word_start; |
661 int word_length; | 662 int word_length; |
662 word_iterator.Initialize(&character_attributes_, in_word_utf16.c_str(), | 663 word_iterator.Initialize(&character_attributes_, in_word_utf16.c_str(), |
663 in_word_len, true); | 664 in_word_len, true); |
664 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { | 665 while (word_iterator.GetNextWord(&word, &word_start, &word_length)) { |
665 // Found a word (or a contraction) that the spellchecker can check the | 666 // Found a word (or a contraction) that the spellchecker can check the |
666 // spelling of. | 667 // spelling of. |
667 std::string encoded_word = UTF16ToUTF8(word); | 668 std::string encoded_word = UTF16ToUTF8(word); |
668 bool word_ok = CheckSpelling(encoded_word); | 669 bool word_ok = CheckSpelling(encoded_word, tag); |
669 if (word_ok) | 670 if (word_ok) |
670 continue; | 671 continue; |
671 | 672 |
672 // If the given word is a concatenated word of two or more valid words | 673 // If the given word is a concatenated word of two or more valid words |
673 // (e.g. "hello:hello"), we should treat it as a valid word. | 674 // (e.g. "hello:hello"), we should treat it as a valid word. |
674 if (IsValidContraction(word)) | 675 if (IsValidContraction(word, tag)) |
675 continue; | 676 continue; |
676 | 677 |
677 *misspelling_start = word_start; | 678 *misspelling_start = word_start; |
678 *misspelling_len = word_length; | 679 *misspelling_len = word_length; |
679 | 680 |
680 // Get the list of suggested words. | 681 // Get the list of suggested words. |
681 if (optional_suggestions) { | 682 if (optional_suggestions) { |
682 FillSuggestionList(encoded_word, optional_suggestions); | 683 FillSuggestionList(encoded_word, optional_suggestions); |
683 } | 684 } |
684 return false; | 685 return false; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 | 733 |
733 // Now add the word to the custom dictionary file. | 734 // Now add the word to the custom dictionary file. |
734 Task* write_word_task = | 735 Task* write_word_task = |
735 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word); | 736 new AddWordToCustomDictionaryTask(custom_dictionary_file_name_, word); |
736 if (file_loop_) | 737 if (file_loop_) |
737 file_loop_->PostTask(FROM_HERE, write_word_task); | 738 file_loop_->PostTask(FROM_HERE, write_word_task); |
738 else | 739 else |
739 write_word_task->Run(); | 740 write_word_task->Run(); |
740 } | 741 } |
741 | 742 |
742 bool SpellChecker::CheckSpelling(const std::string& word_to_check) { | 743 bool SpellChecker::CheckSpelling(const std::string& word_to_check, int tag) { |
743 bool word_correct = false; | 744 bool word_correct = false; |
744 | 745 |
745 TimeTicks begin_time = TimeTicks::Now(); | 746 TimeTicks begin_time = TimeTicks::Now(); |
746 if (is_using_platform_spelling_engine_) { | 747 if (is_using_platform_spelling_engine_) { |
747 word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check); | 748 word_correct = SpellCheckerPlatform::CheckSpelling(word_to_check, tag); |
748 } else { | 749 } else { |
749 // |hunspell_->spell| returns 0 if the word is spelled correctly and | 750 // |hunspell_->spell| returns 0 if the word is spelled correctly and |
750 // non-zero otherwsie. | 751 // non-zero otherwsie. |
751 word_correct = (hunspell_->spell(word_to_check.c_str()) != 0); | 752 word_correct = (hunspell_->spell(word_to_check.c_str()) != 0); |
752 } | 753 } |
753 DHISTOGRAM_TIMES("Spellcheck.CheckTime", TimeTicks::Now() - begin_time); | 754 DHISTOGRAM_TIMES("Spellcheck.CheckTime", TimeTicks::Now() - begin_time); |
754 | 755 |
755 return word_correct; | 756 return word_correct; |
756 } | 757 } |
757 | 758 |
(...skipping 13 matching lines...) Expand all Loading... |
771 | 772 |
772 // Populate the vector of WideStrings. | 773 // Populate the vector of WideStrings. |
773 for (int i = 0; i < number_of_suggestions; i++) { | 774 for (int i = 0; i < number_of_suggestions; i++) { |
774 if (i < kMaxSuggestions) | 775 if (i < kMaxSuggestions) |
775 optional_suggestions->push_back(UTF8ToWide(suggestions[i])); | 776 optional_suggestions->push_back(UTF8ToWide(suggestions[i])); |
776 free(suggestions[i]); | 777 free(suggestions[i]); |
777 } | 778 } |
778 if (suggestions != NULL) | 779 if (suggestions != NULL) |
779 free(suggestions); | 780 free(suggestions); |
780 } | 781 } |
OLD | NEW |