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(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 
     28 bool SpellcheckLanguage::InitializeIfNeeded() {
     29   DCHECK(platform_spelling_engine_.get());
     30   return platform_spelling_engine_->InitializeIfNeeded();
     31 }
     32 
     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.
     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 
    122 bool SpellcheckLanguage::IsEnabled() {
    123   DCHECK(platform_spelling_engine_.get());
    124   return platform_spelling_engine_->IsEnabled();
    125 }
    126