1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,616 @@ 1.4 +/******* BEGIN LICENSE BLOCK ******* 1.5 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 1.6 + * 1.7 + * The contents of this file are subject to the Mozilla Public License Version 1.8 + * 1.1 (the "License"); you may not use this file except in compliance with 1.9 + * the License. You may obtain a copy of the License at 1.10 + * http://www.mozilla.org/MPL/ 1.11 + * 1.12 + * Software distributed under the License is distributed on an "AS IS" basis, 1.13 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1.14 + * for the specific language governing rights and limitations under the 1.15 + * License. 1.16 + * 1.17 + * The Initial Developers of the Original Code are Kevin Hendricks (MySpell) 1.18 + * and László Németh (Hunspell). Portions created by the Initial Developers 1.19 + * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved. 1.20 + * 1.21 + * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca) 1.22 + * David Einstein (deinst@world.std.com) 1.23 + * Michiel van Leeuwen (mvl@exedo.nl) 1.24 + * Caolan McNamara (cmc@openoffice.org) 1.25 + * László Németh (nemethl@gyorsposta.hu) 1.26 + * Davide Prina 1.27 + * Giuseppe Modugno 1.28 + * Gianluca Turconi 1.29 + * Simon Brouwer 1.30 + * Noll Janos 1.31 + * Biro Arpad 1.32 + * Goldman Eleonora 1.33 + * Sarlos Tamas 1.34 + * Bencsath Boldizsar 1.35 + * Halacsy Peter 1.36 + * Dvornik Laszlo 1.37 + * Gefferth Andras 1.38 + * Nagy Viktor 1.39 + * Varga Daniel 1.40 + * Chris Halls 1.41 + * Rene Engelhard 1.42 + * Bram Moolenaar 1.43 + * Dafydd Jones 1.44 + * Harri Pitkanen 1.45 + * Andras Timar 1.46 + * Tor Lillqvist 1.47 + * Jesper Kristensen (mail@jesperkristensen.dk) 1.48 + * 1.49 + * Alternatively, the contents of this file may be used under the terms of 1.50 + * either the GNU General Public License Version 2 or later (the "GPL"), or 1.51 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 1.52 + * in which case the provisions of the GPL or the LGPL are applicable instead 1.53 + * of those above. If you wish to allow use of your version of this file only 1.54 + * under the terms of either the GPL or the LGPL, and not to allow others to 1.55 + * use your version of this file under the terms of the MPL, indicate your 1.56 + * decision by deleting the provisions above and replace them with the notice 1.57 + * and other provisions required by the GPL or the LGPL. If you do not delete 1.58 + * the provisions above, a recipient may use your version of this file under 1.59 + * the terms of any one of the MPL, the GPL or the LGPL. 1.60 + * 1.61 + ******* END LICENSE BLOCK *******/ 1.62 + 1.63 +#include "mozHunspell.h" 1.64 +#include "nsReadableUtils.h" 1.65 +#include "nsXPIDLString.h" 1.66 +#include "nsIObserverService.h" 1.67 +#include "nsISimpleEnumerator.h" 1.68 +#include "nsIDirectoryEnumerator.h" 1.69 +#include "nsIFile.h" 1.70 +#include "nsDirectoryServiceUtils.h" 1.71 +#include "nsDirectoryServiceDefs.h" 1.72 +#include "mozISpellI18NManager.h" 1.73 +#include "nsICharsetConverterManager.h" 1.74 +#include "nsUnicharUtilCIID.h" 1.75 +#include "nsUnicharUtils.h" 1.76 +#include "nsCRT.h" 1.77 +#include "mozInlineSpellChecker.h" 1.78 +#include "mozilla/Services.h" 1.79 +#include <stdlib.h> 1.80 +#include "nsIPrefService.h" 1.81 +#include "nsIPrefBranch.h" 1.82 + 1.83 +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); 1.84 + 1.85 +NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell) 1.86 +NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell) 1.87 + 1.88 +NS_INTERFACE_MAP_BEGIN(mozHunspell) 1.89 + NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine) 1.90 + NS_INTERFACE_MAP_ENTRY(nsIObserver) 1.91 + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 1.92 + NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter) 1.93 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine) 1.94 + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell) 1.95 +NS_INTERFACE_MAP_END 1.96 + 1.97 +NS_IMPL_CYCLE_COLLECTION(mozHunspell, 1.98 + mPersonalDictionary, 1.99 + mEncoder, 1.100 + mDecoder) 1.101 + 1.102 +template<> mozilla::Atomic<size_t> mozilla::CountingAllocatorBase<HunspellAllocator>::sAmount(0); 1.103 + 1.104 +mozHunspell::mozHunspell() 1.105 + : mHunspell(nullptr) 1.106 +{ 1.107 +#ifdef DEBUG 1.108 + // There must be only one instance of this class: it reports memory based on 1.109 + // a single static count in HunspellAllocator. 1.110 + static bool hasRun = false; 1.111 + MOZ_ASSERT(!hasRun); 1.112 + hasRun = true; 1.113 +#endif 1.114 +} 1.115 + 1.116 +nsresult 1.117 +mozHunspell::Init() 1.118 +{ 1.119 + LoadDictionaryList(); 1.120 + 1.121 + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 1.122 + if (obs) { 1.123 + obs->AddObserver(this, "profile-do-change", true); 1.124 + obs->AddObserver(this, "profile-after-change", true); 1.125 + } 1.126 + 1.127 + mozilla::RegisterWeakMemoryReporter(this); 1.128 + 1.129 + return NS_OK; 1.130 +} 1.131 + 1.132 +mozHunspell::~mozHunspell() 1.133 +{ 1.134 + mozilla::UnregisterWeakMemoryReporter(this); 1.135 + 1.136 + mPersonalDictionary = nullptr; 1.137 + delete mHunspell; 1.138 +} 1.139 + 1.140 +/* attribute wstring dictionary; */ 1.141 +NS_IMETHODIMP mozHunspell::GetDictionary(char16_t **aDictionary) 1.142 +{ 1.143 + NS_ENSURE_ARG_POINTER(aDictionary); 1.144 + 1.145 + *aDictionary = ToNewUnicode(mDictionary); 1.146 + return *aDictionary ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.147 +} 1.148 + 1.149 +/* set the Dictionary. 1.150 + * This also Loads the dictionary and initializes the converter using the dictionaries converter 1.151 + */ 1.152 +NS_IMETHODIMP mozHunspell::SetDictionary(const char16_t *aDictionary) 1.153 +{ 1.154 + NS_ENSURE_ARG_POINTER(aDictionary); 1.155 + 1.156 + if (nsDependentString(aDictionary).IsEmpty()) { 1.157 + delete mHunspell; 1.158 + mHunspell = nullptr; 1.159 + mDictionary.AssignLiteral(""); 1.160 + mAffixFileName.AssignLiteral(""); 1.161 + mLanguage.AssignLiteral(""); 1.162 + mDecoder = nullptr; 1.163 + mEncoder = nullptr; 1.164 + 1.165 + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 1.166 + if (obs) { 1.167 + obs->NotifyObservers(nullptr, 1.168 + SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION, 1.169 + nullptr); 1.170 + } 1.171 + return NS_OK; 1.172 + } 1.173 + 1.174 + nsIFile* affFile = mDictionaries.GetWeak(nsDependentString(aDictionary)); 1.175 + if (!affFile) 1.176 + return NS_ERROR_FILE_NOT_FOUND; 1.177 + 1.178 + nsAutoCString dictFileName, affFileName; 1.179 + 1.180 + // XXX This isn't really good. nsIFile->NativePath isn't safe for all 1.181 + // character sets on Windows. 1.182 + // A better way would be to QI to nsIFile, and get a filehandle 1.183 + // from there. Only problem is that hunspell wants a path 1.184 + 1.185 + nsresult rv = affFile->GetNativePath(affFileName); 1.186 + NS_ENSURE_SUCCESS(rv, rv); 1.187 + 1.188 + if (mAffixFileName.Equals(affFileName.get())) 1.189 + return NS_OK; 1.190 + 1.191 + dictFileName = affFileName; 1.192 + int32_t dotPos = dictFileName.RFindChar('.'); 1.193 + if (dotPos == -1) 1.194 + return NS_ERROR_FAILURE; 1.195 + 1.196 + dictFileName.SetLength(dotPos); 1.197 + dictFileName.AppendLiteral(".dic"); 1.198 + 1.199 + // SetDictionary can be called multiple times, so we might have a 1.200 + // valid mHunspell instance which needs cleaned up. 1.201 + delete mHunspell; 1.202 + 1.203 + mDictionary = aDictionary; 1.204 + mAffixFileName = affFileName; 1.205 + 1.206 + mHunspell = new Hunspell(affFileName.get(), 1.207 + dictFileName.get()); 1.208 + if (!mHunspell) 1.209 + return NS_ERROR_OUT_OF_MEMORY; 1.210 + 1.211 + nsCOMPtr<nsICharsetConverterManager> ccm = 1.212 + do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); 1.213 + NS_ENSURE_SUCCESS(rv, rv); 1.214 + 1.215 + rv = ccm->GetUnicodeDecoder(mHunspell->get_dic_encoding(), 1.216 + getter_AddRefs(mDecoder)); 1.217 + NS_ENSURE_SUCCESS(rv, rv); 1.218 + 1.219 + rv = ccm->GetUnicodeEncoder(mHunspell->get_dic_encoding(), 1.220 + getter_AddRefs(mEncoder)); 1.221 + NS_ENSURE_SUCCESS(rv, rv); 1.222 + 1.223 + 1.224 + if (mEncoder) 1.225 + mEncoder->SetOutputErrorBehavior(mEncoder->kOnError_Signal, nullptr, '?'); 1.226 + 1.227 + int32_t pos = mDictionary.FindChar('-'); 1.228 + if (pos == -1) 1.229 + pos = mDictionary.FindChar('_'); 1.230 + 1.231 + if (pos == -1) 1.232 + mLanguage.Assign(mDictionary); 1.233 + else 1.234 + mLanguage = Substring(mDictionary, 0, pos); 1.235 + 1.236 + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 1.237 + if (obs) { 1.238 + obs->NotifyObservers(nullptr, 1.239 + SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION, 1.240 + nullptr); 1.241 + } 1.242 + 1.243 + return NS_OK; 1.244 +} 1.245 + 1.246 +/* readonly attribute wstring language; */ 1.247 +NS_IMETHODIMP mozHunspell::GetLanguage(char16_t **aLanguage) 1.248 +{ 1.249 + NS_ENSURE_ARG_POINTER(aLanguage); 1.250 + 1.251 + if (mDictionary.IsEmpty()) 1.252 + return NS_ERROR_NOT_INITIALIZED; 1.253 + 1.254 + *aLanguage = ToNewUnicode(mLanguage); 1.255 + return *aLanguage ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.256 +} 1.257 + 1.258 +/* readonly attribute boolean providesPersonalDictionary; */ 1.259 +NS_IMETHODIMP mozHunspell::GetProvidesPersonalDictionary(bool *aProvidesPersonalDictionary) 1.260 +{ 1.261 + NS_ENSURE_ARG_POINTER(aProvidesPersonalDictionary); 1.262 + 1.263 + *aProvidesPersonalDictionary = false; 1.264 + return NS_OK; 1.265 +} 1.266 + 1.267 +/* readonly attribute boolean providesWordUtils; */ 1.268 +NS_IMETHODIMP mozHunspell::GetProvidesWordUtils(bool *aProvidesWordUtils) 1.269 +{ 1.270 + NS_ENSURE_ARG_POINTER(aProvidesWordUtils); 1.271 + 1.272 + *aProvidesWordUtils = false; 1.273 + return NS_OK; 1.274 +} 1.275 + 1.276 +/* readonly attribute wstring name; */ 1.277 +NS_IMETHODIMP mozHunspell::GetName(char16_t * *aName) 1.278 +{ 1.279 + return NS_ERROR_NOT_IMPLEMENTED; 1.280 +} 1.281 + 1.282 +/* readonly attribute wstring copyright; */ 1.283 +NS_IMETHODIMP mozHunspell::GetCopyright(char16_t * *aCopyright) 1.284 +{ 1.285 + return NS_ERROR_NOT_IMPLEMENTED; 1.286 +} 1.287 + 1.288 +/* attribute mozIPersonalDictionary personalDictionary; */ 1.289 +NS_IMETHODIMP mozHunspell::GetPersonalDictionary(mozIPersonalDictionary * *aPersonalDictionary) 1.290 +{ 1.291 + *aPersonalDictionary = mPersonalDictionary; 1.292 + NS_IF_ADDREF(*aPersonalDictionary); 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 +NS_IMETHODIMP mozHunspell::SetPersonalDictionary(mozIPersonalDictionary * aPersonalDictionary) 1.297 +{ 1.298 + mPersonalDictionary = aPersonalDictionary; 1.299 + return NS_OK; 1.300 +} 1.301 + 1.302 +struct AppendNewStruct 1.303 +{ 1.304 + char16_t **dics; 1.305 + uint32_t count; 1.306 + bool failed; 1.307 +}; 1.308 + 1.309 +static PLDHashOperator 1.310 +AppendNewString(const nsAString& aString, nsIFile* aFile, void* aClosure) 1.311 +{ 1.312 + AppendNewStruct *ans = (AppendNewStruct*) aClosure; 1.313 + ans->dics[ans->count] = ToNewUnicode(aString); 1.314 + if (!ans->dics[ans->count]) { 1.315 + ans->failed = true; 1.316 + return PL_DHASH_STOP; 1.317 + } 1.318 + 1.319 + ++ans->count; 1.320 + return PL_DHASH_NEXT; 1.321 +} 1.322 + 1.323 +/* void GetDictionaryList ([array, size_is (count)] out wstring dictionaries, out uint32_t count); */ 1.324 +NS_IMETHODIMP mozHunspell::GetDictionaryList(char16_t ***aDictionaries, 1.325 + uint32_t *aCount) 1.326 +{ 1.327 + if (!aDictionaries || !aCount) 1.328 + return NS_ERROR_NULL_POINTER; 1.329 + 1.330 + AppendNewStruct ans = { 1.331 + (char16_t**) NS_Alloc(sizeof(char16_t*) * mDictionaries.Count()), 1.332 + 0, 1.333 + false 1.334 + }; 1.335 + 1.336 + // This pointer is used during enumeration 1.337 + mDictionaries.EnumerateRead(AppendNewString, &ans); 1.338 + 1.339 + if (ans.failed) { 1.340 + while (ans.count) { 1.341 + --ans.count; 1.342 + NS_Free(ans.dics[ans.count]); 1.343 + } 1.344 + NS_Free(ans.dics); 1.345 + return NS_ERROR_OUT_OF_MEMORY; 1.346 + } 1.347 + 1.348 + *aDictionaries = ans.dics; 1.349 + *aCount = ans.count; 1.350 + 1.351 + return NS_OK; 1.352 +} 1.353 + 1.354 +void 1.355 +mozHunspell::LoadDictionaryList() 1.356 +{ 1.357 + mDictionaries.Clear(); 1.358 + 1.359 + nsresult rv; 1.360 + 1.361 + nsCOMPtr<nsIProperties> dirSvc = 1.362 + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); 1.363 + if (!dirSvc) 1.364 + return; 1.365 + 1.366 + // find built in dictionaries, or dictionaries specified in 1.367 + // spellchecker.dictionary_path in prefs 1.368 + nsCOMPtr<nsIFile> dictDir; 1.369 + 1.370 + // check preferences first 1.371 + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); 1.372 + if (prefs) { 1.373 + nsCString extDictPath; 1.374 + rv = prefs->GetCharPref("spellchecker.dictionary_path", getter_Copies(extDictPath)); 1.375 + if (NS_SUCCEEDED(rv)) { 1.376 + // set the spellchecker.dictionary_path 1.377 + rv = NS_NewNativeLocalFile(extDictPath, true, getter_AddRefs(dictDir)); 1.378 + } 1.379 + } 1.380 + if (!dictDir) { 1.381 + // spellcheck.dictionary_path not found, set internal path 1.382 + rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY, 1.383 + NS_GET_IID(nsIFile), getter_AddRefs(dictDir)); 1.384 + } 1.385 + if (dictDir) { 1.386 + LoadDictionariesFromDir(dictDir); 1.387 + } 1.388 + else { 1.389 + // try to load gredir/dictionaries 1.390 + nsCOMPtr<nsIFile> greDir; 1.391 + rv = dirSvc->Get(NS_GRE_DIR, 1.392 + NS_GET_IID(nsIFile), getter_AddRefs(greDir)); 1.393 + if (NS_SUCCEEDED(rv)) { 1.394 + greDir->AppendNative(NS_LITERAL_CSTRING("dictionaries")); 1.395 + LoadDictionariesFromDir(greDir); 1.396 + } 1.397 + 1.398 + // try to load appdir/dictionaries only if different than gredir 1.399 + nsCOMPtr<nsIFile> appDir; 1.400 + rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, 1.401 + NS_GET_IID(nsIFile), getter_AddRefs(appDir)); 1.402 + bool equals; 1.403 + if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(appDir->Equals(greDir, &equals)) && !equals) { 1.404 + appDir->AppendNative(NS_LITERAL_CSTRING("dictionaries")); 1.405 + LoadDictionariesFromDir(appDir); 1.406 + } 1.407 + } 1.408 + 1.409 + // find dictionaries from extensions requiring restart 1.410 + nsCOMPtr<nsISimpleEnumerator> dictDirs; 1.411 + rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST, 1.412 + NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dictDirs)); 1.413 + if (NS_FAILED(rv)) 1.414 + return; 1.415 + 1.416 + bool hasMore; 1.417 + while (NS_SUCCEEDED(dictDirs->HasMoreElements(&hasMore)) && hasMore) { 1.418 + nsCOMPtr<nsISupports> elem; 1.419 + dictDirs->GetNext(getter_AddRefs(elem)); 1.420 + 1.421 + dictDir = do_QueryInterface(elem); 1.422 + if (dictDir) 1.423 + LoadDictionariesFromDir(dictDir); 1.424 + } 1.425 + 1.426 + // find dictionaries from restartless extensions 1.427 + for (int32_t i = 0; i < mDynamicDirectories.Count(); i++) { 1.428 + LoadDictionariesFromDir(mDynamicDirectories[i]); 1.429 + } 1.430 + 1.431 + // Now we have finished updating the list of dictionaries, update the current 1.432 + // dictionary and any editors which may use it. 1.433 + mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking(); 1.434 + 1.435 + // Check if the current dictionary is still available. 1.436 + // If not, try to replace it with another dictionary of the same language. 1.437 + if (!mDictionary.IsEmpty()) { 1.438 + rv = SetDictionary(mDictionary.get()); 1.439 + if (NS_SUCCEEDED(rv)) 1.440 + return; 1.441 + } 1.442 + 1.443 + // If the current dictionary has gone, and we don't have a good replacement, 1.444 + // set no current dictionary. 1.445 + if (!mDictionary.IsEmpty()) { 1.446 + SetDictionary(EmptyString().get()); 1.447 + } 1.448 +} 1.449 + 1.450 +NS_IMETHODIMP 1.451 +mozHunspell::LoadDictionariesFromDir(nsIFile* aDir) 1.452 +{ 1.453 + nsresult rv; 1.454 + 1.455 + bool check = false; 1.456 + rv = aDir->Exists(&check); 1.457 + if (NS_FAILED(rv) || !check) 1.458 + return NS_ERROR_UNEXPECTED; 1.459 + 1.460 + rv = aDir->IsDirectory(&check); 1.461 + if (NS_FAILED(rv) || !check) 1.462 + return NS_ERROR_UNEXPECTED; 1.463 + 1.464 + nsCOMPtr<nsISimpleEnumerator> e; 1.465 + rv = aDir->GetDirectoryEntries(getter_AddRefs(e)); 1.466 + if (NS_FAILED(rv)) 1.467 + return NS_ERROR_UNEXPECTED; 1.468 + 1.469 + nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e)); 1.470 + if (!files) 1.471 + return NS_ERROR_UNEXPECTED; 1.472 + 1.473 + nsCOMPtr<nsIFile> file; 1.474 + while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file) { 1.475 + nsAutoString leafName; 1.476 + file->GetLeafName(leafName); 1.477 + if (!StringEndsWith(leafName, NS_LITERAL_STRING(".dic"))) 1.478 + continue; 1.479 + 1.480 + nsAutoString dict(leafName); 1.481 + dict.SetLength(dict.Length() - 4); // magic length of ".dic" 1.482 + 1.483 + // check for the presence of the .aff file 1.484 + leafName = dict; 1.485 + leafName.AppendLiteral(".aff"); 1.486 + file->SetLeafName(leafName); 1.487 + rv = file->Exists(&check); 1.488 + if (NS_FAILED(rv) || !check) 1.489 + continue; 1.490 + 1.491 +#ifdef DEBUG_bsmedberg 1.492 + printf("Adding dictionary: %s\n", NS_ConvertUTF16toUTF8(dict).get()); 1.493 +#endif 1.494 + 1.495 + mDictionaries.Put(dict, file); 1.496 + } 1.497 + 1.498 + return NS_OK; 1.499 +} 1.500 + 1.501 +nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst) 1.502 +{ 1.503 + NS_ENSURE_ARG_POINTER(aDst); 1.504 + NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER); 1.505 + 1.506 + int32_t outLength; 1.507 + int32_t inLength = NS_strlen(aStr); 1.508 + nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength); 1.509 + NS_ENSURE_SUCCESS(rv, rv); 1.510 + 1.511 + *aDst = (char *) nsMemory::Alloc(sizeof(char) * (outLength+1)); 1.512 + NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY); 1.513 + 1.514 + rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength); 1.515 + if (NS_SUCCEEDED(rv)) 1.516 + (*aDst)[outLength] = '\0'; 1.517 + 1.518 + return rv; 1.519 +} 1.520 + 1.521 +/* boolean Check (in wstring word); */ 1.522 +NS_IMETHODIMP mozHunspell::Check(const char16_t *aWord, bool *aResult) 1.523 +{ 1.524 + NS_ENSURE_ARG_POINTER(aWord); 1.525 + NS_ENSURE_ARG_POINTER(aResult); 1.526 + NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE); 1.527 + 1.528 + nsXPIDLCString charsetWord; 1.529 + nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord)); 1.530 + NS_ENSURE_SUCCESS(rv, rv); 1.531 + 1.532 + *aResult = !!mHunspell->spell(charsetWord); 1.533 + 1.534 + 1.535 + if (!*aResult && mPersonalDictionary) 1.536 + rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult); 1.537 + 1.538 + return rv; 1.539 +} 1.540 + 1.541 +/* void Suggest (in wstring word, [array, size_is (count)] out wstring suggestions, out uint32_t count); */ 1.542 +NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestions, uint32_t *aSuggestionCount) 1.543 +{ 1.544 + NS_ENSURE_ARG_POINTER(aSuggestions); 1.545 + NS_ENSURE_ARG_POINTER(aSuggestionCount); 1.546 + NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE); 1.547 + 1.548 + nsresult rv; 1.549 + *aSuggestionCount = 0; 1.550 + 1.551 + nsXPIDLCString charsetWord; 1.552 + rv = ConvertCharset(aWord, getter_Copies(charsetWord)); 1.553 + NS_ENSURE_SUCCESS(rv, rv); 1.554 + 1.555 + char ** wlst; 1.556 + *aSuggestionCount = mHunspell->suggest(&wlst, charsetWord); 1.557 + 1.558 + if (*aSuggestionCount) { 1.559 + *aSuggestions = (char16_t **)nsMemory::Alloc(*aSuggestionCount * sizeof(char16_t *)); 1.560 + if (*aSuggestions) { 1.561 + uint32_t index = 0; 1.562 + for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) { 1.563 + // Convert the suggestion to utf16 1.564 + int32_t inLength = strlen(wlst[index]); 1.565 + int32_t outLength; 1.566 + rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength); 1.567 + if (NS_SUCCEEDED(rv)) 1.568 + { 1.569 + (*aSuggestions)[index] = (char16_t *) nsMemory::Alloc(sizeof(char16_t) * (outLength+1)); 1.570 + if ((*aSuggestions)[index]) 1.571 + { 1.572 + rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength); 1.573 + if (NS_SUCCEEDED(rv)) 1.574 + (*aSuggestions)[index][outLength] = 0; 1.575 + } 1.576 + else 1.577 + rv = NS_ERROR_OUT_OF_MEMORY; 1.578 + } 1.579 + } 1.580 + 1.581 + if (NS_FAILED(rv)) 1.582 + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the char16_t strings up to the point at which the error occurred 1.583 + } 1.584 + else // if (*aSuggestions) 1.585 + rv = NS_ERROR_OUT_OF_MEMORY; 1.586 + } 1.587 + 1.588 + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst); 1.589 + return rv; 1.590 +} 1.591 + 1.592 +NS_IMETHODIMP 1.593 +mozHunspell::Observe(nsISupports* aSubj, const char *aTopic, 1.594 + const char16_t *aData) 1.595 +{ 1.596 + NS_ASSERTION(!strcmp(aTopic, "profile-do-change") 1.597 + || !strcmp(aTopic, "profile-after-change"), 1.598 + "Unexpected observer topic"); 1.599 + 1.600 + LoadDictionaryList(); 1.601 + 1.602 + return NS_OK; 1.603 +} 1.604 + 1.605 +/* void addDirectory(in nsIFile dir); */ 1.606 +NS_IMETHODIMP mozHunspell::AddDirectory(nsIFile *aDir) 1.607 +{ 1.608 + mDynamicDirectories.AppendObject(aDir); 1.609 + LoadDictionaryList(); 1.610 + return NS_OK; 1.611 +} 1.612 + 1.613 +/* void removeDirectory(in nsIFile dir); */ 1.614 +NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir) 1.615 +{ 1.616 + mDynamicDirectories.RemoveObject(aDir); 1.617 + LoadDictionaryList(); 1.618 + return NS_OK; 1.619 +}