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