зеркало из https://github.com/mozilla/gecko-dev.git
Bug 344895 - Spellchecker hangs Firefox when dealing with a largish textarea, patch by brettw, r+sr=roc
This commit is contained in:
Родитель
a33c51bdb1
Коммит
b4ce183f8f
|
@ -102,7 +102,7 @@ mozInlineSpellChecker::SpellCheckingState
|
|||
mozInlineSpellChecker::gCanEnableSpellChecking =
|
||||
mozInlineSpellChecker::SpellCheck_Uninitialized;
|
||||
|
||||
mozInlineSpellChecker::mozInlineSpellChecker():mNumWordsInSpellSelection(0), mMaxNumWordsInSpellSelection(250)
|
||||
mozInlineSpellChecker::mozInlineSpellChecker():mNumWordsInSpellSelection(0),mMaxNumWordsInSpellSelection(250)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs)
|
||||
|
@ -261,7 +261,10 @@ mozInlineSpellChecker::SetEnableRealTimeSpell(PRBool aEnabled)
|
|||
}
|
||||
}
|
||||
|
||||
// spellcheck the current content
|
||||
// spellcheck the current contents. SpellCheckRange doesn't supply a created
|
||||
// range to DoSpellCheck, which in our case is the entire range. But this
|
||||
// optimization doesn't matter because there is nothing in the spellcheck
|
||||
// selection when starting, which triggers a better optimization.
|
||||
res = SpellCheckRange(nsnull);
|
||||
}
|
||||
else
|
||||
|
@ -367,7 +370,13 @@ mozInlineSpellChecker::SpellCheckAfterEditorChange(
|
|||
}
|
||||
|
||||
if (rangeToCheck) {
|
||||
rv = DoSpellCheck(wordUtil, rangeToCheck, wordRange, spellCheckSelection);
|
||||
if (aAction == kOpInsertText) {
|
||||
rv = DoSpellCheck(wordUtil, rangeToCheck, wordRange, rangeToCheck,
|
||||
spellCheckSelection);
|
||||
} else {
|
||||
rv = DoSpellCheck(wordUtil, rangeToCheck, wordRange, nsnull,
|
||||
spellCheckSelection);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -397,7 +406,7 @@ mozInlineSpellChecker::SpellCheckRange(nsIDOMRange* aRange)
|
|||
rv = wordUtil.Init(mEditor);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK; // editor doesn't like us
|
||||
rv = DoSpellCheck(wordUtil, aRange, nsnull, spellCheckSelection);
|
||||
rv = DoSpellCheck(wordUtil, aRange, nsnull, nsnull, spellCheckSelection);
|
||||
} else
|
||||
{
|
||||
// use full range: SpellCheckBetweenNodes will do the somewhat complicated
|
||||
|
@ -524,6 +533,9 @@ mozInlineSpellChecker::IgnoreWords(const PRUnichar **aWordsToIgnore,
|
|||
// selection (i.e. words previsouly marked as misspelled). Therefore callers
|
||||
// spell check the spell check selection instead of the entire document for
|
||||
// ignore word and add word.
|
||||
//
|
||||
// FIXME TODO Performance: Make sure this works nicely with the empty
|
||||
// selection optimization of DoSpellCheck
|
||||
|
||||
nsresult
|
||||
mozInlineSpellChecker::SpellCheckSelection(nsISelection* aSelection)
|
||||
|
@ -748,7 +760,7 @@ mozInlineSpellChecker::SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
|
|||
res = wordUtil.Init(mEditor);
|
||||
if (NS_FAILED(res))
|
||||
return NS_OK; // editor doesn't like us
|
||||
return DoSpellCheck(wordUtil, range, nsnull, spellCheckSelection);
|
||||
return DoSpellCheck(wordUtil, range, nsnull, nsnull, spellCheckSelection);
|
||||
}
|
||||
|
||||
static inline PRBool IsNonwordChar(PRUnichar chr)
|
||||
|
@ -827,6 +839,11 @@ mozInlineSpellChecker::SkipSpellCheckForNode(nsIDOMNode *aNode,
|
|||
// any spell selection removed (this is used to hide the underlining for the
|
||||
// word that the caret is in). aNoCheckRange should be on word boundaries.
|
||||
//
|
||||
// aCreatedRange is a possibly NULL range of new text that was inserted.
|
||||
// Inside this range, we don't bother to check whether things are inside
|
||||
// the spellcheck selection, which speeds up large paste operations
|
||||
// considerably.
|
||||
//
|
||||
// Normal case when editing text by typing
|
||||
// h e l l o w o r k d h o w a r e y o u
|
||||
// ^ caret
|
||||
|
@ -844,6 +861,7 @@ mozInlineSpellChecker::SkipSpellCheckForNode(nsIDOMNode *aNode,
|
|||
nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
||||
nsIDOMRange *aRange,
|
||||
nsIDOMRange *aNoCheckRange,
|
||||
nsIDOMRange *aCreatedRange,
|
||||
nsISelection *aSpellCheckSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> beginNode, endNode;
|
||||
|
@ -855,6 +873,13 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
if (iscollapsed)
|
||||
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
|
||||
// when there are no misspelled words yet).
|
||||
PRInt32 originalRangeCount;
|
||||
rv = aSpellCheckSelection->GetRangeCount(&originalRangeCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// set the starting DOM position to be the beginning of our range
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRange->GetStartContainer(getter_AddRefs(beginNode));
|
||||
|
@ -865,9 +890,11 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
aWordUtil.SetPosition(beginNode, beginOffset);
|
||||
|
||||
// we need to use IsPointInRange which is on a more specific interface
|
||||
nsCOMPtr<nsIDOMNSRange> noCheckRange;
|
||||
nsCOMPtr<nsIDOMNSRange> noCheckRange, createdRange;
|
||||
if (aNoCheckRange)
|
||||
noCheckRange = do_QueryInterface(aNoCheckRange);
|
||||
if (aCreatedRange)
|
||||
createdRange = do_QueryInterface(aCreatedRange);
|
||||
|
||||
nsAutoString wordText;
|
||||
nsCOMPtr<nsIDOMRange> wordRange;
|
||||
|
@ -890,15 +917,24 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
#endif
|
||||
|
||||
// see if there is a spellcheck range that already intersects the word
|
||||
// and remove it
|
||||
nsCOMPtr<nsIDOMRange> currentRange;
|
||||
IsPointInSelection(aSpellCheckSelection, beginNode, beginOffset,
|
||||
getter_AddRefs(currentRange));
|
||||
if (!currentRange)
|
||||
IsPointInSelection(aSpellCheckSelection, endNode, endOffset - 1,
|
||||
getter_AddRefs(currentRange));
|
||||
if (currentRange)
|
||||
RemoveRange(aSpellCheckSelection, currentRange);
|
||||
// and remove it. We only need to remove old ranges, so don't bother if
|
||||
// there were no ranges when we started out.
|
||||
if (originalRangeCount > 0) {
|
||||
// likewise, if this word is inside new text, we won't bother testing
|
||||
PRBool inCreatedRange = PR_FALSE;
|
||||
if (createdRange)
|
||||
createdRange->IsPointInRange(beginNode, beginOffset, &inCreatedRange);
|
||||
if (! inCreatedRange) {
|
||||
nsCOMPtr<nsIDOMRange> currentRange;
|
||||
IsPointInSelection(aSpellCheckSelection, beginNode, beginOffset,
|
||||
getter_AddRefs(currentRange));
|
||||
if (!currentRange)
|
||||
IsPointInSelection(aSpellCheckSelection, endNode, endOffset - 1,
|
||||
getter_AddRefs(currentRange));
|
||||
if (currentRange)
|
||||
RemoveRange(aSpellCheckSelection, currentRange);
|
||||
}
|
||||
}
|
||||
|
||||
// some words are special and don't need checking
|
||||
if (dontCheckWord)
|
||||
|
@ -1174,7 +1210,8 @@ mozInlineSpellChecker::HandleNavigationEvent(nsIDOMEvent* aEvent,
|
|||
nsCOMPtr<nsISelection> spellCheckSelection;
|
||||
GetSpellCheckSelection(getter_AddRefs(spellCheckSelection));
|
||||
|
||||
rv = DoSpellCheck(wordUtil, currentWordRange, nsnull, spellCheckSelection);
|
||||
rv = DoSpellCheck(wordUtil, currentWordRange, nsnull, nsnull,
|
||||
spellCheckSelection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ public:
|
|||
// spell check the text contained within aRange
|
||||
nsresult DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
||||
nsIDOMRange *aRange, nsIDOMRange* aNoCheckRange,
|
||||
nsIDOMRange *aCreatedRange,
|
||||
nsISelection *aSpellCheckSelection);
|
||||
|
||||
// helper routine to determine if a point is inside of a the passed in selection.
|
||||
|
|
Загрузка…
Ссылка в новой задаче