Bug 302050: inline spellchecking for textboxes backend. r=bryner sr=bzbarsky

This commit is contained in:
brettw%gmail.com 2005-12-05 18:07:33 +00:00
Родитель d5494068f9
Коммит 97c9c6513a
19 изменённых файлов: 411 добавлений и 25 удалений

Просмотреть файл

@ -286,7 +286,9 @@ XULPopupListenerImpl::PreLaunchPopup(nsIDOMEvent* aMouseEvent)
}
// Store clicked-on node in xul document for context menus and menu popups.
// CLEAR THE POPUP EVENT BEFORE THIS FUNCTION EXITS
xulDocument->SetPopupNode( targetNode );
xulDocument->SetPopupEvent( aMouseEvent );
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aMouseEvent));
@ -322,6 +324,7 @@ XULPopupListenerImpl::PreLaunchPopup(nsIDOMEvent* aMouseEvent)
aMouseEvent->PreventDefault();
break;
}
xulDocument->SetPopupEvent(nsnull);
return NS_OK;
}

Просмотреть файл

@ -1622,6 +1622,34 @@ nsXULDocument::SetPopupNode(nsIDOMNode* aNode)
return rv;
}
NS_IMETHODIMP
nsXULDocument::GetPopupEvent(nsIDOMEvent** aEvent)
{
nsresult rv;
nsCOMPtr<nsIFocusController> focusController;
GetFocusController(getter_AddRefs(focusController));
NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
rv = focusController->GetPopupEvent(aEvent);
return rv;
}
NS_IMETHODIMP
nsXULDocument::SetPopupEvent(nsIDOMEvent* aEvent)
{
nsresult rv;
nsCOMPtr<nsIFocusController> focusController;
GetFocusController(getter_AddRefs(focusController));
NS_ENSURE_TRUE(focusController, NS_ERROR_FAILURE);
rv = focusController->SetPopupEvent(aEvent);
return rv;
}
NS_IMETHODIMP
nsXULDocument::GetTooltipNode(nsIDOMNode** aNode)
{

Просмотреть файл

@ -52,9 +52,9 @@ class nsIController;
class nsIControllers;
class nsAString;
// {AC71F479-17E1-4ee0-8EFD-0ECF2AA2F827}
// {f9004db3-5272-4a8c-8b19-70a4adb8f8b6}
#define NS_IFOCUSCONTROLLER_IID \
{ 0xac71f479, 0x17e1, 0x4ee0, { 0x8e, 0xfd, 0xe, 0xcf, 0x2a, 0xa2, 0xf8, 0x27 } }
{ 0xf9004db3, 0x5272, 0x4a8c, { 0x8b, 0x19, 0x70, 0xa4, 0xad, 0xb8, 0xf8, 0xb6 } }
class nsIFocusController : public nsISupports {
public:
@ -78,6 +78,9 @@ public:
NS_IMETHOD GetPopupNode(nsIDOMNode** aNode)=0;
NS_IMETHOD SetPopupNode(nsIDOMNode* aNode)=0;
NS_IMETHOD GetPopupEvent(nsIDOMEvent** aEvent)=0;
NS_IMETHOD SetPopupEvent(nsIDOMEvent* aEvent)=0;
NS_IMETHOD GetControllerForCommand(const char * aCommand, nsIController** aResult)=0;
NS_IMETHOD GetControllers(nsIControllers** aResult)=0;

Просмотреть файл

@ -42,10 +42,17 @@
interface nsIDOMXULCommandDispatcher;
interface nsIObserver;
[scriptable, uuid(e64bb081-13ba-430e-ab70-73a9f1d3de58)]
[scriptable, uuid(868685b1-f4bc-4080-9c44-ecd5a3f1bac8)]
interface nsIDOMXULDocument : nsISupports
{
attribute nsIDOMNode popupNode;
/**
* The event that triggered the popup. This is only valid during
* the popup showing event.
*/
attribute nsIDOMEvent popupEvent;
attribute nsIDOMNode tooltipNode;
readonly attribute nsIDOMXULCommandDispatcher commandDispatcher;

Просмотреть файл

@ -591,4 +591,19 @@ nsFocusController::SetPopupNode(nsIDOMNode* aNode)
return NS_OK;
}
NS_IMETHODIMP
nsFocusController::GetPopupEvent(nsIDOMEvent** aEvent)
{
*aEvent = mPopupEvent;
NS_IF_ADDREF(*aEvent);
return NS_OK;
}
NS_IMETHODIMP
nsFocusController::SetPopupEvent(nsIDOMEvent* aEvent)
{
mPopupEvent = aEvent;
return NS_OK;
}

Просмотреть файл

@ -86,6 +86,9 @@ public:
NS_IMETHOD GetPopupNode(nsIDOMNode** aNode);
NS_IMETHOD SetPopupNode(nsIDOMNode* aNode);
NS_IMETHOD GetPopupEvent(nsIDOMEvent** aEvent);
NS_IMETHOD SetPopupEvent(nsIDOMEvent* aEvent);
NS_IMETHOD GetControllerForCommand(const char *aCommand, nsIController** aResult);
NS_IMETHOD GetControllers(nsIControllers** aResult);
@ -115,6 +118,7 @@ protected:
nsCOMPtr<nsPIDOMWindow> mCurrentWindow; // [OWNER]
nsCOMPtr<nsPIDOMWindow> mPreviousWindow; // [OWNER]
nsCOMPtr<nsIDOMNode> mPopupNode; // [OWNER]
nsCOMPtr<nsIDOMEvent> mPopupEvent;
PRUint32 mSuppressFocus;
PRPackedBool mSuppressFocusScroll;

Просмотреть файл

@ -24,6 +24,7 @@
* Akkana Peck <akkana@netscape.com>
* Charley Manske <cmanske@netscape.com>
* Neil Deakin <neil@mozdevgroup.com>
* Brett Wilson <brettw@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -73,6 +74,30 @@ nsEditorSpellCheck::~nsEditorSpellCheck()
mSpellChecker = nsnull;
}
// The problem is that if the spell checker does not exist, we can not tell
// which dictionaries are installed. This function works around the problem,
// allowing callers to ask if we can spell check without actually doing so (and
// enabling or disabling UI as necessary). This just creates a spellcheck
// object if needed and asks it for the dictionary list.
NS_IMETHODIMP
nsEditorSpellCheck::CanSpellCheck(PRBool* _retval)
{
nsresult rv;
nsCOMPtr<nsISpellChecker> spellChecker;
if (! mSpellChecker) {
spellChecker = do_CreateInstance(NS_SPELLCHECKER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
} else {
spellChecker = mSpellChecker;
}
nsStringArray dictList;
rv = spellChecker->GetDictionaryList(&dictList);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = (dictList.Count() > 0);
return NS_OK;
}
NS_IMETHODIMP
nsEditorSpellCheck::InitSpellChecker(nsIEditor* aEditor, PRBool aEnableSelectionChecking)
{
@ -199,7 +224,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::GetNextMisspelledWord(PRUnichar **aNextMisspelledWord)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
nsAutoString nextMisspelledWord;
@ -233,7 +258,7 @@ nsEditorSpellCheck::CheckCurrentWord(const PRUnichar *aSuggestedWord,
PRBool *aIsMisspelled)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
DeleteSuggestedWordList();
return mSpellChecker->CheckWord(nsDependentString(aSuggestedWord),
@ -245,7 +270,7 @@ nsEditorSpellCheck::CheckCurrentWordNoSuggest(const PRUnichar *aSuggestedWord,
PRBool *aIsMisspelled)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
return mSpellChecker->CheckWord(nsDependentString(aSuggestedWord),
aIsMisspelled, nsnull);
@ -257,7 +282,7 @@ nsEditorSpellCheck::ReplaceWord(const PRUnichar *aMisspelledWord,
PRBool allOccurrences)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
return mSpellChecker->Replace(nsDependentString(aMisspelledWord),
nsDependentString(aReplaceWord), allOccurrences);
@ -267,7 +292,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::IgnoreWordAllOccurrences(const PRUnichar *aWord)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
return mSpellChecker->IgnoreAll(nsDependentString(aWord));
}
@ -276,7 +301,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::GetPersonalDictionary()
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
// We can spell check with any editor type
mDictionaryList.Clear();
@ -305,7 +330,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::AddWordToDictionary(const PRUnichar *aWord)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
return mSpellChecker->AddWordToPersonalDictionary(nsDependentString(aWord));
}
@ -314,7 +339,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::RemoveWordFromDictionary(const PRUnichar *aWord)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
return mSpellChecker->RemoveWordFromPersonalDictionary(nsDependentString(aWord));
}
@ -323,7 +348,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::GetDictionaryList(PRUnichar ***aDictionaryList, PRUint32 *aCount)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
if (!aDictionaryList || !aCount)
return NS_ERROR_NULL_POINTER;
@ -382,7 +407,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::GetCurrentDictionary(PRUnichar **aDictionary)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
if (!aDictionary)
return NS_ERROR_NULL_POINTER;
@ -402,7 +427,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::SetCurrentDictionary(const PRUnichar *aDictionary)
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
if (!aDictionary)
return NS_ERROR_NULL_POINTER;
@ -414,7 +439,7 @@ NS_IMETHODIMP
nsEditorSpellCheck::UninitSpellChecker()
{
if (!mSpellChecker)
return NS_NOINTERFACE;
return NS_ERROR_NOT_INITIALIZED;
// Save the last used dictionary to the user's preferences.
nsresult rv;

Просмотреть файл

@ -69,6 +69,8 @@ protected:
nsStringArray mSuggestedWordList;
PRInt32 mSuggestedWordIndex;
// these are the words in the current personal dictionary,
// GetPersonalDictionary must be called to load them.
nsStringArray mDictionaryList;
PRInt32 mDictionaryIndex;

Просмотреть файл

@ -63,7 +63,7 @@ typedef short EDirection;
[ptr] native nsIPresShellPtr(nsIPresShell);
[ptr] native nsIContentPtr(nsIContent);
[scriptable, uuid(D4882FFB-E927-408b-96BE-D4391B456FA9)]
[scriptable, uuid(e7cb6526-0809-47ee-b484-a6f297e536c0)]
interface nsIEditor : nsISupports
{
@ -285,7 +285,15 @@ interface nsIEditor : nsISupports
/* ------------ Inline Spell Checking methods -------------- */
readonly attribute nsIInlineSpellChecker inlineSpellChecker;
/** Returns the inline spell checker associated with this object. The spell
* checker is lazily created, so this function may create the object for
* you during this call.
* @param autoCreate If true, this will create a spell checker object
* if one does not exist yet for this editor. If false
* and the object has not been created, this function
* WILL RETURN NULL.
*/
nsIInlineSpellChecker getInlineSpellChecker(in boolean autoCreate);
/* ------------ Clipboard methods -------------- */

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -40,25 +41,143 @@
interface nsIEditor;
interface nsITextServicesFilter;
[scriptable, uuid(6088a862-1229-11d9-941d-c035b2e390c6)]
[scriptable, uuid(78201842-b5f8-441f-a696-fa343bd8a29a)]
interface nsIEditorSpellCheck : nsISupports
{
/**
* Returns true if we can enable spellchecking. If there are no available
* dictionaries, this will return false.
*/
boolean canSpellCheck();
/**
* Turns on the spell checker for the given editor. enableSelectionChecking
* set means that we only want to check the current selection in the editor,
* (this controls the behavior of GetNextMisspelledWord). For spellchecking
* clients with no modal UI (such as inline spellcheckers), this flag doesn't
* matter
*/
void InitSpellChecker(in nsIEditor editor, in boolean enableSelectionChecking);
/**
* When interactively spell checking the document, this will return the
* value of the next word that is misspelled. This also computes the
* suggestions which you can get by calling GetSuggestedWord.
*
* @see nsISpellChecker::GetNextMisspelledWord
*/
wstring GetNextMisspelledWord();
/**
* Used to get suggestions for the last word that was checked and found to
* be misspelled. The first call will give you the first (best) suggestion.
* Subsequent calls will iterate through all the suggestions, allowing you
* to build a list. When there are no more suggestions, an empty string
* (not a null pointer) will be returned.
*
* @see nsISpellChecker::GetSuggestedWord
*/
wstring GetSuggestedWord();
/**
* Check a given word. In spite of the name, this function checks the word
* you give it, returning true if the word is misspelled. If the word is
* misspelled, it will compute the suggestions which you can get from
* GetSuggestedWord().
*
* @see nsISpellChecker::CheckCurrentWord
*/
boolean CheckCurrentWord(in wstring suggestedWord);
/**
* Use when modally checking the document to replace a word.
*
* @see nsISpellChecker::CheckCurrentWord
*/
void ReplaceWord(in wstring misspelledWord, in wstring replaceWord, in boolean allOccurrences);
/**
* @see nsISpellChecker::IgnoreAll
*/
void IgnoreWordAllOccurrences(in wstring word);
/**
* Fills an internal list of words added to the personal dictionary. These
* words can be retrieved using GetPersonalDictionaryWord()
*
* @see nsISpellChecker::GetPersonalDictionary
* @see GetPersonalDictionaryWord
*/
void GetPersonalDictionary();
/**
* Used after you call GetPersonalDictionary() to iterate through all the
* words added to the personal dictionary. Will return the empty string when
* there are no more words.
*/
wstring GetPersonalDictionaryWord();
/**
* Adds a word to the current personal dictionary.
*
* @see nsISpellChecker::AddWordToDictionary
*/
void AddWordToDictionary(in wstring word);
/**
* Removes a word from the current personal dictionary.
*
* @see nsISpellChecker::RemoveWordFromPersonalDictionary
*/
void RemoveWordFromDictionary(in wstring word);
/**
* Retrieves a list of the currently available dictionaries. The strings will
* typically be language IDs, like "en-US".
*
* @see mozISpellCheckingEngine::GetDictionaryList
*/
void GetDictionaryList([array, size_is(count)] out wstring dictionaryList, out PRUint32 count);
/**
* @see nsISpellChecker::GetCurrentDictionary
*/
wstring GetCurrentDictionary();
/**
* @see nsISpellChecker::SetCurrentDictionary
*/
void SetCurrentDictionary(in wstring dictionary);
/**
* Call this to free up the spell checking object. It will also save the
* current selected language as the default for future use.
*
* If you have called CanSpellCheck but not InitSpellChecker, you can still
* call this function to clear the cached spell check object, and no
* preference saving will happen.
*/
void UninitSpellChecker();
/**
* Used to filter the content (for example, to skip blockquotes in email from
* spellchecking. Call this before calling InitSpellChecker; calling it
* after initialization will have no effect.
*
* @see nsITextServicesDocument::setFilter
*/
void setFilter(in nsITextServicesFilter filter);
/**
* Like CheckCurrentWord, checks the word you give it, returning true if it's
* misspelled. This is faster than CheckCurrentWord because it does not
* compute any suggestions.
*
* Watch out: this does not clear any suggestions left over from previous
* calls to CheckCurrentWord, so there may be suggestions, but they will be
* invalid.
*/
boolean CheckCurrentWordNoSuggest(in wstring suggestedWord);
};

Просмотреть файл

@ -1262,12 +1262,13 @@ nsEditor::MarkNodeDirty(nsIDOMNode* aNode)
return NS_OK;
}
NS_IMETHODIMP nsEditor::GetInlineSpellChecker(nsIInlineSpellChecker ** aInlineSpellChecker)
NS_IMETHODIMP nsEditor::GetInlineSpellChecker(PRBool autoCreate,
nsIInlineSpellChecker ** aInlineSpellChecker)
{
NS_ENSURE_ARG_POINTER(aInlineSpellChecker);
nsresult rv;
if (!mInlineSpellChecker) {
if (!mInlineSpellChecker && autoCreate) {
mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -51,7 +51,7 @@ var InlineSpellChecker =
Init : function (editor, enable)
{
this.editor = editor;
this.inlineSpellChecker = editor.inlineSpellChecker;
this.inlineSpellChecker = editor.getInlineSpellChecker(true);
this.inlineSpellChecker.enableRealTimeSpell = enable;
},

Просмотреть файл

@ -81,7 +81,11 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(mozInlineSpellChecker)
NS_IMPL_RELEASE(mozInlineSpellChecker)
mozInlineSpellChecker::SpellCheckingState
mozInlineSpellChecker::gCanEnableSpellChecking =
mozInlineSpellChecker::SpellCheck_Uninitialized;
mozInlineSpellChecker::mozInlineSpellChecker()
{
}
@ -110,6 +114,40 @@ nsresult mozInlineSpellChecker::Cleanup()
return UnregisterEventListeners();
}
// mozInlineSpellChecker::CanEnableInlineSpellChecking
//
// This function can be called to see if it seems likely that we can enable
// spellchecking before actually creating the InlineSpellChecking objects.
//
// The problem is that we can't get the dictionary list without actually
// creating a whole bunch of spellchecking objects. This function tries to
// do that and caches the result so we don't have to keep allocating those
// objects if there are no dictionaries or spellchecking.
//
// This caching will prevent adding dictionaries at runtime if we start out
// with no dictionaries! Installing dictionaries as extensions will require
// a restart anyway, so it shouldn't be a problem.
PRBool mozInlineSpellChecker::CanEnableInlineSpellChecking() // static
{
nsresult rv;
if (gCanEnableSpellChecking == SpellCheck_Uninitialized) {
gCanEnableSpellChecking = SpellCheck_NotAvailable;
nsCOMPtr<nsIEditorSpellCheck> spellchecker =
do_CreateInstance("@mozilla.org/editor/editorspellchecker;1", &rv);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
PRBool canSpellCheck = PR_FALSE;
rv = spellchecker->CanSpellCheck(&canSpellCheck);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (canSpellCheck)
gCanEnableSpellChecking = SpellCheck_Available;
}
return (gCanEnableSpellChecking == SpellCheck_Available);
}
// the inline spell checker listens to mouse events and keyboard navigation events
nsresult mozInlineSpellChecker::RegisterEventListeners()
{
@ -189,6 +227,9 @@ NS_IMETHODIMP mozInlineSpellChecker::SetEnableRealTimeSpell(PRBool aEnabled)
RegisterEventListeners();
}
}
// spellcheck the current contents
res = SpellCheckRange(nsnull);
}
else
{
@ -297,8 +338,11 @@ NS_IMETHODIMP mozInlineSpellChecker::SpellCheckAfterEditorChange(PRInt32 action,
break;
case kOpLoadHTML:
// XXX this should cause a spellcheck of the entire document
{
// spell check the entire document
SpellCheckRange(nsnull);
break;
}
case kOpInsertElement:
PRBool iscollapsed;
@ -334,6 +378,7 @@ NS_IMETHODIMP mozInlineSpellChecker::SpellCheckAfterEditorChange(PRInt32 action,
return res;
}
// supply a NULL range and this will check the entire editor
NS_IMETHODIMP mozInlineSpellChecker::SpellCheckRange(nsIDOMRange *aRange)
{
NS_ENSURE_TRUE(mSpellCheck, NS_ERROR_NOT_INITIALIZED);
@ -344,7 +389,22 @@ NS_IMETHODIMP mozInlineSpellChecker::SpellCheckRange(nsIDOMRange *aRange)
CleanupRangesInSelection(spellCheckSelection);
return SpellCheckRange(aRange,spellCheckSelection);
if(aRange) {
// use the given range
rv = SpellCheckRange(aRange,spellCheckSelection);
} else {
// use full range: SpellCheckBetweenNodes will do the somewhat complicated
// task of creating a range over the element we give it and call
// SpellCheckRange(range,selection) for us
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
if (!editor)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIDOMElement> rootElem;
rv = editor->GetRootElement(getter_AddRefs(rootElem));
NS_ENSURE_SUCCESS(rv, rv);
rv = SpellCheckBetweenNodes(rootElem, 0, rootElem, -1, spellCheckSelection);
}
return rv;
}
NS_IMETHODIMP mozInlineSpellChecker::GetMispelledWord(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMRange **newword)

Просмотреть файл

@ -56,6 +56,12 @@ class mozInlineSpellChecker : public nsIInlineSpellChecker, nsIEditActionListene
{
private:
// Access with CanEnableInlineSpellChecking
enum SpellCheckingState { SpellCheck_Uninitialized = -1,
SpellCheck_NotAvailable = 0,
SpellCheck_Available = 1};
static SpellCheckingState gCanEnableSpellChecking;
nsWeakPtr mEditor;
nsCOMPtr<nsIEditorSpellCheck> mSpellCheck;
nsCOMPtr<nsITextServicesDocument> mTextServicesDocument;
@ -113,6 +119,9 @@ public:
NS_DECL_NSIEDITACTIONLISTENER
NS_DECL_NSIINLINESPELLCHECKER
// returns true if it looks likely that we can enable real-time spell checking
static PRBool CanEnableInlineSpellChecking();
/*BEGIN implementations of mouseevent handler interface*/
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);

Просмотреть файл

@ -63,7 +63,41 @@
NS_GENERIC_FACTORY_CONSTRUCTOR(mozSpellChecker)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(mozPersonalDictionary, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(mozSpellI18NManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(mozInlineSpellChecker)
// This special constructor for the inline spell checker asks the inline
// spell checker if we can create spell checking objects at all (ie, if there
// are any dictionaries loaded) before trying to create one. The static
// CanEnableInlineSpellChecking caches the value so this will be faster (we
// have to run this code for every edit box we create, as well as for every
// right click in those edit boxes).
static NS_IMETHODIMP
mozInlineSpellCheckerConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
{
if (! mozInlineSpellChecker::CanEnableInlineSpellChecking())
return NS_ERROR_FAILURE;
nsresult rv;
mozInlineSpellChecker* inst;
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
NS_NEWXPCOM(inst, mozInlineSpellChecker);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
////////////////////////////////////////////////////////////////////////
// Define a table of CIDs implemented by this module along with other

Просмотреть файл

@ -103,6 +103,7 @@ REQUIRES = xpcom \
commandhandler \
webbrwsr \
uconv \
txtsvc \
$(NULL)
CPPSRCS = \

Просмотреть файл

@ -57,6 +57,7 @@ REQUIRES = xpcom \
necko \
webshell \
editor \
txtsvc \
intl \
uconv \
txmgr \

Просмотреть файл

@ -67,6 +67,7 @@
#include "nsIScrollableFrame.h" //to turn off scroll bars
#include "nsFormControlFrame.h" //for registering accesskeys
#include "nsIDeviceContext.h" // to measure fonts
#include "nsIInlineSpellChecker.h"
#include "nsIContent.h"
#include "nsIAtom.h"
@ -132,6 +133,8 @@
#define DEFAULT_COLUMN_WIDTH 20
#define PREF_DEFAULT_SPELLCHECK "layout.textarea.spellcheckDefault"
#include "nsContentCID.h"
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
@ -1661,6 +1664,63 @@ nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext,
return NS_ERROR_FAILURE;
}
// nsTextControlFrame::SetEnableRealTimeSpell
//
// This enables or disables the spellchecker based on the given flag. It
// will only create a spellcheck object if necessary.
void
nsTextControlFrame::SetEnableRealTimeSpell(PRBool aEnabled)
{
nsresult rv = NS_OK;
NS_ASSERTION(!aEnabled || !IsPasswordTextControl(),
"don't enable real time spell for password controls");
// The editor will lazily create the spell checker object if it has not been
// created. We only want one created if we are turning it on, since not
// created implies there's no spell checking yet.
nsCOMPtr<nsIInlineSpellChecker> inlineSpellChecker;
rv = mEditor->GetInlineSpellChecker(aEnabled,
getter_AddRefs(inlineSpellChecker));
if (NS_SUCCEEDED(rv) && inlineSpellChecker) {
inlineSpellChecker->SetEnableRealTimeSpell(aEnabled);
}
}
// nsTextControlFrame::SyncRealTimeSpell
//
// This function is called to update whether inline spell checking is enabled
// for the control. It is called on initialization and when things happen
// that might affect spellchecking (for example, if it gets enabled or
// disabled).
//
// Multi-line text controls are spellchecked when the preference is set.
// Everything else (including read-only textareas) are not spellchecked by
// default.
void
nsTextControlFrame::SyncRealTimeSpell()
{
PRBool readOnly = PR_FALSE;
if (mEditor) {
PRUint32 flags;
mEditor->GetFlags(&flags);
if (flags & nsIPlaintextEditor::eEditorReadonlyMask)
readOnly = PR_TRUE;
}
PRBool enable = PR_FALSE;
if (!readOnly && !IsSingleLineTextControl()) {
// multi-line text control: check the pref to see what the default should be
// GetBoolPref defaults the value to PR_FALSE is the pref is not set
enable = nsContentUtils::GetBoolPref(PREF_DEFAULT_SPELLCHECK);
}
SetEnableRealTimeSpell(enable);
}
nsresult
nsTextControlFrame::InitEditor()
{
@ -1745,6 +1805,8 @@ nsTextControlFrame::InitEditor()
transMgr->SetMaxTransactionCount(DEFAULT_UNDO_CAP);
SyncRealTimeSpell();
if (IsPasswordTextControl()) {
// Disable undo for password textfields. Note that we want to do this at
// the very end of InitEditor, so the calls to EnableUndo when setting the
@ -2811,6 +2873,7 @@ nsTextControlFrame::AttributeChanged(PRInt32 aNameSpaceID,
mSelCon->SetCaretEnabled(PR_TRUE);
}
mEditor->SetFlags(flags);
SyncRealTimeSpell();
}
else if (mEditor && nsHTMLAtoms::disabled == aAttribute)
{

Просмотреть файл

@ -290,6 +290,9 @@ private:
nsresult SelectAllContents();
nsresult SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd);
void SetEnableRealTimeSpell(PRBool aEnabled);
void SyncRealTimeSpell();
private:
nsCOMPtr<nsIEditor> mEditor;
nsCOMPtr<nsISelectionController> mSelCon;