• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/logging.h"
8 #include "chrome/renderer/spellchecker/spellcheck_worditerator.h"
9 #include "chrome/renderer/spellchecker/spelling_engine.h"
10 
11 
SpellcheckLanguage()12 SpellcheckLanguage::SpellcheckLanguage()
13     : platform_spelling_engine_(CreateNativeSpellingEngine()) {
14 }
15 
~SpellcheckLanguage()16 SpellcheckLanguage::~SpellcheckLanguage() {
17 }
18 
Init(base::File file,const std::string & language)19 void SpellcheckLanguage::Init(base::File file, const std::string& language) {
20   DCHECK(platform_spelling_engine_.get());
21   platform_spelling_engine_->Init(file.Pass());
22 
23   character_attributes_.SetDefaultLanguage(language);
24   text_iterator_.Reset();
25   contraction_iterator_.Reset();
26 }
27 
InitializeIfNeeded()28 bool SpellcheckLanguage::InitializeIfNeeded() {
29   DCHECK(platform_spelling_engine_.get());
30   return platform_spelling_engine_->InitializeIfNeeded();
31 }
32 
SpellCheckWord(const base::char16 * in_word,int in_word_len,int tag,int * misspelling_start,int * misspelling_len,std::vector<base::string16> * optional_suggestions)33 bool SpellcheckLanguage::SpellCheckWord(
34     const base::char16* in_word,
35     int in_word_len,
36     int tag,
37     int* misspelling_start,
38     int* misspelling_len,
39     std::vector<base::string16>* optional_suggestions) {
40   DCHECK(in_word_len >= 0);
41   DCHECK(misspelling_start && misspelling_len) << "Out vars must be given.";
42 
43   // Do nothing if we need to delay initialization. (Rather than blocking,
44   // report the word as correctly spelled.)
45   if (InitializeIfNeeded())
46     return true;
47 
48   // Do nothing if spell checking is disabled.
49   if (!platform_spelling_engine_.get() ||
50       !platform_spelling_engine_->IsEnabled())
51     return true;
52 
53   *misspelling_start = 0;
54   *misspelling_len = 0;
55   if (in_word_len == 0)
56     return true;  // No input means always spelled correctly.
57 
58   base::string16 word;
59   int word_start;
60   int word_length;
61   if (!text_iterator_.IsInitialized() &&
62       !text_iterator_.Initialize(&character_attributes_, true)) {
63       // We failed to initialize text_iterator_, return as spelled correctly.
64       VLOG(1) << "Failed to initialize SpellcheckWordIterator";
65       return true;
66   }
67 
68   text_iterator_.SetText(in_word, in_word_len);
69   DCHECK(platform_spelling_engine_.get());
70   while (text_iterator_.GetNextWord(&word, &word_start, &word_length)) {
71     // Found a word (or a contraction) that the spellchecker can check the
72     // spelling of.
73     if (platform_spelling_engine_->CheckSpelling(word, tag))
74       continue;
75 
76     // If the given word is a concatenated word of two or more valid words
77     // (e.g. "hello:hello"), we should treat it as a valid word.
78     if (IsValidContraction(word, tag))
79       continue;
80 
81     *misspelling_start = word_start;
82     *misspelling_len = word_length;
83 
84     // Get the list of suggested words.
85     if (optional_suggestions) {
86       platform_spelling_engine_->FillSuggestionList(word,
87                                                     optional_suggestions);
88     }
89     return false;
90   }
91 
92   return true;
93 }
94 
95 // Returns whether or not the given string is a valid contraction.
96 // This function is a fall-back when the SpellcheckWordIterator class
97 // returns a concatenated word which is not in the selected dictionary
98 // (e.g. "in'n'out") but each word is valid.
IsValidContraction(const base::string16 & contraction,int tag)99 bool SpellcheckLanguage::IsValidContraction(const base::string16& contraction,
100                                             int tag) {
101   if (!contraction_iterator_.IsInitialized() &&
102       !contraction_iterator_.Initialize(&character_attributes_, false)) {
103     // We failed to initialize the word iterator, return as spelled correctly.
104     VLOG(1) << "Failed to initialize contraction_iterator_";
105     return true;
106   }
107 
108   contraction_iterator_.SetText(contraction.c_str(), contraction.length());
109 
110   base::string16 word;
111   int word_start;
112   int word_length;
113 
114   DCHECK(platform_spelling_engine_.get());
115   while (contraction_iterator_.GetNextWord(&word, &word_start, &word_length)) {
116     if (!platform_spelling_engine_->CheckSpelling(word, tag))
117       return false;
118   }
119   return true;
120 }
121 
IsEnabled()122 bool SpellcheckLanguage::IsEnabled() {
123   DCHECK(platform_spelling_engine_.get());
124   return platform_spelling_engine_->IsEnabled();
125 }
126