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