LCOV - code coverage report
Current view: directory - extensions/spellcheck/hunspell/src - mozHunspell.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 280 148 52.9 %
Date: 2012-06-02 Functions: 45 20 44.4 %

       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 *******/
      59                 : 
      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 "nsIMemoryReporter.h"
      78                 : 
      79                 : static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
      80                 : static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
      81                 : 
      82              11 : NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
      83              11 : NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
      84                 : 
      85              22 : NS_INTERFACE_MAP_BEGIN(mozHunspell)
      86              22 :   NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
      87              19 :   NS_INTERFACE_MAP_ENTRY(nsIObserver)
      88              19 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      89              17 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
      90              14 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell)
      91               8 : NS_INTERFACE_MAP_END
      92                 : 
      93            1464 : NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
      94                 :                            mPersonalDictionary,
      95                 :                            mEncoder,
      96                 :                            mDecoder)
      97                 : 
      98                 : // Memory reporting stuff.
      99                 : static PRInt64 gHunspellAllocatedSize = 0;
     100                 : 
     101            5007 : NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HunspellMallocSizeOfForCounterInc, "hunspell")
     102            5015 : NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(HunspellMallocSizeOfForCounterDec)
     103                 : 
     104            5007 : void HunspellReportMemoryAllocation(void* ptr) {
     105            5007 :   gHunspellAllocatedSize += HunspellMallocSizeOfForCounterInc(ptr);
     106            5007 : }
     107            5015 : void HunspellReportMemoryDeallocation(void* ptr) {
     108            5015 :   gHunspellAllocatedSize -= HunspellMallocSizeOfForCounterDec(ptr);
     109            5015 : }
     110               0 : static PRInt64 HunspellGetCurrentAllocatedSize() {
     111               0 :   return gHunspellAllocatedSize;
     112                 : }
     113                 : 
     114               1 : NS_MEMORY_REPORTER_IMPLEMENT(Hunspell,
     115                 :     "explicit/spell-check",
     116                 :     KIND_HEAP,
     117                 :     UNITS_BYTES,
     118                 :     HunspellGetCurrentAllocatedSize,
     119                 :     "Memory used by the Hunspell spell checking engine.  This number accounts "
     120                 :     "for the memory in use by Hunspell's internal data structures."
     121               3 : )
     122                 : 
     123                 : nsresult
     124               1 : mozHunspell::Init()
     125                 : {
     126               1 :   if (!mDictionaries.Init())
     127               0 :     return NS_ERROR_OUT_OF_MEMORY;
     128                 : 
     129               1 :   LoadDictionaryList();
     130                 : 
     131               2 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     132               1 :   if (obs) {
     133               1 :     obs->AddObserver(this, "profile-do-change", true);
     134               1 :     obs->AddObserver(this, "profile-after-change", true);
     135                 :   }
     136                 : 
     137               1 :   mHunspellReporter = new NS_MEMORY_REPORTER_NAME(Hunspell);
     138               1 :   NS_RegisterMemoryReporter(mHunspellReporter);
     139                 : 
     140               1 :   return NS_OK;
     141                 : }
     142                 : 
     143               3 : mozHunspell::~mozHunspell()
     144                 : {
     145               1 :   mPersonalDictionary = nsnull;
     146               1 :   delete mHunspell;
     147                 : 
     148               1 :   NS_UnregisterMemoryReporter(mHunspellReporter);
     149               4 : }
     150                 : 
     151                 : /* attribute wstring dictionary; */
     152               0 : NS_IMETHODIMP mozHunspell::GetDictionary(PRUnichar **aDictionary)
     153                 : {
     154               0 :   NS_ENSURE_ARG_POINTER(aDictionary);
     155                 : 
     156               0 :   *aDictionary = ToNewUnicode(mDictionary);
     157               0 :   return *aDictionary ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     158                 : }
     159                 : 
     160                 : /* set the Dictionary.
     161                 :  * This also Loads the dictionary and initializes the converter using the dictionaries converter
     162                 :  */
     163             110 : NS_IMETHODIMP mozHunspell::SetDictionary(const PRUnichar *aDictionary)
     164                 : {
     165             110 :   NS_ENSURE_ARG_POINTER(aDictionary);
     166                 : 
     167             110 :   if (nsDependentString(aDictionary).IsEmpty()) {
     168               0 :     delete mHunspell;
     169               0 :     mHunspell = nsnull;
     170               0 :     mDictionary.AssignLiteral("");
     171               0 :     mAffixFileName.AssignLiteral("");
     172               0 :     mLanguage.AssignLiteral("");
     173               0 :     mDecoder = nsnull;
     174               0 :     mEncoder = nsnull;
     175                 : 
     176               0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     177               0 :     if (obs) {
     178               0 :       obs->NotifyObservers(nsnull,
     179                 :                            SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
     180               0 :                            nsnull);
     181                 :     }
     182               0 :     return NS_OK;
     183                 :   }
     184                 : 
     185             110 :   nsIFile* affFile = mDictionaries.GetWeak(nsDependentString(aDictionary));
     186             110 :   if (!affFile)
     187               0 :     return NS_ERROR_FILE_NOT_FOUND;
     188                 : 
     189             220 :   nsCAutoString dictFileName, affFileName;
     190                 : 
     191                 :   // XXX This isn't really good. nsIFile->NativePath isn't safe for all
     192                 :   // character sets on Windows.
     193                 :   // A better way would be to QI to nsILocalFile, and get a filehandle
     194                 :   // from there. Only problem is that hunspell wants a path
     195                 : 
     196             110 :   nsresult rv = affFile->GetNativePath(affFileName);
     197             110 :   NS_ENSURE_SUCCESS(rv, rv);
     198                 : 
     199             110 :   if (mAffixFileName.Equals(affFileName.get()))
     200               0 :     return NS_OK;
     201                 : 
     202             110 :   dictFileName = affFileName;
     203             110 :   PRInt32 dotPos = dictFileName.RFindChar('.');
     204             110 :   if (dotPos == -1)
     205               0 :     return NS_ERROR_FAILURE;
     206                 : 
     207             110 :   dictFileName.SetLength(dotPos);
     208             110 :   dictFileName.AppendLiteral(".dic");
     209                 : 
     210                 :   // SetDictionary can be called multiple times, so we might have a
     211                 :   // valid mHunspell instance which needs cleaned up.
     212             110 :   delete mHunspell;
     213                 : 
     214             110 :   mDictionary = aDictionary;
     215             110 :   mAffixFileName = affFileName;
     216                 : 
     217                 :   mHunspell = new Hunspell(affFileName.get(),
     218             220 :                          dictFileName.get());
     219             110 :   if (!mHunspell)
     220               0 :     return NS_ERROR_OUT_OF_MEMORY;
     221                 : 
     222                 :   nsCOMPtr<nsICharsetConverterManager> ccm =
     223             220 :     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
     224             110 :   NS_ENSURE_SUCCESS(rv, rv);
     225                 : 
     226             220 :   rv = ccm->GetUnicodeDecoder(mHunspell->get_dic_encoding(),
     227             220 :                               getter_AddRefs(mDecoder));
     228             110 :   NS_ENSURE_SUCCESS(rv, rv);
     229                 : 
     230             220 :   rv = ccm->GetUnicodeEncoder(mHunspell->get_dic_encoding(),
     231             220 :                               getter_AddRefs(mEncoder));
     232             110 :   NS_ENSURE_SUCCESS(rv, rv);
     233                 : 
     234                 : 
     235             110 :   if (mEncoder)
     236             110 :     mEncoder->SetOutputErrorBehavior(mEncoder->kOnError_Signal, nsnull, '?');
     237                 : 
     238             110 :   PRInt32 pos = mDictionary.FindChar('-');
     239             110 :   if (pos == -1)
     240             110 :     pos = mDictionary.FindChar('_');
     241                 : 
     242             110 :   if (pos == -1)
     243              96 :     mLanguage.Assign(mDictionary);
     244                 :   else
     245              14 :     mLanguage = Substring(mDictionary, 0, pos);
     246                 : 
     247             220 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     248             110 :   if (obs) {
     249             110 :     obs->NotifyObservers(nsnull,
     250                 :                          SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
     251             110 :                          nsnull);
     252                 :   }
     253                 : 
     254             110 :   return NS_OK;
     255                 : }
     256                 : 
     257                 : /* readonly attribute wstring language; */
     258               0 : NS_IMETHODIMP mozHunspell::GetLanguage(PRUnichar **aLanguage)
     259                 : {
     260               0 :   NS_ENSURE_ARG_POINTER(aLanguage);
     261                 : 
     262               0 :   if (mDictionary.IsEmpty())
     263               0 :     return NS_ERROR_NOT_INITIALIZED;
     264                 : 
     265               0 :   *aLanguage = ToNewUnicode(mLanguage);
     266               0 :   return *aLanguage ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     267                 : }
     268                 : 
     269                 : /* readonly attribute boolean providesPersonalDictionary; */
     270               0 : NS_IMETHODIMP mozHunspell::GetProvidesPersonalDictionary(bool *aProvidesPersonalDictionary)
     271                 : {
     272               0 :   NS_ENSURE_ARG_POINTER(aProvidesPersonalDictionary);
     273                 : 
     274               0 :   *aProvidesPersonalDictionary = false;
     275               0 :   return NS_OK;
     276                 : }
     277                 : 
     278                 : /* readonly attribute boolean providesWordUtils; */
     279               0 : NS_IMETHODIMP mozHunspell::GetProvidesWordUtils(bool *aProvidesWordUtils)
     280                 : {
     281               0 :   NS_ENSURE_ARG_POINTER(aProvidesWordUtils);
     282                 : 
     283               0 :   *aProvidesWordUtils = false;
     284               0 :   return NS_OK;
     285                 : }
     286                 : 
     287                 : /* readonly attribute wstring name; */
     288               0 : NS_IMETHODIMP mozHunspell::GetName(PRUnichar * *aName)
     289                 : {
     290               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     291                 : }
     292                 : 
     293                 : /* readonly attribute wstring copyright; */
     294               0 : NS_IMETHODIMP mozHunspell::GetCopyright(PRUnichar * *aCopyright)
     295                 : {
     296               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     297                 : }
     298                 : 
     299                 : /* attribute mozIPersonalDictionary personalDictionary; */
     300               0 : NS_IMETHODIMP mozHunspell::GetPersonalDictionary(mozIPersonalDictionary * *aPersonalDictionary)
     301                 : {
     302               0 :   *aPersonalDictionary = mPersonalDictionary;
     303               0 :   NS_IF_ADDREF(*aPersonalDictionary);
     304               0 :   return NS_OK;
     305                 : }
     306                 : 
     307               0 : NS_IMETHODIMP mozHunspell::SetPersonalDictionary(mozIPersonalDictionary * aPersonalDictionary)
     308                 : {
     309               0 :   mPersonalDictionary = aPersonalDictionary;
     310               0 :   return NS_OK;
     311                 : }
     312                 : 
     313                 : struct AppendNewStruct
     314                 : {
     315                 :   PRUnichar **dics;
     316                 :   PRUint32 count;
     317                 :   bool failed;
     318                 : };
     319                 : 
     320                 : static PLDHashOperator
     321               0 : AppendNewString(const nsAString& aString, nsIFile* aFile, void* aClosure)
     322                 : {
     323               0 :   AppendNewStruct *ans = (AppendNewStruct*) aClosure;
     324               0 :   ans->dics[ans->count] = ToNewUnicode(aString);
     325               0 :   if (!ans->dics[ans->count]) {
     326               0 :     ans->failed = true;
     327               0 :     return PL_DHASH_STOP;
     328                 :   }
     329                 : 
     330               0 :   ++ans->count;
     331               0 :   return PL_DHASH_NEXT;
     332                 : }
     333                 : 
     334                 : /* void GetDictionaryList ([array, size_is (count)] out wstring dictionaries, out PRUint32 count); */
     335               0 : NS_IMETHODIMP mozHunspell::GetDictionaryList(PRUnichar ***aDictionaries,
     336                 :                                             PRUint32 *aCount)
     337                 : {
     338               0 :   if (!aDictionaries || !aCount)
     339               0 :     return NS_ERROR_NULL_POINTER;
     340                 : 
     341                 :   AppendNewStruct ans = {
     342               0 :     (PRUnichar**) NS_Alloc(sizeof(PRUnichar*) * mDictionaries.Count()),
     343                 :     0,
     344                 :     false
     345               0 :   };
     346                 : 
     347                 :   // This pointer is used during enumeration
     348               0 :   mDictionaries.EnumerateRead(AppendNewString, &ans);
     349                 : 
     350               0 :   if (ans.failed) {
     351               0 :     while (ans.count) {
     352               0 :       --ans.count;
     353               0 :       NS_Free(ans.dics[ans.count]);
     354                 :     }
     355               0 :     NS_Free(ans.dics);
     356               0 :     return NS_ERROR_OUT_OF_MEMORY;
     357                 :   }
     358                 : 
     359               0 :   *aDictionaries = ans.dics;
     360               0 :   *aCount = ans.count;
     361                 : 
     362               0 :   return NS_OK;
     363                 : }
     364                 : 
     365                 : void
     366               1 : mozHunspell::LoadDictionaryList()
     367                 : {
     368               1 :   mDictionaries.Clear();
     369                 : 
     370                 :   nsresult rv;
     371                 : 
     372                 :   nsCOMPtr<nsIProperties> dirSvc =
     373               2 :     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
     374               1 :   if (!dirSvc)
     375                 :     return;
     376                 : 
     377                 :   // find built in dictionaries
     378               2 :   nsCOMPtr<nsIFile> dictDir;
     379               1 :   rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY,
     380               1 :                    NS_GET_IID(nsIFile), getter_AddRefs(dictDir));
     381               1 :   if (NS_SUCCEEDED(rv)) {
     382               0 :     LoadDictionariesFromDir(dictDir);
     383                 :   }
     384                 :   else {
     385                 :     // try to load gredir/dictionaries
     386               2 :     nsCOMPtr<nsIFile> greDir;
     387               1 :     rv = dirSvc->Get(NS_GRE_DIR,
     388               1 :                      NS_GET_IID(nsIFile), getter_AddRefs(greDir));
     389               1 :     if (NS_SUCCEEDED(rv)) {
     390               1 :       greDir->AppendNative(NS_LITERAL_CSTRING("dictionaries"));
     391               1 :       LoadDictionariesFromDir(greDir);
     392                 :     }
     393                 : 
     394                 :     // try to load appdir/dictionaries only if different than gredir
     395               2 :     nsCOMPtr<nsIFile> appDir;
     396               1 :     rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
     397               1 :                      NS_GET_IID(nsIFile), getter_AddRefs(appDir));
     398                 :     bool equals;
     399               1 :     if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(appDir->Equals(greDir, &equals)) && !equals) {
     400               1 :       appDir->AppendNative(NS_LITERAL_CSTRING("dictionaries"));
     401               1 :       LoadDictionariesFromDir(appDir);
     402                 :     }
     403                 :   }
     404                 : 
     405                 :   // find dictionaries from extensions requiring restart
     406               2 :   nsCOMPtr<nsISimpleEnumerator> dictDirs;
     407               1 :   rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST,
     408               1 :                    NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dictDirs));
     409               1 :   if (NS_FAILED(rv))
     410                 :     return;
     411                 : 
     412                 :   bool hasMore;
     413               0 :   while (NS_SUCCEEDED(dictDirs->HasMoreElements(&hasMore)) && hasMore) {
     414               0 :     nsCOMPtr<nsISupports> elem;
     415               0 :     dictDirs->GetNext(getter_AddRefs(elem));
     416                 : 
     417               0 :     dictDir = do_QueryInterface(elem);
     418               0 :     if (dictDir)
     419               0 :       LoadDictionariesFromDir(dictDir);
     420                 :   }
     421                 : 
     422                 :   // find dictionaries from restartless extensions
     423               0 :   for (PRUint32 i = 0; i < mDynamicDirectories.Count(); i++) {
     424               0 :     LoadDictionariesFromDir(mDynamicDirectories[i]);
     425                 :   }
     426                 : 
     427                 :   // Now we have finished updating the list of dictionaries, update the current
     428                 :   // dictionary and any editors which may use it.
     429               0 :   mozInlineSpellChecker::UpdateCanEnableInlineSpellChecking();
     430                 : 
     431                 :   // Check if the current dictionary is still available.
     432                 :   // If not, try to replace it with another dictionary of the same language.
     433               0 :   if (!mDictionary.IsEmpty()) {
     434               0 :     rv = SetDictionary(mDictionary.get());
     435               0 :     if (NS_SUCCEEDED(rv))
     436                 :       return;
     437                 :   }
     438                 : 
     439                 :   // If the current dictionary has gone, and we don't have a good replacement,
     440                 :   // set no current dictionary.
     441               0 :   if (!mDictionary.IsEmpty()) {
     442               0 :     SetDictionary(EmptyString().get());
     443                 :   }
     444                 : }
     445                 : 
     446                 : NS_IMETHODIMP
     447               3 : mozHunspell::LoadDictionariesFromDir(nsIFile* aDir)
     448                 : {
     449                 :   nsresult rv;
     450                 : 
     451               3 :   bool check = false;
     452               3 :   rv = aDir->Exists(&check);
     453               3 :   if (NS_FAILED(rv) || !check)
     454               0 :     return NS_ERROR_UNEXPECTED;
     455                 : 
     456               3 :   rv = aDir->IsDirectory(&check);
     457               3 :   if (NS_FAILED(rv) || !check)
     458               0 :     return NS_ERROR_UNEXPECTED;
     459                 : 
     460               6 :   nsCOMPtr<nsISimpleEnumerator> e;
     461               3 :   rv = aDir->GetDirectoryEntries(getter_AddRefs(e));
     462               3 :   if (NS_FAILED(rv))
     463               0 :     return NS_ERROR_UNEXPECTED;
     464                 : 
     465               6 :   nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e));
     466               3 :   if (!files)
     467               0 :     return NS_ERROR_UNEXPECTED;
     468                 : 
     469               6 :   nsCOMPtr<nsIFile> file;
     470             571 :   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file) {
     471            1130 :     nsAutoString leafName;
     472             565 :     file->GetLeafName(leafName);
     473             565 :     if (!StringEndsWith(leafName, NS_LITERAL_STRING(".dic")))
     474             451 :       continue;
     475                 : 
     476             228 :     nsAutoString dict(leafName);
     477             114 :     dict.SetLength(dict.Length() - 4); // magic length of ".dic"
     478                 : 
     479                 :     // check for the presence of the .aff file
     480             114 :     leafName = dict;
     481             114 :     leafName.AppendLiteral(".aff");
     482             114 :     file->SetLeafName(leafName);
     483             114 :     rv = file->Exists(&check);
     484             114 :     if (NS_FAILED(rv) || !check)
     485               0 :       continue;
     486                 : 
     487                 : #ifdef DEBUG_bsmedberg
     488                 :     printf("Adding dictionary: %s\n", NS_ConvertUTF16toUTF8(dict).get());
     489                 : #endif
     490                 : 
     491             228 :     mDictionaries.Put(dict, file);
     492                 :   }
     493                 : 
     494               3 :   return NS_OK;
     495                 : }
     496                 : 
     497            1030 : nsresult mozHunspell::ConvertCharset(const PRUnichar* aStr, char ** aDst)
     498                 : {
     499            1030 :   NS_ENSURE_ARG_POINTER(aDst);
     500            1030 :   NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER);
     501                 : 
     502                 :   PRInt32 outLength;
     503            1030 :   PRInt32 inLength = nsCRT::strlen(aStr);
     504            1030 :   nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength);
     505            1030 :   NS_ENSURE_SUCCESS(rv, rv);
     506                 : 
     507            1030 :   *aDst = (char *) nsMemory::Alloc(sizeof(char) * (outLength+1));
     508            1030 :   NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY);
     509                 : 
     510            1030 :   rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength);
     511            1030 :   if (NS_SUCCEEDED(rv))
     512            1030 :     (*aDst)[outLength] = '\0';
     513                 : 
     514            1030 :   return rv;
     515                 : }
     516                 : 
     517                 : /* boolean Check (in wstring word); */
     518            1030 : NS_IMETHODIMP mozHunspell::Check(const PRUnichar *aWord, bool *aResult)
     519                 : {
     520            1030 :   NS_ENSURE_ARG_POINTER(aWord);
     521            1030 :   NS_ENSURE_ARG_POINTER(aResult);
     522            1030 :   NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
     523                 : 
     524            2060 :   nsXPIDLCString charsetWord;
     525            1030 :   nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord));
     526            1030 :   NS_ENSURE_SUCCESS(rv, rv);
     527                 : 
     528            1030 :   *aResult = !!mHunspell->spell(charsetWord);
     529                 : 
     530                 : 
     531            1030 :   if (!*aResult && mPersonalDictionary)
     532               0 :     rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
     533                 : 
     534            1030 :   return rv;
     535                 : }
     536                 : 
     537                 : /* void Suggest (in wstring word, [array, size_is (count)] out wstring suggestions, out PRUint32 count); */
     538               0 : NS_IMETHODIMP mozHunspell::Suggest(const PRUnichar *aWord, PRUnichar ***aSuggestions, PRUint32 *aSuggestionCount)
     539                 : {
     540               0 :   NS_ENSURE_ARG_POINTER(aSuggestions);
     541               0 :   NS_ENSURE_ARG_POINTER(aSuggestionCount);
     542               0 :   NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
     543                 : 
     544                 :   nsresult rv;
     545               0 :   *aSuggestionCount = 0;
     546                 : 
     547               0 :   nsXPIDLCString charsetWord;
     548               0 :   rv = ConvertCharset(aWord, getter_Copies(charsetWord));
     549               0 :   NS_ENSURE_SUCCESS(rv, rv);
     550                 : 
     551                 :   char ** wlst;
     552               0 :   *aSuggestionCount = mHunspell->suggest(&wlst, charsetWord);
     553                 : 
     554               0 :   if (*aSuggestionCount) {
     555               0 :     *aSuggestions  = (PRUnichar **)nsMemory::Alloc(*aSuggestionCount * sizeof(PRUnichar *));
     556               0 :     if (*aSuggestions) {
     557               0 :       PRUint32 index = 0;
     558               0 :       for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
     559                 :         // Convert the suggestion to utf16
     560               0 :         PRInt32 inLength = nsCRT::strlen(wlst[index]);
     561                 :         PRInt32 outLength;
     562               0 :         rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength);
     563               0 :         if (NS_SUCCEEDED(rv))
     564                 :         {
     565               0 :           (*aSuggestions)[index] = (PRUnichar *) nsMemory::Alloc(sizeof(PRUnichar) * (outLength+1));
     566               0 :           if ((*aSuggestions)[index])
     567                 :           {
     568               0 :             rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength);
     569               0 :             if (NS_SUCCEEDED(rv))
     570               0 :               (*aSuggestions)[index][outLength] = 0;
     571                 :           }
     572                 :           else
     573               0 :             rv = NS_ERROR_OUT_OF_MEMORY;
     574                 :         }
     575                 :       }
     576                 : 
     577               0 :       if (NS_FAILED(rv))
     578               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the PRUnichar strings up to the point at which the error occurred
     579                 :     }
     580                 :     else // if (*aSuggestions)
     581               0 :       rv = NS_ERROR_OUT_OF_MEMORY;
     582                 :   }
     583                 : 
     584               0 :   NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst);
     585               0 :   return rv;
     586                 : }
     587                 : 
     588                 : NS_IMETHODIMP
     589               0 : mozHunspell::Observe(nsISupports* aSubj, const char *aTopic,
     590                 :                     const PRUnichar *aData)
     591                 : {
     592               0 :   NS_ASSERTION(!strcmp(aTopic, "profile-do-change")
     593                 :                || !strcmp(aTopic, "profile-after-change"),
     594                 :                "Unexpected observer topic");
     595                 : 
     596               0 :   LoadDictionaryList();
     597                 : 
     598               0 :   return NS_OK;
     599                 : }
     600                 : 
     601                 : /* void addDirectory(in nsIFile dir); */
     602               0 : NS_IMETHODIMP mozHunspell::AddDirectory(nsIFile *aDir)
     603                 : {
     604               0 :   mDynamicDirectories.AppendObject(aDir);
     605               0 :   LoadDictionaryList();
     606               0 :   return NS_OK;
     607                 : }
     608                 : 
     609                 : /* void removeDirectory(in nsIFile dir); */
     610               0 : NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir)
     611                 : {
     612               0 :   mDynamicDirectories.RemoveObject(aDir);
     613               0 :   LoadDictionaryList();
     614               0 :   return NS_OK;
     615            4392 : }

Generated by: LCOV version 1.7