--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -30,16 +30,17 @@
* exit if something has changed. If we navigate inside the word, we don't want
* to do anything. As a result, this flag is cleared in FinishNavigationEvent
* when we know that we are checking as a result of navigation.
*/
#include "mozilla/EditorBase.h"
#include "mozilla/EditorUtils.h"
#include "mozilla/Services.h"
+#include "mozilla/TextEditor.h"
#include "mozilla/dom/Selection.h"
#include "mozInlineSpellChecker.h"
#include "mozInlineSpellWordUtil.h"
#include "mozISpellI18NManager.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsIDOMNode.h"
#include "nsIDOMDocument.h"
@@ -212,27 +213,28 @@ mozInlineSpellStatus::InitForEditorChang
nsresult
mozInlineSpellStatus::InitForNavigation(
bool aForceCheck, int32_t aNewPositionOffset,
nsIDOMNode* aOldAnchorNode, int32_t aOldAnchorOffset,
nsIDOMNode* aNewAnchorNode, int32_t aNewAnchorOffset,
bool* aContinue)
{
- nsresult rv;
mOp = eOpNavigation;
mForceNavigationWordCheck = aForceCheck;
mNewNavigationPositionOffset = aNewPositionOffset;
// get the root node for checking
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mSpellChecker->mEditor, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIEditor> editor = mSpellChecker->mEditor;
+ if (NS_WARN_IF(!editor)) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsIDOMElement> rootElt;
- rv = editor->GetRootElement(getter_AddRefs(rootElt));
+ nsresult rv = editor->GetRootElement(getter_AddRefs(rootElt));
NS_ENSURE_SUCCESS(rv, rv);
// the anchor node might not be in the DOM anymore, check
nsCOMPtr<nsINode> root = do_QueryInterface(rootElt, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINode> currentAnchor = do_QueryInterface(aOldAnchorNode, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (root && currentAnchor && ! ContentIsDescendantOf(currentAnchor, root)) {
@@ -341,17 +343,17 @@ mozInlineSpellStatus::FinishInitOnEvent(
// Notice that we don't set mNoCheckRange. We check here whether the cursor
// is in the word that needs checking, so it isn't necessary. Plus, the
// spellchecker isn't guaranteed to only check the given word, and it could
// remove the underline from the new word under the cursor.
nsresult
mozInlineSpellStatus::FinishNavigationEvent(mozInlineSpellWordUtil& aWordUtil)
{
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mSpellChecker->mEditor);
+ nsCOMPtr<nsIEditor> editor = mSpellChecker->mEditor;
if (! editor)
return NS_ERROR_FAILURE; // editor is gone
NS_ASSERTION(mAnchorRange, "No anchor for navigation!");
nsCOMPtr<nsIDOMNode> newAnchorNode, oldAnchorNode;
// get the DOM position of the old caret, the range should be collapsed
nsresult rv = mOldNavigationAnchorRange->GetStartContainer(
@@ -363,19 +365,19 @@ mozInlineSpellStatus::FinishNavigationEv
// to check
RefPtr<nsRange> oldWord;
rv = aWordUtil.GetRangeForWord(oldAnchorNode,
static_cast<int32_t>(oldAnchorOffset),
getter_AddRefs(oldWord));
NS_ENSURE_SUCCESS(rv, rv);
// aWordUtil.GetRangeForWord flushes pending notifications, check editor again.
- editor = do_QueryReferent(mSpellChecker->mEditor);
- if (! editor)
+ if (!mSpellChecker->mEditor) {
return NS_ERROR_FAILURE; // editor is gone
+ }
// get the DOM position of the new caret, the range should be collapsed
rv = mAnchorRange->GetStartContainer(getter_AddRefs(newAnchorNode));
NS_ENSURE_SUCCESS(rv, rv);
uint32_t newAnchorOffset = mAnchorRange->StartOffset();
// see if the new cursor position is in the word of the old cursor position
bool isInRange = false;
@@ -426,26 +428,27 @@ mozInlineSpellStatus::FillNoCheckRangeFr
// mozInlineSpellStatus::GetDocument
//
// Returns the nsIDOMDocument object for the document for the
// current spellchecker.
nsresult
mozInlineSpellStatus::GetDocument(nsIDOMDocument** aDocument)
{
- nsresult rv;
*aDocument = nullptr;
if (! mSpellChecker->mEditor)
return NS_ERROR_UNEXPECTED;
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mSpellChecker->mEditor, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIEditor> editor = mSpellChecker->mEditor;
+ if (NS_WARN_IF(!editor)) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsIDOMDocument> domDoc;
- rv = editor->GetDocument(getter_AddRefs(domDoc));
+ nsresult rv = editor->GetDocument(getter_AddRefs(domDoc));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(domDoc, NS_ERROR_NULL_POINTER);
domDoc.forget(aDocument);
return NS_OK;
}
// mozInlineSpellStatus::PositionToCollapsedRange
//
@@ -541,16 +544,17 @@ NS_INTERFACE_MAP_BEGIN(mozInlineSpellChe
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozInlineSpellChecker)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozInlineSpellChecker)
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozInlineSpellChecker)
NS_IMPL_CYCLE_COLLECTION(mozInlineSpellChecker,
+ mEditor,
mSpellCheck,
mTreeWalker,
mCurrentSelectionAnchorNode)
mozInlineSpellChecker::SpellCheckingState
mozInlineSpellChecker::gCanEnableSpellChecking =
mozInlineSpellChecker::SpellCheck_Uninitialized;
@@ -579,17 +583,17 @@ mozInlineSpellChecker::GetSpellChecker(n
*aSpellCheck = mSpellCheck;
NS_IF_ADDREF(*aSpellCheck);
return NS_OK;
}
NS_IMETHODIMP
mozInlineSpellChecker::Init(nsIEditor *aEditor)
{
- mEditor = do_GetWeakReference(aEditor);
+ mEditor = aEditor;
return NS_OK;
}
// mozInlineSpellChecker::Cleanup
//
// Called by the editor when the editor is going away. This is important
// because we remove listeners. We do NOT clean up anything else in this
// function, because it can get called while DoSpellCheck is running!
@@ -617,17 +621,17 @@ nsresult mozInlineSpellChecker::Cleanup(
// Notify ENDED observers now. If we wait to notify as we normally do when
// these async operations finish, then in the meantime the editor may create
// another inline spell checker and cause more STARTED and ENDED
// notifications to be broadcast. Interleaved notifications for the same
// editor but different inline spell checkers could easily confuse
// observers. They may receive two consecutive STARTED notifications for
// example, which we guarantee will not happen.
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditor);
+ nsCOMPtr<nsIEditor> editor = mEditor.forget();
if (mPendingSpellCheck) {
// Cancel the pending editor spell checker initialization.
mPendingSpellCheck = nullptr;
mPendingInitEditorSpellCheckCallback->Cancel();
mPendingInitEditorSpellCheckCallback = nullptr;
ChangeNumPendingSpellChecks(-1, editor);
}
@@ -641,17 +645,16 @@ nsresult mozInlineSpellChecker::Cleanup(
mNumPendingUpdateCurrentDictionary = 0;
}
if (mNumPendingSpellChecks > 0) {
// If mNumPendingSpellChecks is still > 0 at this point, the remainder is
// pending scheduled spell checks.
ChangeNumPendingSpellChecks(-mNumPendingSpellChecks, editor);
}
- mEditor = nullptr;
mFullSpellCheckScheduled = false;
return rv;
}
// mozInlineSpellChecker::CanEnableInlineSpellChecking
//
// This function can be called to see if it seems likely that we can enable
@@ -696,23 +699,24 @@ mozInlineSpellChecker::UpdateCanEnableIn
// mozInlineSpellChecker::RegisterEventListeners
//
// The inline spell checker listens to mouse events and keyboard navigation
// events.
nsresult
mozInlineSpellChecker::RegisterEventListeners()
{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
+ if (NS_WARN_IF(!mEditor)) {
+ return NS_ERROR_FAILURE;
+ }
- editor->AddEditActionListener(this);
+ mEditor->AddEditActionListener(this);
nsCOMPtr<nsIDOMDocument> doc;
- nsresult rv = editor->GetDocument(getter_AddRefs(doc));
+ nsresult rv = mEditor->GetDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<EventTarget> piTarget = do_QueryInterface(doc, &rv);
NS_ENSURE_SUCCESS(rv, rv);
piTarget->AddEventListener(NS_LITERAL_STRING("blur"), this,
true, false);
piTarget->AddEventListener(NS_LITERAL_STRING("click"), this,
@@ -722,23 +726,24 @@ mozInlineSpellChecker::RegisterEventList
return NS_OK;
}
// mozInlineSpellChecker::UnregisterEventListeners
nsresult
mozInlineSpellChecker::UnregisterEventListeners()
{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
+ if (NS_WARN_IF(!mEditor)) {
+ return NS_ERROR_FAILURE;
+ }
- editor->RemoveEditActionListener(this);
+ mEditor->RemoveEditActionListener(this);
nsCOMPtr<nsIDOMDocument> doc;
- editor->GetDocument(getter_AddRefs(doc));
+ mEditor->GetDocument(getter_AddRefs(doc));
NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
nsCOMPtr<EventTarget> piTarget = do_QueryInterface(doc);
NS_ENSURE_TRUE(piTarget, NS_ERROR_NULL_POINTER);
piTarget->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true);
piTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
piTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, false);
@@ -791,19 +796,18 @@ mozInlineSpellChecker::SetEnableRealTime
mPendingSpellCheck->SetFilter(filter);
mPendingInitEditorSpellCheckCallback = new InitEditorSpellCheckCallback(this);
if (!mPendingInitEditorSpellCheckCallback) {
mPendingSpellCheck = nullptr;
NS_ENSURE_STATE(mPendingInitEditorSpellCheckCallback);
}
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditor);
nsresult rv = mPendingSpellCheck->InitSpellChecker(
- editor, false, mPendingInitEditorSpellCheckCallback);
+ mEditor, false, mPendingInitEditorSpellCheckCallback);
if (NS_FAILED(rv)) {
mPendingSpellCheck = nullptr;
mPendingInitEditorSpellCheckCallback = nullptr;
NS_ENSURE_SUCCESS(rv, rv);
}
ChangeNumPendingSpellChecks(1);
@@ -852,20 +856,19 @@ mozInlineSpellChecker::ChangeNumPendingS
// Broadcasts the given topic to observers. aEditor is passed to observers if
// nonnull; otherwise mEditor is passed.
void
mozInlineSpellChecker::NotifyObservers(const char* aTopic, nsIEditor* aEditor)
{
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os)
return;
- nsCOMPtr<nsIEditor> editor = aEditor;
- if (!editor) {
- editor = do_QueryReferent(mEditor);
- }
+ // XXX Do we need to grab the editor here? If it's necessary, each observer
+ // should do it instead.
+ nsCOMPtr<nsIEditor> editor = aEditor ? aEditor : mEditor.get();
os->NotifyObservers(editor, aTopic, nullptr);
}
// mozInlineSpellChecker::SpellCheckAfterEditorChange
//
// Called by the editor when nearly anything happens to change the content.
//
// The start and end positions specify a range for the thing that happened,
@@ -950,44 +953,45 @@ mozInlineSpellChecker::GetMisspelledWord
}
// mozInlineSpellChecker::ReplaceWord
NS_IMETHODIMP
mozInlineSpellChecker::ReplaceWord(nsIDOMNode *aNode, int32_t aOffset,
const nsAString &newword)
{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(newword.Length() != 0, NS_ERROR_FAILURE);
+ if (NS_WARN_IF(!mEditor) || NS_WARN_IF(newword.IsEmpty())) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsIDOMRange> range;
nsresult res = GetMisspelledWord(aNode, aOffset, getter_AddRefs(range));
NS_ENSURE_SUCCESS(res, res);
if (range)
{
// This range was retrieved from the spellchecker selection. As
// ranges cannot be shared between selections, we must clone it
// before adding it to the editor's selection.
nsCOMPtr<nsIDOMRange> editorRange;
res = range->CloneRange(getter_AddRefs(editorRange));
NS_ENSURE_SUCCESS(res, res);
- AutoPlaceHolderBatch phb(editor, nullptr);
+ AutoPlaceHolderBatch phb(mEditor, nullptr);
nsCOMPtr<nsISelection> selection;
- res = editor->GetSelection(getter_AddRefs(selection));
+ res = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
selection->RemoveAllRanges();
selection->AddRange(editorRange);
- nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryReferent(mEditor));
- if (textEditor)
- textEditor->InsertText(newword);
+ MOZ_ASSERT(mEditor);
+ RefPtr<TextEditor> textEditor = mEditor->AsTextEditor();
+ MOZ_ASSERT(textEditor);
+ textEditor->InsertText(newword);
}
return NS_OK;
}
// mozInlineSpellChecker::AddWordToDictionary
NS_IMETHODIMP
@@ -1160,31 +1164,32 @@ nsresult
mozInlineSpellChecker::MakeSpellCheckRange(
nsIDOMNode* aStartNode, int32_t aStartOffset,
nsIDOMNode* aEndNode, int32_t aEndOffset,
nsRange** aRange)
{
nsresult rv;
*aRange = nullptr;
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
+ if (NS_WARN_IF(!mEditor)) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsIDOMDocument> doc;
- rv = editor->GetDocument(getter_AddRefs(doc));
+ rv = mEditor->GetDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsINode> documentNode = do_QueryInterface(doc);
RefPtr<nsRange> range = new nsRange(documentNode);
// possibly use full range of the editor
nsCOMPtr<nsIDOMElement> rootElem;
if (! aStartNode || ! aEndNode) {
- rv = editor->GetRootElement(getter_AddRefs(rootElem));
+ rv = mEditor->GetRootElement(getter_AddRefs(rootElem));
NS_ENSURE_SUCCESS(rv, rv);
aStartNode = rootElem;
aStartOffset = 0;
aEndNode = rootElem;
aEndOffset = -1;
}
@@ -1459,17 +1464,17 @@ nsresult mozInlineSpellChecker::DoSpellC
bool* aDoneChecking)
{
*aDoneChecking = true;
NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
// get the editor for ShouldSpellCheckNode, this may fail in reasonable
// circumstances since the editor could have gone away
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
+ nsCOMPtr<nsIEditor> editor = mEditor;
if (! editor)
return NS_ERROR_FAILURE;
if (aStatus->mRange->Collapsed())
return NS_OK;
// see if the selection has any ranges, if not, then we can optimize checking
// range inclusion later (we have no ranges when we are initially checking or
@@ -1494,20 +1499,19 @@ nsresult mozInlineSpellChecker::DoSpellC
return NS_OK;
}
aWordUtil.SetEnd(endNode, endOffset);
aWordUtil.SetPosition(beginNode, beginOffset);
}
// aWordUtil.SetPosition flushes pending notifications, check editor again.
- // XXX Uhhh, *we're* holding a strong ref to the editor.
- editor = do_QueryReferent(mEditor);
- if (! editor)
+ if (!mEditor) {
return NS_ERROR_FAILURE;
+ }
int32_t wordsChecked = 0;
PRTime beginTime = PR_Now();
nsAutoString wordText;
RefPtr<nsRange> wordRange;
bool dontCheckWord;
while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText,
@@ -1652,19 +1656,19 @@ mozInlineSpellChecker::ResumeCheck(Uniqu
"How could this be false? The full spell check is "
"calling us!!");
mFullSpellCheckScheduled = false;
}
if (! mSpellCheck)
return NS_OK; // spell checking has been turned off
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditor);
- if (! editor)
- return NS_OK; // editor is gone
+ if (!mEditor) {
+ return NS_OK;
+ }
mozInlineSpellWordUtil wordUtil;
nsresult rv = wordUtil.Init(mEditor);
if (NS_FAILED(rv))
return NS_OK; // editor doesn't like us, don't assert
nsCOMPtr<nsISelection> spellCheckSelectionRef;
rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelectionRef));
@@ -1810,36 +1814,40 @@ mozInlineSpellChecker::AddRange(nsISelec
rv = aSpellCheckSelection->AddRange(aRange);
if (NS_SUCCEEDED(rv))
mNumWordsInSpellSelection++;
}
return rv;
}
-nsresult mozInlineSpellChecker::GetSpellCheckSelection(nsISelection ** aSpellCheckSelection)
+nsresult
+mozInlineSpellChecker::GetSpellCheckSelection(
+ nsISelection** aSpellCheckSelection)
{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_ERROR_NULL_POINTER);
-
+ if (NS_WARN_IF(!mEditor)) {
+ return NS_ERROR_FAILURE;
+ }
nsCOMPtr<nsISelectionController> selcon;
- nsresult rv = editor->GetSelectionController(getter_AddRefs(selcon));
+ nsresult rv = mEditor->GetSelectionController(getter_AddRefs(selcon));
NS_ENSURE_SUCCESS(rv, rv);
return selcon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK, aSpellCheckSelection);
}
-nsresult mozInlineSpellChecker::SaveCurrentSelectionPosition()
+nsresult
+mozInlineSpellChecker::SaveCurrentSelectionPosition()
{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ENSURE_TRUE(editor, NS_OK);
+ if (NS_WARN_IF(!mEditor)) {
+ return NS_OK; // XXX Why NS_OK?
+ }
// figure out the old caret position based on the current selection
nsCOMPtr<nsISelection> selection;
- nsresult rv = editor->GetSelection(getter_AddRefs(selection));
+ nsresult rv = mEditor->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
rv = selection->GetFocusNode(getter_AddRefs(mCurrentSelectionAnchorNode));
NS_ENSURE_SUCCESS(rv, rv);
selection->GetFocusOffset(&mCurrentSelectionOffset);
return NS_OK;