extensions/spellcheck/hunspell/src/mozHunspell.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /******* BEGIN LICENSE BLOCK *******
     2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
     3  *
     4  * The contents of this file are subject to the Mozilla Public License Version
     5  * 1.1 (the "License"); you may not use this file except in compliance with
     6  * the License. You may obtain a copy of the License at
     7  * http://www.mozilla.org/MPL/
     8  *
     9  * Software distributed under the License is distributed on an "AS IS" basis,
    10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    11  * for the specific language governing rights and limitations under the
    12  * License.
    13  *
    14  * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
    15  * and László Németh (Hunspell). Portions created by the Initial Developers
    16  * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
    17  *
    18  * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
    19  *                 David Einstein (deinst@world.std.com)
    20  *                 Michiel van Leeuwen (mvl@exedo.nl)
    21  *                 Caolan McNamara (cmc@openoffice.org)
    22  *                 László Németh (nemethl@gyorsposta.hu)
    23  *                 Davide Prina
    24  *                 Giuseppe Modugno
    25  *                 Gianluca Turconi
    26  *                 Simon Brouwer
    27  *                 Noll Janos
    28  *                 Biro Arpad
    29  *                 Goldman Eleonora
    30  *                 Sarlos Tamas
    31  *                 Bencsath Boldizsar
    32  *                 Halacsy Peter
    33  *                 Dvornik Laszlo
    34  *                 Gefferth Andras
    35  *                 Nagy Viktor
    36  *                 Varga Daniel
    37  *                 Chris Halls
    38  *                 Rene Engelhard
    39  *                 Bram Moolenaar
    40  *                 Dafydd Jones
    41  *                 Harri Pitkanen
    42  *                 Andras Timar
    43  *                 Tor Lillqvist
    44  *                 Jesper Kristensen (mail@jesperkristensen.dk)
    45  *
    46  * Alternatively, the contents of this file may be used under the terms of
    47  * either the GNU General Public License Version 2 or later (the "GPL"), or
    48  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    49  * in which case the provisions of the GPL or the LGPL are applicable instead
    50  * of those above. If you wish to allow use of your version of this file only
    51  * under the terms of either the GPL or the LGPL, and not to allow others to
    52  * use your version of this file under the terms of the MPL, indicate your
    53  * decision by deleting the provisions above and replace them with the notice
    54  * and other provisions required by the GPL or the LGPL. If you do not delete
    55  * the provisions above, a recipient may use your version of this file under
    56  * the terms of any one of the MPL, the GPL or the LGPL.
    57  *
    58  ******* END LICENSE BLOCK *******/
    60 #include "mozHunspell.h"
    61 #include "nsReadableUtils.h"
    62 #include "nsXPIDLString.h"
    63 #include "nsIObserverService.h"
    64 #include "nsISimpleEnumerator.h"
    65 #include "nsIDirectoryEnumerator.h"
    66 #include "nsIFile.h"
    67 #include "nsDirectoryServiceUtils.h"
    68 #include "nsDirectoryServiceDefs.h"
    69 #include "mozISpellI18NManager.h"
    70 #include "nsICharsetConverterManager.h"
    71 #include "nsUnicharUtilCIID.h"
    72 #include "nsUnicharUtils.h"
    73 #include "nsCRT.h"
    74 #include "mozInlineSpellChecker.h"
    75 #include "mozilla/Services.h"
    76 #include <stdlib.h>
    77 #include "nsIPrefService.h"
    78 #include "nsIPrefBranch.h"
    80 static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
    82 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
    83 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
    85 NS_INTERFACE_MAP_BEGIN(mozHunspell)
    86   NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
    87   NS_INTERFACE_MAP_ENTRY(nsIObserver)
    88   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    89   NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
    90   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
    91   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell)
    92 NS_INTERFACE_MAP_END
    94 NS_IMPL_CYCLE_COLLECTION(mozHunspell,
    95                          mPersonalDictionary,
    96                          mEncoder,
    97                          mDecoder)
    99 template<> mozilla::Atomic<size_t> mozilla::CountingAllocatorBase<HunspellAllocator>::sAmount(0);
   101 mozHunspell::mozHunspell()
   102   : mHunspell(nullptr)
   103 {
   104 #ifdef DEBUG
   105   // There must be only one instance of this class: it reports memory based on
   106   // a single static count in HunspellAllocator.
   107   static bool hasRun = false;
   108   MOZ_ASSERT(!hasRun);
   109   hasRun = true;
   110 #endif
   111 }
   113 nsresult
   114 mozHunspell::Init()
   115 {
   116   LoadDictionaryList();
   118   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   119   if (obs) {
   120     obs->AddObserver(this, "profile-do-change", true);
   121     obs->AddObserver(this, "profile-after-change", true);
   122   }
   124   mozilla::RegisterWeakMemoryReporter(this);
   126   return NS_OK;
   127 }
   129 mozHunspell::~mozHunspell()
   130 {
   131   mozilla::UnregisterWeakMemoryReporter(this);
   133   mPersonalDictionary = nullptr;
   134   delete mHunspell;
   135 }
   137 /* attribute wstring dictionary; */
   138 NS_IMETHODIMP mozHunspell::GetDictionary(char16_t **aDictionary)
   139 {
   140   NS_ENSURE_ARG_POINTER(aDictionary);
   142   *aDictionary = ToNewUnicode(mDictionary);
   143   return *aDictionary ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   144 }
   146 /* set the Dictionary.
   147  * This also Loads the dictionary and initializes the converter using the dictionaries converter
   148  */
   149 NS_IMETHODIMP mozHunspell::SetDictionary(const char16_t *aDictionary)
   150 {
   151   NS_ENSURE_ARG_POINTER(aDictionary);
   153   if (nsDependentString(aDictionary).IsEmpty()) {
   154     delete mHunspell;
   155     mHunspell = nullptr;
   156     mDictionary.AssignLiteral("");
   157     mAffixFileName.AssignLiteral("");
   158     mLanguage.AssignLiteral("");
   159     mDecoder = nullptr;
   160     mEncoder = nullptr;
   162     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   163     if (obs) {
   164       obs->NotifyObservers(nullptr,
   165                            SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
   166                            nullptr);
   167     }
   168     return NS_OK;
   169   }
   171   nsIFile* affFile = mDictionaries.GetWeak(nsDependentString(aDictionary));
   172   if (!affFile)
   173     return NS_ERROR_FILE_NOT_FOUND;
   175   nsAutoCString dictFileName, affFileName;
   177   // XXX This isn't really good. nsIFile->NativePath isn't safe for all
   178   // character sets on Windows.
   179   // A better way would be to QI to nsIFile, and get a filehandle
   180   // from there. Only problem is that hunspell wants a path
   182   nsresult rv = affFile->GetNativePath(affFileName);
   183   NS_ENSURE_SUCCESS(rv, rv);
   185   if (mAffixFileName.Equals(affFileName.get()))
   186     return NS_OK;
   188   dictFileName = affFileName;
   189   int32_t dotPos = dictFileName.RFindChar('.');
   190   if (dotPos == -1)
   191     return NS_ERROR_FAILURE;
   193   dictFileName.SetLength(dotPos);
   194   dictFileName.AppendLiteral(".dic");
   196   // SetDictionary can be called multiple times, so we might have a
   197   // valid mHunspell instance which needs cleaned up.
   198   delete mHunspell;
   200   mDictionary = aDictionary;
   201   mAffixFileName = affFileName;
   203   mHunspell = new Hunspell(affFileName.get(),
   204                          dictFileName.get());
   205   if (!mHunspell)
   206     return NS_ERROR_OUT_OF_MEMORY;
   208   nsCOMPtr<nsICharsetConverterManager> ccm =
   209     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
   210   NS_ENSURE_SUCCESS(rv, rv);
   212   rv = ccm->GetUnicodeDecoder(mHunspell->get_dic_encoding(),
   213                               getter_AddRefs(mDecoder));
   214   NS_ENSURE_SUCCESS(rv, rv);
   216   rv = ccm->GetUnicodeEncoder(mHunspell->get_dic_encoding(),
   217                               getter_AddRefs(mEncoder));
   218   NS_ENSURE_SUCCESS(rv, rv);
   221   if (mEncoder)
   222     mEncoder->SetOutputErrorBehavior(mEncoder->kOnError_Signal, nullptr, '?');
   224   int32_t pos = mDictionary.FindChar('-');
   225   if (pos == -1)
   226     pos = mDictionary.FindChar('_');
   228   if (pos == -1)
   229     mLanguage.Assign(mDictionary);
   230   else
   231     mLanguage = Substring(mDictionary, 0, pos);
   233   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   234   if (obs) {
   235     obs->NotifyObservers(nullptr,
   236                          SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
   237                          nullptr);
   238   }
   240   return NS_OK;
   241 }
   243 /* readonly attribute wstring language; */
   244 NS_IMETHODIMP mozHunspell::GetLanguage(char16_t **aLanguage)
   245 {
   246   NS_ENSURE_ARG_POINTER(aLanguage);
   248   if (mDictionary.IsEmpty())
   249     return NS_ERROR_NOT_INITIALIZED;
   251   *aLanguage = ToNewUnicode(mLanguage);
   252   return *aLanguage ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   253 }
   255 /* readonly attribute boolean providesPersonalDictionary; */
   256 NS_IMETHODIMP mozHunspell::GetProvidesPersonalDictionary(bool *aProvidesPersonalDictionary)
   257 {
   258   NS_ENSURE_ARG_POINTER(aProvidesPersonalDictionary);
   260   *aProvidesPersonalDictionary = false;
   261   return NS_OK;
   262 }
   264 /* readonly attribute boolean providesWordUtils; */
   265 NS_IMETHODIMP mozHunspell::GetProvidesWordUtils(bool *aProvidesWordUtils)
   266 {
   267   NS_ENSURE_ARG_POINTER(aProvidesWordUtils);
   269   *aProvidesWordUtils = false;
   270   return NS_OK;
   271 }
   273 /* readonly attribute wstring name; */
   274 NS_IMETHODIMP mozHunspell::GetName(char16_t * *aName)
   275 {
   276   return NS_ERROR_NOT_IMPLEMENTED;
   277 }
   279 /* readonly attribute wstring copyright; */
   280 NS_IMETHODIMP mozHunspell::GetCopyright(char16_t * *aCopyright)
   281 {
   282   return NS_ERROR_NOT_IMPLEMENTED;
   283 }
   285 /* attribute mozIPersonalDictionary personalDictionary; */
   286 NS_IMETHODIMP mozHunspell::GetPersonalDictionary(mozIPersonalDictionary * *aPersonalDictionary)
   287 {
   288   *aPersonalDictionary = mPersonalDictionary;
   289   NS_IF_ADDREF(*aPersonalDictionary);
   290   return NS_OK;
   291 }
   293 NS_IMETHODIMP mozHunspell::SetPersonalDictionary(mozIPersonalDictionary * aPersonalDictionary)
   294 {
   295   mPersonalDictionary = aPersonalDictionary;
   296   return NS_OK;
   297 }
   299 struct AppendNewStruct
   300 {
   301   char16_t **dics;
   302   uint32_t count;
   303   bool failed;
   304 };
   306 static PLDHashOperator
   307 AppendNewString(const nsAString& aString, nsIFile* aFile, void* aClosure)
   308 {
   309   AppendNewStruct *ans = (AppendNewStruct*) aClosure;
   310   ans->dics[ans->count] = ToNewUnicode(aString);
   311   if (!ans->dics[ans->count]) {
   312     ans->failed = true;
   313     return PL_DHASH_STOP;
   314   }
   316   ++ans->count;
   317   return PL_DHASH_NEXT;
   318 }
   320 /* void GetDictionaryList ([array, size_is (count)] out wstring dictionaries, out uint32_t count); */
   321 NS_IMETHODIMP mozHunspell::GetDictionaryList(char16_t ***aDictionaries,
   322                                             uint32_t *aCount)
   323 {
   324   if (!aDictionaries || !aCount)
   325     return NS_ERROR_NULL_POINTER;
   327   AppendNewStruct ans = {
   328     (char16_t**) NS_Alloc(sizeof(char16_t*) * mDictionaries.Count()),
   329     0,
   330     false
   331   };
   333   // This pointer is used during enumeration
   334   mDictionaries.EnumerateRead(AppendNewString, &ans);
   336   if (ans.failed) {
   337     while (ans.count) {
   338       --ans.count;
   339       NS_Free(ans.dics[ans.count]);
   340     }
   341     NS_Free(ans.dics);
   342     return NS_ERROR_OUT_OF_MEMORY;
   343   }
   345   *aDictionaries = ans.dics;
   346   *aCount = ans.count;
   348   return NS_OK;
   349 }
   351 void
   352 mozHunspell::LoadDictionaryList()
   353 {
   354   mDictionaries.Clear();
   356   nsresult rv;
   358   nsCOMPtr<nsIProperties> dirSvc =
   359     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
   360   if (!dirSvc)
   361     return;
   363   // find built in dictionaries, or dictionaries specified in
   364   // spellchecker.dictionary_path in prefs
   365   nsCOMPtr<nsIFile> dictDir;
   367   // check preferences first
   368   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   369   if (prefs) {
   370     nsCString extDictPath;
   371     rv = prefs->GetCharPref("spellchecker.dictionary_path", getter_Copies(extDictPath));
   372     if (NS_SUCCEEDED(rv)) {
   373       // set the spellchecker.dictionary_path
   374       rv = NS_NewNativeLocalFile(extDictPath, true, getter_AddRefs(dictDir));
   375     }
   376   }
   377   if (!dictDir) {
   378     // spellcheck.dictionary_path not found, set internal path
   379     rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY,
   380                      NS_GET_IID(nsIFile), getter_AddRefs(dictDir));
   381   }
   382   if (dictDir) {
   383     LoadDictionariesFromDir(dictDir);
   384   }
   385   else {
   386     // try to load gredir/dictionaries
   387     nsCOMPtr<nsIFile> greDir;
   388     rv = dirSvc->Get(NS_GRE_DIR,
   389                      NS_GET_IID(nsIFile), getter_AddRefs(greDir));
   390     if (NS_SUCCEEDED(rv)) {
   391       greDir->AppendNative(NS_LITERAL_CSTRING("dictionaries"));
   392       LoadDictionariesFromDir(greDir);
   393     }
   395     // try to load appdir/dictionaries only if different than gredir
   396     nsCOMPtr<nsIFile> appDir;
   397     rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
   398                      NS_GET_IID(nsIFile), getter_AddRefs(appDir));
   399     bool equals;
   400     if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(appDir->Equals(greDir, &equals)) && !equals) {
   401       appDir->AppendNative(NS_LITERAL_CSTRING("dictionaries"));
   402       LoadDictionariesFromDir(appDir);
   403     }
   404   }
   406   // find dictionaries from extensions requiring restart
   407   nsCOMPtr<nsISimpleEnumerator> dictDirs;
   408   rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST,
   409                    NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dictDirs));
   410   if (NS_FAILED(rv))
   411     return;
   413   bool hasMore;
   414   while (NS_SUCCEEDED(dictDirs->HasMoreElements(&hasMore)) && hasMore) {
   415     nsCOMPtr<nsISupports> elem;
   416     dictDirs->GetNext(getter_AddRefs(elem));
   418     dictDir = do_QueryInterface(elem);
   419     if (dictDir)
   420       LoadDictionariesFromDir(dictDir);
   421   }
   423   // find dictionaries from restartless extensions
   424   for (int32_t i = 0; i < mDynamicDirectories.Count(); i++) {
   425     LoadDictionariesFromDir(mDynamicDirectories[i]);
   426   }
   428   // Now we have finished updating the list of dictionaries, update the current
   429   // dictionary and any editors which may use it.
   430   mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
   432   // Check if the current dictionary is still available.
   433   // If not, try to replace it with another dictionary of the same language.
   434   if (!mDictionary.IsEmpty()) {
   435     rv = SetDictionary(mDictionary.get());
   436     if (NS_SUCCEEDED(rv))
   437       return;
   438   }
   440   // If the current dictionary has gone, and we don't have a good replacement,
   441   // set no current dictionary.
   442   if (!mDictionary.IsEmpty()) {
   443     SetDictionary(EmptyString().get());
   444   }
   445 }
   447 NS_IMETHODIMP
   448 mozHunspell::LoadDictionariesFromDir(nsIFile* aDir)
   449 {
   450   nsresult rv;
   452   bool check = false;
   453   rv = aDir->Exists(&check);
   454   if (NS_FAILED(rv) || !check)
   455     return NS_ERROR_UNEXPECTED;
   457   rv = aDir->IsDirectory(&check);
   458   if (NS_FAILED(rv) || !check)
   459     return NS_ERROR_UNEXPECTED;
   461   nsCOMPtr<nsISimpleEnumerator> e;
   462   rv = aDir->GetDirectoryEntries(getter_AddRefs(e));
   463   if (NS_FAILED(rv))
   464     return NS_ERROR_UNEXPECTED;
   466   nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e));
   467   if (!files)
   468     return NS_ERROR_UNEXPECTED;
   470   nsCOMPtr<nsIFile> file;
   471   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file) {
   472     nsAutoString leafName;
   473     file->GetLeafName(leafName);
   474     if (!StringEndsWith(leafName, NS_LITERAL_STRING(".dic")))
   475       continue;
   477     nsAutoString dict(leafName);
   478     dict.SetLength(dict.Length() - 4); // magic length of ".dic"
   480     // check for the presence of the .aff file
   481     leafName = dict;
   482     leafName.AppendLiteral(".aff");
   483     file->SetLeafName(leafName);
   484     rv = file->Exists(&check);
   485     if (NS_FAILED(rv) || !check)
   486       continue;
   488 #ifdef DEBUG_bsmedberg
   489     printf("Adding dictionary: %s\n", NS_ConvertUTF16toUTF8(dict).get());
   490 #endif
   492     mDictionaries.Put(dict, file);
   493   }
   495   return NS_OK;
   496 }
   498 nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
   499 {
   500   NS_ENSURE_ARG_POINTER(aDst);
   501   NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER);
   503   int32_t outLength;
   504   int32_t inLength = NS_strlen(aStr);
   505   nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength);
   506   NS_ENSURE_SUCCESS(rv, rv);
   508   *aDst = (char *) nsMemory::Alloc(sizeof(char) * (outLength+1));
   509   NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY);
   511   rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength);
   512   if (NS_SUCCEEDED(rv))
   513     (*aDst)[outLength] = '\0';
   515   return rv;
   516 }
   518 /* boolean Check (in wstring word); */
   519 NS_IMETHODIMP mozHunspell::Check(const char16_t *aWord, bool *aResult)
   520 {
   521   NS_ENSURE_ARG_POINTER(aWord);
   522   NS_ENSURE_ARG_POINTER(aResult);
   523   NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
   525   nsXPIDLCString charsetWord;
   526   nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord));
   527   NS_ENSURE_SUCCESS(rv, rv);
   529   *aResult = !!mHunspell->spell(charsetWord);
   532   if (!*aResult && mPersonalDictionary)
   533     rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
   535   return rv;
   536 }
   538 /* void Suggest (in wstring word, [array, size_is (count)] out wstring suggestions, out uint32_t count); */
   539 NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestions, uint32_t *aSuggestionCount)
   540 {
   541   NS_ENSURE_ARG_POINTER(aSuggestions);
   542   NS_ENSURE_ARG_POINTER(aSuggestionCount);
   543   NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
   545   nsresult rv;
   546   *aSuggestionCount = 0;
   548   nsXPIDLCString charsetWord;
   549   rv = ConvertCharset(aWord, getter_Copies(charsetWord));
   550   NS_ENSURE_SUCCESS(rv, rv);
   552   char ** wlst;
   553   *aSuggestionCount = mHunspell->suggest(&wlst, charsetWord);
   555   if (*aSuggestionCount) {
   556     *aSuggestions  = (char16_t **)nsMemory::Alloc(*aSuggestionCount * sizeof(char16_t *));
   557     if (*aSuggestions) {
   558       uint32_t index = 0;
   559       for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
   560         // Convert the suggestion to utf16
   561         int32_t inLength = strlen(wlst[index]);
   562         int32_t outLength;
   563         rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength);
   564         if (NS_SUCCEEDED(rv))
   565         {
   566           (*aSuggestions)[index] = (char16_t *) nsMemory::Alloc(sizeof(char16_t) * (outLength+1));
   567           if ((*aSuggestions)[index])
   568           {
   569             rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength);
   570             if (NS_SUCCEEDED(rv))
   571               (*aSuggestions)[index][outLength] = 0;
   572           }
   573           else
   574             rv = NS_ERROR_OUT_OF_MEMORY;
   575         }
   576       }
   578       if (NS_FAILED(rv))
   579         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the char16_t strings up to the point at which the error occurred
   580     }
   581     else // if (*aSuggestions)
   582       rv = NS_ERROR_OUT_OF_MEMORY;
   583   }
   585   NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst);
   586   return rv;
   587 }
   589 NS_IMETHODIMP
   590 mozHunspell::Observe(nsISupports* aSubj, const char *aTopic,
   591                     const char16_t *aData)
   592 {
   593   NS_ASSERTION(!strcmp(aTopic, "profile-do-change")
   594                || !strcmp(aTopic, "profile-after-change"),
   595                "Unexpected observer topic");
   597   LoadDictionaryList();
   599   return NS_OK;
   600 }
   602 /* void addDirectory(in nsIFile dir); */
   603 NS_IMETHODIMP mozHunspell::AddDirectory(nsIFile *aDir)
   604 {
   605   mDynamicDirectories.AppendObject(aDir);
   606   LoadDictionaryList();
   607   return NS_OK;
   608 }
   610 /* void removeDirectory(in nsIFile dir); */
   611 NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir)
   612 {
   613   mDynamicDirectories.RemoveObject(aDir);
   614   LoadDictionaryList();
   615   return NS_OK;
   616 }

mercurial