LCOV - app.info - extensions/spellcheck/src/mozSpellChecker.cpp

LCOV - code coverage report
| Current view: | directory - extensions/spellcheck/src - mozSpellChecker.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 256 | 2 | 0.8 %
| Date: | 2012-04-21 | Functions: | 27 | 2 | 7.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 Original Code is Mozilla Spellchecker Component.
          15                 :  *
          16                 :  * The Initial Developer of the Original Code is David Einstein.
          17                 :  * Portions created by the Initial Developer are Copyright (C) 2001
          18                 :  * the Initial Developer. All Rights Reserved.
          19                 :  *
          20                 :  * Contributor(s): David Einstein Deinst@world.std.com
          21                 :  *   Jesper Kristensen <mail@jesperkristensen.dk>
          22                 :  *
          23                 :  * Alternatively, the contents of this file may be used under the terms of
          24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          27                 :  * of those above. If you wish to allow use of your version of this file only
          28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          29                 :  * use your version of this file under the terms of the MPL, indicate your
          30                 :  * decision by deleting the provisions above and replace them with the notice
          31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          32                 :  * the provisions above, a recipient may use your version of this file under
          33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          34                 :  *
          35                 :  * ***** END LICENSE BLOCK ***** */
          36                 :
          37                 :
          38                 : #include "mozSpellChecker.h"
          39                 : #include "nsIServiceManager.h"
          40                 : #include "mozISpellI18NManager.h"
          41                 : #include "nsIStringEnumerator.h"
          42                 : #include "nsICategoryManager.h"
          43                 : #include "nsISupportsPrimitives.h"
          44                 :
          45                 : #define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1"
          46                 :
          47               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker)
          48               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(mozSpellChecker)
          49                 :
          50               0 : NS_INTERFACE_MAP_BEGIN(mozSpellChecker)
          51               0 :   NS_INTERFACE_MAP_ENTRY(nsISpellChecker)
          52               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpellChecker)
          53               0 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozSpellChecker)
          54               0 : NS_INTERFACE_MAP_END
          55                 :
          56            1396 : NS_IMPL_CYCLE_COLLECTION_3(mozSpellChecker,
          57                 :                            mConverter,
          58                 :                            mTsDoc,
          59                 :                            mPersonalDictionary)
          60                 :
          61               0 : mozSpellChecker::mozSpellChecker()
          62                 : {
          63               0 : }
          64                 :
          65               0 : mozSpellChecker::~mozSpellChecker()
          66                 : {
          67               0 :   if(mPersonalDictionary){
          68                 :     //    mPersonalDictionary->Save();
          69               0 :     mPersonalDictionary->EndSession();
          70                 :   }
          71               0 :   mSpellCheckingEngine = nsnull;
          72               0 :   mPersonalDictionary = nsnull;
          73               0 : }
          74                 :
          75                 : nsresult
          76               0 : mozSpellChecker::Init()
          77                 : {
          78               0 :   mPersonalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
          79                 :
          80               0 :   mSpellCheckingEngine = nsnull;
          81                 :
          82               0 :   return NS_OK;
          83                 : }
          84                 :
          85                 : NS_IMETHODIMP
          86               0 : mozSpellChecker::SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc)
          87                 : {
          88               0 :   mTsDoc = aDoc;
          89               0 :   mFromStart = aFromStartofDoc;
          90               0 :   return NS_OK;
          91                 : }
          92                 :
          93                 :
          94                 : NS_IMETHODIMP
          95               0 : mozSpellChecker::NextMisspelledWord(nsAString &aWord, nsTArray<nsString> *aSuggestions)
          96                 : {
          97               0 :   if(!aSuggestions||!mConverter)
          98               0 :     return NS_ERROR_NULL_POINTER;
          99                 :
         100                 :   PRInt32 selOffset;
         101                 :   PRInt32 begin,end;
         102                 :   nsresult result;
         103               0 :   result = SetupDoc(&selOffset);
         104                 :   bool isMisspelled,done;
         105               0 :   if (NS_FAILED(result))
         106               0 :     return result;
         107                 :
         108               0 :   while( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done )
         109                 :     {
         110               0 :       nsString str;
         111               0 :       result = mTsDoc->GetCurrentTextBlock(&str);
         112                 :
         113               0 :       if (NS_FAILED(result))
         114               0 :         return result;
         115               0 :       do{
         116               0 :         result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end);
         117               0 :         if(NS_SUCCEEDED(result)&&(begin != -1)){
         118               0 :           const nsAString &currWord = Substring(str, begin, end - begin);
         119               0 :           result = CheckWord(currWord, &isMisspelled, aSuggestions);
         120               0 :           if(isMisspelled){
         121               0 :             aWord = currWord;
         122               0 :             mTsDoc->SetSelection(begin, end-begin);
         123                 :             // After ScrollSelectionIntoView(), the pending notifications might
         124                 :             // be flushed and PresShell/PresContext/Frames may be dead.
         125                 :             // See bug 418470.
         126               0 :             mTsDoc->ScrollSelectionIntoView();
         127               0 :             return NS_OK;
         128                 :           }
         129                 :         }
         130               0 :         selOffset = end;
         131                 :       }while(end != -1);
         132               0 :       mTsDoc->NextBlock();
         133               0 :       selOffset=0;
         134                 :     }
         135               0 :   return NS_OK;
         136                 : }
         137                 :
         138                 : NS_IMETHODIMP
         139               0 : mozSpellChecker::CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray<nsString> *aSuggestions)
         140                 : {
         141                 :   nsresult result;
         142                 :   bool correct;
         143               0 :   if(!mSpellCheckingEngine)
         144               0 :     return NS_ERROR_NULL_POINTER;
         145                 :
         146               0 :   *aIsMisspelled = false;
         147               0 :   result = mSpellCheckingEngine->Check(PromiseFlatString(aWord).get(), &correct);
         148               0 :   NS_ENSURE_SUCCESS(result, result);
         149               0 :   if(!correct){
         150               0 :     if(aSuggestions){
         151                 :       PRUint32 count,i;
         152                 :       PRUnichar **words;
         153                 :
         154               0 :       result = mSpellCheckingEngine->Suggest(PromiseFlatString(aWord).get(), &words, &count);
         155               0 :       NS_ENSURE_SUCCESS(result, result);
         156               0 :       for(i=0;i<count;i++){
         157               0 :         aSuggestions->AppendElement(nsDependentString(words[i]));
         158                 :       }
         159                 :
         160               0 :       if (count)
         161               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
         162                 :     }
         163               0 :     *aIsMisspelled = true;
         164                 :   }
         165               0 :   return NS_OK;
         166                 : }
         167                 :
         168                 : NS_IMETHODIMP
         169               0 : mozSpellChecker::Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences)
         170                 : {
         171               0 :   if(!mConverter)
         172               0 :     return NS_ERROR_NULL_POINTER;
         173                 :
         174               0 :   nsAutoString newWord(aNewWord); // sigh
         175                 :
         176               0 :   if(aAllOccurrences){
         177                 :     PRInt32 selOffset;
         178                 :     PRInt32 startBlock,currentBlock,currOffset;
         179                 :     PRInt32 begin,end;
         180                 :     bool done;
         181                 :     nsresult result;
         182               0 :     nsAutoString str;
         183                 :
         184                 :     // find out where we are
         185               0 :     result = SetupDoc(&selOffset);
         186               0 :     if(NS_FAILED(result))
         187               0 :       return result;
         188               0 :     result = GetCurrentBlockIndex(mTsDoc,&startBlock);
         189               0 :     if(NS_FAILED(result))
         190               0 :       return result;
         191                 :
         192                 :     //start at the beginning
         193               0 :     result = mTsDoc->FirstBlock();
         194               0 :     currOffset=0;
         195               0 :     currentBlock = 0;
         196               0 :     while( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done )
         197                 :       {
         198               0 :         result = mTsDoc->GetCurrentTextBlock(&str);
         199               0 :         do{
         200               0 :           result = mConverter->FindNextWord(str.get(),str.Length(),currOffset,&begin,&end);
         201               0 :           if(NS_SUCCEEDED(result)&&(begin != -1)){
         202               0 :             if (aOldWord.Equals(Substring(str, begin, end-begin))) {
         203                 :               // if we are before the current selection point but in the same block
         204                 :               // move the selection point forwards
         205               0 :               if((currentBlock == startBlock)&&(begin < selOffset)){
         206                 :                 selOffset +=
         207               0 :                   PRInt32(aNewWord.Length()) - PRInt32(aOldWord.Length());
         208               0 :                 if(selOffset < begin) selOffset=begin;
         209                 :               }
         210               0 :               mTsDoc->SetSelection(begin, end-begin);
         211               0 :               mTsDoc->InsertText(&newWord);
         212               0 :               mTsDoc->GetCurrentTextBlock(&str);
         213               0 :               end += (aNewWord.Length() - aOldWord.Length());  // recursion was cute in GEB, not here.
         214                 :             }
         215                 :           }
         216               0 :           currOffset = end;
         217                 :         }while(currOffset != -1);
         218               0 :         mTsDoc->NextBlock();
         219               0 :         currentBlock++;
         220               0 :         currOffset=0;
         221                 :       }
         222                 :
         223                 :     // We are done replacing.  Put the selection point back where we found  it (or equivalent);
         224               0 :     result = mTsDoc->FirstBlock();
         225               0 :     currentBlock = 0;
         226               0 :     while(( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ) &&(currentBlock < startBlock)){
         227               0 :       mTsDoc->NextBlock();
         228                 :     }
         229                 :
         230                 : //After we have moved to the block where the first occurrence of replace was done, put the
         231                 : //selection to the next word following it. In case there is no word following it i.e if it happens
         232                 : //to be the last word in that block, then move to the next block and put the selection to the
         233                 : //first word in that block, otherwise when the Setupdoc() is called, it queries the LastSelectedBlock()
         234                 : //and the selection offset of the last occurrence of the replaced word is taken instead of the first
         235                 : //occurrence and things get messed up as reported in the bug 244969
         236                 :
         237               0 :     if( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ){
         238               0 :       nsString str;
         239               0 :       result = mTsDoc->GetCurrentTextBlock(&str);
         240               0 :       result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end);
         241               0 :             if(end == -1)
         242                 :              {
         243               0 :                 mTsDoc->NextBlock();
         244               0 :                 selOffset=0;
         245               0 :                 result = mTsDoc->GetCurrentTextBlock(&str);
         246               0 :                 result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end);
         247               0 :                 mTsDoc->SetSelection(begin, 0);
         248                 :              }
         249                 :          else
         250               0 :                 mTsDoc->SetSelection(begin, 0);
         251                 :     }
         252                 :  }
         253                 :   else{
         254               0 :     mTsDoc->InsertText(&newWord);
         255                 :   }
         256               0 :   return NS_OK;
         257                 : }
         258                 :
         259                 : NS_IMETHODIMP
         260               0 : mozSpellChecker::IgnoreAll(const nsAString &aWord)
         261                 : {
         262               0 :   if(mPersonalDictionary){
         263               0 :     mPersonalDictionary->IgnoreWord(PromiseFlatString(aWord).get());
         264                 :   }
         265               0 :   return NS_OK;
         266                 : }
         267                 :
         268                 : NS_IMETHODIMP
         269               0 : mozSpellChecker::AddWordToPersonalDictionary(const nsAString &aWord)
         270                 : {
         271                 :   nsresult res;
         272               0 :   PRUnichar empty=0;
         273               0 :   if (!mPersonalDictionary)
         274               0 :     return NS_ERROR_NULL_POINTER;
         275               0 :   res = mPersonalDictionary->AddWord(PromiseFlatString(aWord).get(),&empty);
         276               0 :   return res;
         277                 : }
         278                 :
         279                 : NS_IMETHODIMP
         280               0 : mozSpellChecker::RemoveWordFromPersonalDictionary(const nsAString &aWord)
         281                 : {
         282                 :   nsresult res;
         283               0 :   PRUnichar empty=0;
         284               0 :   if (!mPersonalDictionary)
         285               0 :     return NS_ERROR_NULL_POINTER;
         286               0 :   res = mPersonalDictionary->RemoveWord(PromiseFlatString(aWord).get(),&empty);
         287               0 :   return res;
         288                 : }
         289                 :
         290                 : NS_IMETHODIMP
         291               0 : mozSpellChecker::GetPersonalDictionary(nsTArray<nsString> *aWordList)
         292                 : {
         293               0 :   if(!aWordList || !mPersonalDictionary)
         294               0 :     return NS_ERROR_NULL_POINTER;
         295                 :
         296               0 :   nsCOMPtr<nsIStringEnumerator> words;
         297               0 :   mPersonalDictionary->GetWordList(getter_AddRefs(words));
         298                 :
         299                 :   bool hasMore;
         300               0 :   nsAutoString word;
         301               0 :   while (NS_SUCCEEDED(words->HasMore(&hasMore)) && hasMore) {
         302               0 :     words->GetNext(word);
         303               0 :     aWordList->AppendElement(word);
         304                 :   }
         305               0 :   return NS_OK;
         306                 : }
         307                 :
         308                 : NS_IMETHODIMP
         309               0 : mozSpellChecker::GetDictionaryList(nsTArray<nsString> *aDictionaryList)
         310                 : {
         311                 :   nsresult rv;
         312                 :
         313                 :   // For catching duplicates
         314               0 :   nsClassHashtable<nsStringHashKey, nsCString> dictionaries;
         315               0 :   dictionaries.Init();
         316                 :
         317               0 :   nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
         318               0 :   rv = GetEngineList(&spellCheckingEngines);
         319               0 :   NS_ENSURE_SUCCESS(rv, rv);
         320                 :
         321               0 :   for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
         322               0 :     nsCOMPtr<mozISpellCheckingEngine> engine = spellCheckingEngines[i];
         323                 :
         324               0 :     PRUint32 count = 0;
         325               0 :     PRUnichar **words = NULL;
         326               0 :     engine->GetDictionaryList(&words, &count);
         327               0 :     for (PRUint32 k = 0; k < count; k++) {
         328               0 :       nsAutoString dictName;
         329                 :
         330               0 :       dictName.Assign(words[k]);
         331                 :
         332                 :       // Skip duplicate dictionaries. Only take the first one
         333                 :       // for each name.
         334               0 :       if (dictionaries.Get(dictName, NULL))
         335               0 :         continue;
         336                 :
         337               0 :       dictionaries.Put(dictName, NULL);
         338                 :
         339               0 :       if (!aDictionaryList->AppendElement(dictName)) {
         340               0 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
         341               0 :         return NS_ERROR_OUT_OF_MEMORY;
         342                 :       }
         343                 :     }
         344                 :
         345               0 :     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, words);
         346                 :   }
         347                 :
         348               0 :   return NS_OK;
         349                 : }
         350                 :
         351                 : NS_IMETHODIMP
         352               0 : mozSpellChecker::GetCurrentDictionary(nsAString &aDictionary)
         353                 : {
         354               0 :   if (!mSpellCheckingEngine) {
         355               0 :     aDictionary.AssignLiteral("");
         356               0 :     return NS_OK;
         357                 :   }
         358                 :
         359               0 :   nsXPIDLString dictname;
         360               0 :   mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
         361               0 :   aDictionary = dictname;
         362               0 :   return NS_OK;
         363                 : }
         364                 :
         365                 : NS_IMETHODIMP
         366               0 : mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary)
         367                 : {
         368               0 :   mSpellCheckingEngine = nsnull;
         369                 :
         370               0 :   if (aDictionary.IsEmpty()) {
         371               0 :     return NS_OK;
         372                 :   }
         373                 :
         374                 :   nsresult rv;
         375               0 :   nsCOMArray<mozISpellCheckingEngine> spellCheckingEngines;
         376               0 :   rv = GetEngineList(&spellCheckingEngines);
         377               0 :   NS_ENSURE_SUCCESS(rv, rv);
         378                 :
         379               0 :   for (PRUint32 i = 0; i < spellCheckingEngines.Count(); i++) {
         380                 :     // We must set mSpellCheckingEngine before we call SetDictionary, since
         381                 :     // SetDictionary calls back to this spell checker to check if the
         382                 :     // dictionary was set
         383               0 :     mSpellCheckingEngine = spellCheckingEngines[i];
         384                 :
         385               0 :     rv = mSpellCheckingEngine->SetDictionary(PromiseFlatString(aDictionary).get());
         386                 :
         387               0 :     if (NS_SUCCEEDED(rv)) {
         388               0 :       nsCOMPtr<mozIPersonalDictionary> personalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1");
         389               0 :       mSpellCheckingEngine->SetPersonalDictionary(personalDictionary.get());
         390                 :
         391               0 :       nsXPIDLString language;
         392               0 :       nsCOMPtr<mozISpellI18NManager> serv(do_GetService("@mozilla.org/spellchecker/i18nmanager;1", &rv));
         393               0 :       NS_ENSURE_SUCCESS(rv, rv);
         394               0 :       return serv->GetUtil(language.get(),getter_AddRefs(mConverter));
         395                 :     }
         396                 :   }
         397                 :
         398               0 :   mSpellCheckingEngine = NULL;
         399                 :
         400                 :   // We could not find any engine with the requested dictionary
         401               0 :   return NS_ERROR_NOT_AVAILABLE;
         402                 : }
         403                 :
         404                 : NS_IMETHODIMP
         405               0 : mozSpellChecker::CheckCurrentDictionary()
         406                 : {
         407                 :   // If the current dictionary has been uninstalled, we need to stop using it.
         408                 :   // This happens when there is a current engine, but that engine has no
         409                 :   // current dictionary.
         410                 :
         411               0 :   if (!mSpellCheckingEngine) {
         412                 :     // We didn't have a current dictionary
         413               0 :     return NS_OK;
         414                 :   }
         415                 :
         416               0 :   nsXPIDLString dictname;
         417               0 :   mSpellCheckingEngine->GetDictionary(getter_Copies(dictname));
         418                 :
         419               0 :   if (!dictname.IsEmpty()) {
         420                 :     // We still have a current dictionary
         421               0 :     return NS_OK;
         422                 :   }
         423                 :
         424                 :   // We had a current dictionary, but it has gone, so we cannot use it anymore.
         425               0 :   mSpellCheckingEngine = nsnull;
         426               0 :   return NS_OK;
         427                 : }
         428                 :
         429                 : nsresult
         430               0 : mozSpellChecker::SetupDoc(PRInt32 *outBlockOffset)
         431                 : {
         432                 :   nsresult  rv;
         433                 :
         434                 :   nsITextServicesDocument::TSDBlockSelectionStatus blockStatus;
         435                 :   PRInt32 selOffset;
         436                 :   PRInt32 selLength;
         437               0 :   *outBlockOffset = 0;
         438                 :
         439               0 :   if (!mFromStart)
         440                 :   {
         441               0 :     rv = mTsDoc->LastSelectedBlock(&blockStatus, &selOffset, &selLength);
         442               0 :     if (NS_SUCCEEDED(rv) && (blockStatus != nsITextServicesDocument::eBlockNotFound))
         443                 :     {
         444               0 :       switch (blockStatus)
         445                 :       {
         446                 :         case nsITextServicesDocument::eBlockOutside:  // No TB in S, but found one before/after S.
         447                 :         case nsITextServicesDocument::eBlockPartial:  // S begins or ends in TB but extends outside of TB.
         448                 :           // the TS doc points to the block we want.
         449               0 :           *outBlockOffset = selOffset + selLength;
         450               0 :           break;
         451                 :
         452                 :         case nsITextServicesDocument::eBlockInside:  // S extends beyond the start and end of TB.
         453                 :           // we want the block after this one.
         454               0 :           rv = mTsDoc->NextBlock();
         455               0 :           *outBlockOffset = 0;
         456               0 :           break;
         457                 :
         458                 :         case nsITextServicesDocument::eBlockContains: // TB contains entire S.
         459               0 :           *outBlockOffset = selOffset + selLength;
         460               0 :           break;
         461                 :
         462                 :         case nsITextServicesDocument::eBlockNotFound: // There is no text block (TB) in or before the selection (S).
         463                 :         default:
         464               0 :           NS_NOTREACHED("Shouldn't ever get this status");
         465                 :       }
         466                 :     }
         467                 :     else  //failed to get last sel block. Just start at beginning
         468                 :     {
         469               0 :       rv = mTsDoc->FirstBlock();
         470               0 :       *outBlockOffset = 0;
         471                 :     }
         472                 :
         473                 :   }
         474                 :   else // we want the first block
         475                 :   {
         476               0 :     rv = mTsDoc->FirstBlock();
         477               0 :     mFromStart = false;
         478                 :   }
         479               0 :   return rv;
         480                 : }
         481                 :
         482                 :
         483                 : // utility method to discover which block we're in. The TSDoc interface doesn't give
         484                 : // us this, because it can't assume a read-only document.
         485                 : // shamelessly stolen from nsTextServicesDocument
         486                 : nsresult
         487               0 : mozSpellChecker::GetCurrentBlockIndex(nsITextServicesDocument *aDoc, PRInt32 *outBlockIndex)
         488                 : {
         489               0 :   PRInt32  blockIndex = 0;
         490               0 :   bool     isDone = false;
         491               0 :   nsresult result = NS_OK;
         492                 :
         493               0 :   do
         494                 :   {
         495               0 :     aDoc->PrevBlock();
         496                 :
         497               0 :     result = aDoc->IsDone(&isDone);
         498                 :
         499               0 :     if (!isDone)
         500               0 :       blockIndex ++;
         501                 :
         502               0 :   } while (NS_SUCCEEDED(result) && !isDone);
         503                 :
         504               0 :   *outBlockIndex = blockIndex;
         505                 :
         506               0 :   return result;
         507                 : }
         508                 :
         509                 : nsresult
         510               0 : mozSpellChecker::GetEngineList(nsCOMArray<mozISpellCheckingEngine>* aSpellCheckingEngines)
         511                 : {
         512                 :   nsresult rv;
         513                 :   bool hasMoreEngines;
         514                 :
         515               0 :   nsCOMPtr<nsICategoryManager> catMgr = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
         516               0 :   if (!catMgr)
         517               0 :     return NS_ERROR_NULL_POINTER;
         518                 :
         519               0 :   nsCOMPtr<nsISimpleEnumerator> catEntries;
         520                 :
         521                 :   // Get contract IDs of registrated external spell-check engines and
         522                 :   // append one of HunSpell at the end.
         523               0 :   rv = catMgr->EnumerateCategory("spell-check-engine", getter_AddRefs(catEntries));
         524               0 :   if (NS_FAILED(rv))
         525               0 :     return rv;
         526                 :
         527               0 :   while (catEntries->HasMoreElements(&hasMoreEngines), hasMoreEngines){
         528               0 :     nsCOMPtr<nsISupports> elem;
         529               0 :     rv = catEntries->GetNext(getter_AddRefs(elem));
         530                 :
         531               0 :     nsCOMPtr<nsISupportsCString> entry = do_QueryInterface(elem, &rv);
         532               0 :     if (NS_FAILED(rv))
         533               0 :       return rv;
         534                 :
         535               0 :     nsCString contractId;
         536               0 :     rv = entry->GetData(contractId);
         537               0 :     if (NS_FAILED(rv))
         538               0 :       return rv;
         539                 :
         540                 :     // Try to load spellchecker engine. Ignore errors silently
         541                 :     // except for the last one (HunSpell).
         542                 :     nsCOMPtr<mozISpellCheckingEngine> engine =
         543               0 :       do_GetService(contractId.get(), &rv);
         544               0 :     if (NS_SUCCEEDED(rv)) {
         545               0 :       aSpellCheckingEngines->AppendObject(engine);
         546                 :     }
         547                 :   }
         548                 :
         549                 :   // Try to load HunSpell spellchecker engine.
         550                 :   nsCOMPtr<mozISpellCheckingEngine> engine =
         551               0 :     do_GetService(DEFAULT_SPELL_CHECKER, &rv);
         552               0 :   if (NS_FAILED(rv)) {
         553                 :     // Fail if not succeeded to load HunSpell. Ignore errors
         554                 :     // for external spellcheck engines.
         555               0 :     return rv;
         556                 :   }
         557               0 :   aSpellCheckingEngines->AppendObject(engine);
         558                 :
         559               0 :   return NS_OK;
         560            4188 : }

Generated by: LCOV version 1.7