# HG changeset patch # User Masayuki Nakano # Date 1516264343 -32400 # Node ID 05408b85794113aac014ed397105ff098b58763b # Parent ab897df98b850f7b37a1a96ca9deb7f4090da413 Bug 1430982 - part 3: Make mozSpellChecker and nsEditorSpellChecker treat TextServicesDocument directly rather than nsITextServicesDocument r=m_kato Now, TextServicesDocument can be treated by anybody. So, let's make mozSpellChecker and nsEditorSpellChecker treat it directly instead of nsITextServicesDocument. MozReview-Commit-ID: 2tMy6y3i17b diff --git a/editor/composer/nsEditorSpellCheck.cpp b/editor/composer/nsEditorSpellCheck.cpp --- a/editor/composer/nsEditorSpellCheck.cpp +++ b/editor/composer/nsEditorSpellCheck.cpp @@ -2,21 +2,22 @@ /* vim: set ts=2 sts=2 sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include // for getenv #include "mozilla/Attributes.h" // for final -#include "mozilla/Preferences.h" // for Preferences #include "mozilla/dom/Element.h" // for Element #include "mozilla/dom/Selection.h" #include "mozilla/intl/LocaleService.h" // for retrieving app locale #include "mozilla/mozalloc.h" // for operator delete, etc +#include "mozilla/Preferences.h" // for Preferences +#include "mozilla/TextServicesDocument.h" // for TextServicesDocument #include "nsAString.h" // for nsAString::IsEmpty, etc #include "nsComponentManagerUtils.h" // for do_CreateInstance #include "nsDebug.h" // for NS_ENSURE_TRUE, etc #include "nsDependentSubstring.h" // for Substring #include "nsEditorSpellCheck.h" #include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc #include "nsIContent.h" // for nsIContent #include "nsIContentPrefService2.h" // for nsIContentPrefService2, etc @@ -372,26 +373,22 @@ nsEditorSpellCheck::InitSpellChecker(nsI nsCOMPtr domDoc; mEditor->GetDocument(getter_AddRefs(domDoc)); nsCOMPtr doc = do_QueryInterface(domDoc); NS_ENSURE_STATE(doc); nsresult rv; // We can spell check with any editor type - nsCOMPtrtsDoc = - do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ENSURE_TRUE(tsDoc, NS_ERROR_NULL_POINTER); - - tsDoc->SetFilter(mTxtSrvFilter); + RefPtr textServicesDocument = + new TextServicesDocument(); + textServicesDocument->SetFilter(mTxtSrvFilter); // Pass the editor to the text services document - rv = tsDoc->InitWithEditor(aEditor); + rv = textServicesDocument->InitWithEditor(aEditor); NS_ENSURE_SUCCESS(rv, rv); if (aEnableSelectionChecking) { // Find out if the section is collapsed or not. // If it isn't, we want to spellcheck just the selection. nsCOMPtr domSelection; aEditor->GetSelection(getter_AddRefs(domSelection)); @@ -407,34 +404,34 @@ nsEditorSpellCheck::InitSpellChecker(nsI if (!range->Collapsed()) { // We don't want to touch the range in the selection, // so create a new copy of it. RefPtr rangeBounds = range->CloneRange(); // Make sure the new range spans complete words. - rv = tsDoc->ExpandRangeToWordBoundaries(rangeBounds); + rv = textServicesDocument->ExpandRangeToWordBoundaries(rangeBounds); NS_ENSURE_SUCCESS(rv, rv); // Now tell the text services that you only want // to iterate over the text in this range. - rv = tsDoc->SetExtent(rangeBounds); + rv = textServicesDocument->SetExtent(rangeBounds); NS_ENSURE_SUCCESS(rv, rv); } } } mSpellChecker = do_CreateInstance(NS_SPELLCHECKER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NULL_POINTER); - rv = mSpellChecker->SetDocument(tsDoc, true); + rv = mSpellChecker->SetDocument(textServicesDocument, true); NS_ENSURE_SUCCESS(rv, rv); // do not fail if UpdateCurrentDictionary fails because this method may // succeed later. rv = UpdateCurrentDictionary(aCallback); if (NS_FAILED(rv) && aCallback) { // However, if it does fail, we still need to call the callback since we // discard the failure. Do it asynchronously so that the caller is always diff --git a/editor/txtsvc/nsISpellChecker.h b/editor/txtsvc/nsISpellChecker.h --- a/editor/txtsvc/nsISpellChecker.h +++ b/editor/txtsvc/nsISpellChecker.h @@ -13,33 +13,36 @@ #define NS_SPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker;1" #define NS_ISPELLCHECKER_IID \ { /* 27bff957-b486-40ae-9f5d-af0cdd211868 */ \ 0x27bff957, 0xb486, 0x40ae, \ { 0x9f, 0x5d, 0xaf, 0x0c, 0xdd, 0x21, 0x18, 0x68 } } -class nsITextServicesDocument; +namespace mozilla { +class TextServicesDocument; +} // namespace mozilla /** * A generic interface for a spelling checker. */ class nsISpellChecker : public nsISupports{ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISPELLCHECKER_IID) /** * Tells the spellchecker what document to check. * @param aDoc is the document to check. * @param aFromStartOfDoc If true, start check from beginning of document, * if false, start check from current cursor position. */ - NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc) = 0; + NS_IMETHOD SetDocument(mozilla::TextServicesDocument* aDoc, + bool aFromStartofDoc) = 0; /** * Selects (hilites) the next misspelled word in the document. * @param aWord will contain the misspelled word. * @param aSuggestions is an array of nsStrings, that represent the * suggested replacements for the misspelled word. */ NS_IMETHOD NextMisspelledWord(nsAString &aWord, nsTArray *aSuggestions) = 0; diff --git a/extensions/spellcheck/src/mozSpellChecker.cpp b/extensions/spellcheck/src/mozSpellChecker.cpp --- a/extensions/spellcheck/src/mozSpellChecker.cpp +++ b/extensions/spellcheck/src/mozSpellChecker.cpp @@ -5,38 +5,40 @@ #include "mozSpellChecker.h" #include "nsIServiceManager.h" #include "mozISpellI18NManager.h" #include "nsIStringEnumerator.h" #include "nsICategoryManager.h" #include "nsISupportsPrimitives.h" #include "nsISimpleEnumerator.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/PRemoteSpellcheckEngineChild.h" -#include "mozilla/dom/ContentChild.h" +#include "mozilla/TextServicesDocument.h" #include "nsXULAppAPI.h" using mozilla::dom::ContentChild; using mozilla::GenericPromise; using mozilla::PRemoteSpellcheckEngineChild; using mozilla::RemoteSpellcheckEngineChild; +using mozilla::TextServicesDocument; #define DEFAULT_SPELL_CHECKER "@mozilla.org/spellchecker/engine;1" NS_IMPL_CYCLE_COLLECTING_ADDREF(mozSpellChecker) NS_IMPL_CYCLE_COLLECTING_RELEASE(mozSpellChecker) NS_INTERFACE_MAP_BEGIN(mozSpellChecker) NS_INTERFACE_MAP_ENTRY(nsISpellChecker) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpellChecker) NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozSpellChecker) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION(mozSpellChecker, - mTsDoc, + mTextServicesDocument, mPersonalDictionary) mozSpellChecker::mozSpellChecker() : mEngine(nullptr) { } mozSpellChecker::~mozSpellChecker() @@ -67,19 +69,20 @@ mozSpellChecker::Init() } else { mPersonalDictionary = do_GetService("@mozilla.org/spellchecker/personaldictionary;1"); } return NS_OK; } NS_IMETHODIMP -mozSpellChecker::SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc) +mozSpellChecker::SetDocument(TextServicesDocument* aTextServicesDocument, + bool aFromStartofDoc) { - mTsDoc = aDoc; + mTextServicesDocument = aTextServicesDocument; mFromStart = aFromStartofDoc; return NS_OK; } NS_IMETHODIMP mozSpellChecker::NextMisspelledWord(nsAString &aWord, nsTArray *aSuggestions) { @@ -89,43 +92,44 @@ mozSpellChecker::NextMisspelledWord(nsAS int32_t selOffset; int32_t begin,end; nsresult result; result = SetupDoc(&selOffset); bool isMisspelled,done; if (NS_FAILED(result)) return result; - while( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ) - { - nsString str; - result = mTsDoc->GetCurrentTextBlock(&str); + while (NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done) { + nsString str; + result = mTextServicesDocument->GetCurrentTextBlock(&str); - if (NS_FAILED(result)) - return result; - do{ - result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end); - if(NS_SUCCEEDED(result)&&(begin != -1)){ - const nsAString &currWord = Substring(str, begin, end - begin); - result = CheckWord(currWord, &isMisspelled, aSuggestions); - if(isMisspelled){ - aWord = currWord; - mTsDoc->SetSelection(begin, end-begin); - // After ScrollSelectionIntoView(), the pending notifications might - // be flushed and PresShell/PresContext/Frames may be dead. - // See bug 418470. - mTsDoc->ScrollSelectionIntoView(); - return NS_OK; - } + if (NS_FAILED(result)) { + return result; + } + do { + result = mConverter->FindNextWord(str.get(), str.Length(), + selOffset, &begin, &end); + if (NS_SUCCEEDED(result) && begin != -1) { + const nsAString &currWord = Substring(str, begin, end - begin); + result = CheckWord(currWord, &isMisspelled, aSuggestions); + if (isMisspelled) { + aWord = currWord; + mTextServicesDocument->SetSelection(begin, end - begin); + // After ScrollSelectionIntoView(), the pending notifications might + // be flushed and PresShell/PresContext/Frames may be dead. + // See bug 418470. + mTextServicesDocument->ScrollSelectionIntoView(); + return NS_OK; } - selOffset = end; - }while(end != -1); - mTsDoc->NextBlock(); - selOffset=0; - } + } + selOffset = end; + } while(end != -1); + mTextServicesDocument->NextBlock(); + selOffset=0; + } return NS_OK; } NS_IMETHODIMP mozSpellChecker::CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray *aSuggestions) { nsresult result; bool correct; @@ -182,83 +186,83 @@ mozSpellChecker::Replace(const nsAString bool done; nsresult result; nsAutoString str; // find out where we are result = SetupDoc(&selOffset); if(NS_FAILED(result)) return result; - result = GetCurrentBlockIndex(mTsDoc,&startBlock); + result = GetCurrentBlockIndex(mTextServicesDocument,&startBlock); if(NS_FAILED(result)) return result; //start at the beginning - result = mTsDoc->FirstBlock(); + result = mTextServicesDocument->FirstBlock(); currOffset=0; currentBlock = 0; - while( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ) - { - result = mTsDoc->GetCurrentTextBlock(&str); - do{ - result = mConverter->FindNextWord(str.get(),str.Length(),currOffset,&begin,&end); - if(NS_SUCCEEDED(result)&&(begin != -1)){ - if (aOldWord.Equals(Substring(str, begin, end-begin))) { - // if we are before the current selection point but in the same block - // move the selection point forwards - if((currentBlock == startBlock)&&(begin < selOffset)){ - selOffset += - int32_t(aNewWord.Length()) - int32_t(aOldWord.Length()); - if(selOffset < begin) selOffset=begin; + while (NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done) { + result = mTextServicesDocument->GetCurrentTextBlock(&str); + do { + result = mConverter->FindNextWord(str.get(),str.Length(),currOffset,&begin,&end); + if (NS_SUCCEEDED(result) && (begin != -1)) { + if (aOldWord.Equals(Substring(str, begin, end-begin))) { + // if we are before the current selection point but in the same + // block move the selection point forwards + if (currentBlock == startBlock && begin < selOffset) { + selOffset += + int32_t(aNewWord.Length()) - int32_t(aOldWord.Length()); + if (selOffset < begin) { + selOffset=begin; } - mTsDoc->SetSelection(begin, end-begin); - mTsDoc->InsertText(&newWord); - mTsDoc->GetCurrentTextBlock(&str); - end += (aNewWord.Length() - aOldWord.Length()); // recursion was cute in GEB, not here. } + mTextServicesDocument->SetSelection(begin, end-begin); + mTextServicesDocument->InsertText(&newWord); + mTextServicesDocument->GetCurrentTextBlock(&str); + end += (aNewWord.Length() - aOldWord.Length()); // recursion was cute in GEB, not here. } - currOffset = end; - }while(currOffset != -1); - mTsDoc->NextBlock(); - currentBlock++; - currOffset=0; - } + } + currOffset = end; + } while(currOffset != -1); + mTextServicesDocument->NextBlock(); + currentBlock++; + currOffset=0; + } // We are done replacing. Put the selection point back where we found it (or equivalent); - result = mTsDoc->FirstBlock(); + result = mTextServicesDocument->FirstBlock(); currentBlock = 0; - while(( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ) &&(currentBlock < startBlock)){ - mTsDoc->NextBlock(); + while(NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done && + currentBlock < startBlock) { + mTextServicesDocument->NextBlock(); } //After we have moved to the block where the first occurrence of replace was done, put the //selection to the next word following it. In case there is no word following it i.e if it happens //to be the last word in that block, then move to the next block and put the selection to the //first word in that block, otherwise when the Setupdoc() is called, it queries the LastSelectedBlock() //and the selection offset of the last occurrence of the replaced word is taken instead of the first //occurrence and things get messed up as reported in the bug 244969 - if( NS_SUCCEEDED(mTsDoc->IsDone(&done)) && !done ){ + if (NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done){ nsString str; - result = mTsDoc->GetCurrentTextBlock(&str); + result = mTextServicesDocument->GetCurrentTextBlock(&str); result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end); - if(end == -1) - { - mTsDoc->NextBlock(); - selOffset=0; - result = mTsDoc->GetCurrentTextBlock(&str); - result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end); - mTsDoc->SetSelection(begin, 0); - } - else - mTsDoc->SetSelection(begin, 0); + if (end == -1) { + mTextServicesDocument->NextBlock(); + selOffset=0; + result = mTextServicesDocument->GetCurrentTextBlock(&str); + result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end); + mTextServicesDocument->SetSelection(begin, 0); + } else { + mTextServicesDocument->SetSelection(begin, 0); + } } - } - else{ - mTsDoc->InsertText(&newWord); + } else { + mTextServicesDocument->InsertText(&newWord); } return NS_OK; } NS_IMETHODIMP mozSpellChecker::IgnoreAll(const nsAString &aWord) { if(mPersonalDictionary){ @@ -455,82 +459,81 @@ mozSpellChecker::SetupDoc(int32_t *outBl { nsresult rv; nsITextServicesDocument::TSDBlockSelectionStatus blockStatus; int32_t selOffset; int32_t selLength; *outBlockOffset = 0; - if (!mFromStart) - { - rv = mTsDoc->LastSelectedBlock(&blockStatus, &selOffset, &selLength); + if (!mFromStart) { + rv = mTextServicesDocument->LastSelectedBlock(&blockStatus, &selOffset, + &selLength); if (NS_SUCCEEDED(rv) && (blockStatus != nsITextServicesDocument::eBlockNotFound)) { switch (blockStatus) { case nsITextServicesDocument::eBlockOutside: // No TB in S, but found one before/after S. case nsITextServicesDocument::eBlockPartial: // S begins or ends in TB but extends outside of TB. // the TS doc points to the block we want. *outBlockOffset = selOffset + selLength; break; case nsITextServicesDocument::eBlockInside: // S extends beyond the start and end of TB. // we want the block after this one. - rv = mTsDoc->NextBlock(); + rv = mTextServicesDocument->NextBlock(); *outBlockOffset = 0; break; case nsITextServicesDocument::eBlockContains: // TB contains entire S. *outBlockOffset = selOffset + selLength; break; case nsITextServicesDocument::eBlockNotFound: // There is no text block (TB) in or before the selection (S). default: NS_NOTREACHED("Shouldn't ever get this status"); } } - else //failed to get last sel block. Just start at beginning - { - rv = mTsDoc->FirstBlock(); + // Failed to get last sel block. Just start at beginning + else { + rv = mTextServicesDocument->FirstBlock(); *outBlockOffset = 0; } } - else // we want the first block - { - rv = mTsDoc->FirstBlock(); + // We want the first block + else { + rv = mTextServicesDocument->FirstBlock(); mFromStart = false; } return rv; } // utility method to discover which block we're in. The TSDoc interface doesn't give // us this, because it can't assume a read-only document. // shamelessly stolen from nsTextServicesDocument nsresult -mozSpellChecker::GetCurrentBlockIndex(nsITextServicesDocument *aDoc, int32_t *outBlockIndex) +mozSpellChecker::GetCurrentBlockIndex( + TextServicesDocument* aTextServicesDocument, + int32_t* aOutBlockIndex) { int32_t blockIndex = 0; bool isDone = false; nsresult result = NS_OK; - do - { - aDoc->PrevBlock(); - - result = aDoc->IsDone(&isDone); - - if (!isDone) - blockIndex ++; - + do { + aTextServicesDocument->PrevBlock(); + result = aTextServicesDocument->IsDone(&isDone); + if (!isDone) { + blockIndex++; + } } while (NS_SUCCEEDED(result) && !isDone); - *outBlockIndex = blockIndex; + *aOutBlockIndex = blockIndex; return result; } nsresult mozSpellChecker::GetEngineList(nsCOMArray* aSpellCheckingEngines) { MOZ_ASSERT(!XRE_IsContentProcess()); diff --git a/extensions/spellcheck/src/mozSpellChecker.h b/extensions/spellcheck/src/mozSpellChecker.h --- a/extensions/spellcheck/src/mozSpellChecker.h +++ b/extensions/spellcheck/src/mozSpellChecker.h @@ -5,17 +5,16 @@ #ifndef mozSpellChecker_h__ #define mozSpellChecker_h__ #include "nsCOMPtr.h" #include "nsCOMArray.h" #include "nsISpellChecker.h" #include "nsString.h" -#include "nsITextServicesDocument.h" #include "mozIPersonalDictionary.h" #include "mozISpellCheckingEngine.h" #include "nsClassHashtable.h" #include "nsTArray.h" #include "mozISpellI18NUtil.h" #include "nsCycleCollectionParticipant.h" #include "RemoteSpellCheckEngineChild.h" @@ -29,17 +28,18 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(mozSpellChecker) mozSpellChecker(); nsresult Init(); // nsISpellChecker - NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc) override; + NS_IMETHOD SetDocument(mozilla::TextServicesDocument* aTextServicesDocument, + bool aFromStartofDoc) override; NS_IMETHOD NextMisspelledWord(nsAString &aWord, nsTArray *aSuggestions) override; NS_IMETHOD CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray *aSuggestions) override; NS_IMETHOD Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences) override; NS_IMETHOD IgnoreAll(const nsAString &aWord) override; NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord) override; NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord) override; NS_IMETHOD GetPersonalDictionary(nsTArray *aWordList) override; @@ -53,27 +53,29 @@ public: void DeleteRemoteEngine() { mEngine = nullptr; } protected: virtual ~mozSpellChecker(); nsCOMPtr mConverter; - nsCOMPtr mTsDoc; + RefPtr mTextServicesDocument; nsCOMPtr mPersonalDictionary; nsCOMPtr mSpellCheckingEngine; bool mFromStart; nsString mCurrentDictionary; nsresult SetupDoc(int32_t *outBlockOffset); - nsresult GetCurrentBlockIndex(nsITextServicesDocument *aDoc, int32_t *outBlockIndex); + nsresult GetCurrentBlockIndex( + mozilla::TextServicesDocument* aTextServicesDocument, + int32_t* aOutBlockIndex); nsresult GetEngineList(nsCOMArray *aDictionaryList); mozilla::RemoteSpellcheckEngineChild *mEngine; friend class mozilla::RemoteSpellcheckEngineChild; }; #endif // mozSpellChecker_h__