зеркало из https://github.com/mozilla/pjs.git
Bug #278312 --> editor changes to support inline spell checking. Includes the interface for the inline spell checker
and editor hooks to call out to an inline spell checker component. moa/r=glazman sr=bienvenu
This commit is contained in:
Родитель
ff1c1514c9
Коммит
6fcaaf5e1f
|
@ -49,6 +49,7 @@ nsComposeTxtSrvFilter::nsComposeTxtSrvFilter() :
|
|||
mPreAtom = do_GetAtom("pre");
|
||||
mSpanAtom = do_GetAtom("span");
|
||||
mMozQuoteAtom = do_GetAtom("_moz_quote");
|
||||
mClassAtom = do_GetAtom("class");
|
||||
mTypeAtom = do_GetAtom("type");
|
||||
mScriptAtom = do_GetAtom("script");
|
||||
mTextAreaAtom = do_GetAtom("textarea");
|
||||
|
@ -82,6 +83,11 @@ nsComposeTxtSrvFilter::Skip(nsIDOMNode* aNode, PRBool *_retval)
|
|||
if (NS_SUCCEEDED(content->GetAttr(kNameSpaceID_None, mMozQuoteAtom, mozQuote))) {
|
||||
*_retval = mozQuote.LowerCaseEqualsLiteral("true");
|
||||
}
|
||||
|
||||
nsAutoString className;
|
||||
if (NS_SUCCEEDED(content->GetAttr(kNameSpaceID_None, mClassAtom, className))) {
|
||||
*_retval = className.EqualsLiteral("moz-signature");
|
||||
}
|
||||
}
|
||||
} else if (tag == mScriptAtom ||
|
||||
tag == mTextAreaAtom ||
|
||||
|
|
|
@ -69,6 +69,7 @@ protected:
|
|||
nsCOMPtr<nsIAtom> mPreAtom; // mail plain text quotes are wrapped in pre tags
|
||||
nsCOMPtr<nsIAtom> mSpanAtom; //or they may be wrapped in span tags (editor.quotesPreformatted).
|
||||
nsCOMPtr<nsIAtom> mMozQuoteAtom; // _moz_quote_
|
||||
nsCOMPtr<nsIAtom> mClassAtom;
|
||||
nsCOMPtr<nsIAtom> mTypeAtom;
|
||||
nsCOMPtr<nsIAtom> mScriptAtom;
|
||||
nsCOMPtr<nsIAtom> mTextAreaAtom;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Kin Blas <kin@netscape.com>
|
||||
* Akkana Peck <akkana@netscape.com>
|
||||
* Charley Manske <cmanske@netscape.com>
|
||||
* Neil Deakin <neil@mozdevgroup.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
|
||||
|
@ -239,6 +240,17 @@ nsEditorSpellCheck::CheckCurrentWord(const PRUnichar *aSuggestedWord,
|
|||
aIsMisspelled, &mSuggestedWordList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorSpellCheck::CheckCurrentWordNoSuggest(const PRUnichar *aSuggestedWord,
|
||||
PRBool *aIsMisspelled)
|
||||
{
|
||||
if (!mSpellChecker)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
return mSpellChecker->CheckWord(nsDependentString(aSuggestedWord),
|
||||
aIsMisspelled, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditorSpellCheck::ReplaceWord(const PRUnichar *aMisspelledWord,
|
||||
const PRUnichar *aReplaceWord,
|
||||
|
|
|
@ -51,6 +51,7 @@ interface nsITransactionManager;
|
|||
interface nsITransaction;
|
||||
interface nsIEditorObserver;
|
||||
interface nsIEditActionListener;
|
||||
interface nsIInlineSpellChecker;
|
||||
|
||||
%{C++
|
||||
class nsIPresShell;
|
||||
|
@ -62,8 +63,7 @@ typedef short EDirection;
|
|||
[ptr] native nsIPresShellPtr(nsIPresShell);
|
||||
[ptr] native nsIContentPtr(nsIContent);
|
||||
|
||||
|
||||
[scriptable, uuid(e456440e-2e2b-4097-b3ec-60dc22b0aa9a)]
|
||||
[scriptable, uuid(D4882FFB-E927-408b-96BE-D4391B456FA9)]
|
||||
|
||||
interface nsIEditor : nsISupports
|
||||
{
|
||||
|
@ -283,6 +283,10 @@ interface nsIEditor : nsISupports
|
|||
*/
|
||||
void setShouldTxnSetSelection(in boolean should);
|
||||
|
||||
/* ------------ Inline Spell Checking methods -------------- */
|
||||
|
||||
readonly attribute nsIInlineSpellChecker inlineSpellChecker;
|
||||
|
||||
/* ------------ Clipboard methods -------------- */
|
||||
|
||||
/** cut the currently selected text, putting it into the OS clipboard
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
interface nsIEditor;
|
||||
interface nsITextServicesFilter;
|
||||
|
||||
[scriptable, uuid(87ce8b81-1cf2-11d3-9ce4-c60a16061e7c)]
|
||||
[scriptable, uuid(6088a862-1229-11d9-941d-c035b2e390c6)]
|
||||
interface nsIEditorSpellCheck : nsISupports
|
||||
{
|
||||
|
||||
|
@ -59,5 +59,6 @@ interface nsIEditorSpellCheck : nsISupports
|
|||
void SetCurrentDictionary(in wstring dictionary);
|
||||
void UninitSpellChecker();
|
||||
void setFilter(in nsITextServicesFilter filter);
|
||||
boolean CheckCurrentWordNoSuggest(in wstring suggestedWord);
|
||||
|
||||
};
|
||||
|
|
|
@ -53,12 +53,14 @@ REQUIRES = xpcom \
|
|||
layout \
|
||||
content \
|
||||
txmgr \
|
||||
txtsvc \
|
||||
htmlparser \
|
||||
necko \
|
||||
pref \
|
||||
view \
|
||||
gfx \
|
||||
widget \
|
||||
lwbrk \
|
||||
unicharutil \
|
||||
commandhandler \
|
||||
docshell \
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
#include "nsEditor.h"
|
||||
#include "nsEditorUtils.h"
|
||||
#include "nsISelectionDisplay.h"
|
||||
#include "nsIInlineSpellChecker.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
|
||||
|
@ -215,6 +216,9 @@ nsEditor::~nsEditor()
|
|||
delete mEditorObservers; // no need to release observers; we didn't addref them
|
||||
mEditorObservers = 0;
|
||||
|
||||
if (mInlineSpellChecker)
|
||||
mInlineSpellChecker->Cleanup();
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
PRInt32 i;
|
||||
|
@ -1141,6 +1145,22 @@ nsEditor::MarkNodeDirty(nsIDOMNode* aNode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::GetInlineSpellChecker(nsIInlineSpellChecker ** aInlineSpellChecker)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInlineSpellChecker);
|
||||
nsresult rv;
|
||||
|
||||
if (!mInlineSpellChecker) {
|
||||
mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mInlineSpellChecker->Init(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
|
@ -5234,6 +5254,26 @@ nsEditor::RemoveAttributeOrEquivalent(nsIDOMElement * aElement,
|
|||
return RemoveAttribute(aElement, aAttribute);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::HandleInlineSpellCheck(PRInt32 action,
|
||||
nsISelection *aSelection,
|
||||
nsIDOMNode *previousSelectedNode,
|
||||
PRInt32 previousSelectedOffset,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset)
|
||||
{
|
||||
return mInlineSpellChecker ? mInlineSpellChecker->SpellCheckAfterEditorChange(action,
|
||||
aSelection,
|
||||
previousSelectedNode,
|
||||
previousSelectedOffset,
|
||||
aStartNode,
|
||||
aStartOffset,
|
||||
aEndNode,
|
||||
aEndOffset) : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::SwitchTextDirection()
|
||||
{
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
#include "nsIDTD.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsSelectionState.h"
|
||||
#include "nsIEditorSpellCheck.h"
|
||||
#include "nsIInlineSpellChecker.h"
|
||||
|
||||
class nsIEditActionListener;
|
||||
class nsIDocumentStateListener;
|
||||
|
@ -547,6 +549,15 @@ public:
|
|||
|
||||
PRBool GetShouldTxnSetSelection();
|
||||
|
||||
nsresult HandleInlineSpellCheck(PRInt32 action,
|
||||
nsISelection *aSelection,
|
||||
nsIDOMNode *previousSelectedNode,
|
||||
PRInt32 previousSelectedOffset,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset);
|
||||
|
||||
public:
|
||||
// Argh! These transaction names are used by PlaceholderTxn and
|
||||
// nsPlaintextEditor. They should be localized to those classes.
|
||||
|
@ -563,6 +574,7 @@ protected:
|
|||
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
|
||||
nsIViewManager *mViewManager;
|
||||
PRInt32 mUpdateCount;
|
||||
nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker; // used for real-time spellchecking
|
||||
nsCOMPtr<nsITransactionManager> mTxnMgr;
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
|
|
|
@ -54,6 +54,7 @@ REQUIRES = xpcom \
|
|||
unicharutil \
|
||||
content \
|
||||
txmgr \
|
||||
txtsvc \
|
||||
htmlparser \
|
||||
necko \
|
||||
pref \
|
||||
|
|
|
@ -280,7 +280,22 @@ nsHTMLEditor::InsertHTMLWithContext(const nsAString & aInputString,
|
|||
// create a dom document fragment that represents the structure to paste
|
||||
nsCOMPtr<nsIDOMNode> fragmentAsNode;
|
||||
PRInt32 rangeStartHint, rangeEndHint;
|
||||
res = CreateDOMFragmentFromPaste(aInputString, aContextStr, aInfoStr,
|
||||
|
||||
nsAutoString contextStr;
|
||||
contextStr.Assign(aContextStr);
|
||||
|
||||
#ifdef MOZ_THUNDERBIRD
|
||||
// See Bug #228920 --> editor / parser has trouble inserting single cell data from Excel.
|
||||
// The details are in the bug. Until we figure out why the parser is not building the right
|
||||
// document structure for the single cell paste case, we can explicitly check for just such
|
||||
// a condition and work around it. By setting the contextStr to an empty string we end up
|
||||
// pasting just the cell text which is what we want anyway.
|
||||
// A paste from an excel cell always starts with a new line, two spaces and then the td tag
|
||||
if (StringBeginsWith(aInputString, NS_LITERAL_STRING("\n <td")))
|
||||
contextStr = NS_LITERAL_STRING("");
|
||||
#endif
|
||||
|
||||
res = CreateDOMFragmentFromPaste(aInputString, contextStr, aInfoStr,
|
||||
address_of(fragmentAsNode),
|
||||
&rangeStartHint, &rangeEndHint);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Neil Deakin <neil@mozdevgroup.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"),
|
||||
|
@ -425,13 +426,16 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
|
|||
nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> rangeStartParent, rangeEndParent;
|
||||
PRInt32 rangeStartOffset = 0, rangeEndOffset = 0;
|
||||
// do we have a real range to act on?
|
||||
PRBool bDamagedRange = PR_FALSE;
|
||||
if (mDocChangeRange)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> rangeStartParent, rangeEndParent;
|
||||
mDocChangeRange->GetStartContainer(getter_AddRefs(rangeStartParent));
|
||||
mDocChangeRange->GetEndContainer(getter_AddRefs(rangeEndParent));
|
||||
mDocChangeRange->GetStartOffset(&rangeStartOffset);
|
||||
mDocChangeRange->GetEndOffset(&rangeEndOffset);
|
||||
if (rangeStartParent && rangeEndParent)
|
||||
bDamagedRange = PR_TRUE;
|
||||
}
|
||||
|
@ -540,11 +544,19 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
|
|||
}
|
||||
}
|
||||
|
||||
res = mHTMLEditor->HandleInlineSpellCheck(action, selection,
|
||||
mRangeItem.startNode, mRangeItem.startOffset,
|
||||
rangeStartParent, rangeStartOffset,
|
||||
rangeEndParent, rangeEndOffset);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// detect empty doc
|
||||
res = CreateBogusNodeIfNeeded(selection);
|
||||
|
||||
// adjust selection HINT if needed
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
if (!mDidExplicitlySetInterline)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsITableEditor.h"
|
||||
#include "nsIEditorMailSupport.h"
|
||||
#include "nsIEditorStyleSheets.h"
|
||||
#include "nsITextServicesDocument.h"
|
||||
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
@ -788,6 +789,9 @@ protected:
|
|||
// an array for holding default style settings
|
||||
nsVoidArray mDefaultStyles;
|
||||
|
||||
// for real-time spelling
|
||||
nsCOMPtr<nsITextServicesDocument> mTextServices;
|
||||
|
||||
// Maintain a static parser service ...
|
||||
static nsIParserService* sParserService;
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ REQUIRES = xpcom \
|
|||
layout \
|
||||
content \
|
||||
txmgr \
|
||||
txtsvc \
|
||||
htmlparser \
|
||||
necko \
|
||||
pref \
|
||||
|
|
|
@ -49,7 +49,9 @@
|
|||
#include "nsIDOMNodeList.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMNSRange.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentIterator.h"
|
||||
|
@ -58,6 +60,8 @@
|
|||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIWordBreakerFactory.h"
|
||||
#include "nsLWBrkCIID.h"
|
||||
|
||||
// for IBMBIDI
|
||||
#include "nsIPresShell.h"
|
||||
|
@ -196,6 +200,15 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
nsAutoLockRulesSniffing lockIt(this);
|
||||
mDidExplicitlySetInterline = PR_FALSE;
|
||||
|
||||
// get the selection and cache the position before editing
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode));
|
||||
selection->GetAnchorOffset(&mCachedSelectionOffset);
|
||||
|
||||
if (!mActionNesting)
|
||||
{
|
||||
// let rules remember the top level action
|
||||
|
@ -221,13 +234,21 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
res = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = mEditor->HandleInlineSpellCheck(action, selection,
|
||||
mCachedSelectionNode, mCachedSelectionOffset,
|
||||
nsnull, 0, nsnull, 0);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// detect empty doc
|
||||
res = CreateBogusNodeIfNeeded(selection);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// insure trailing br node
|
||||
res = CreateTrailingBRIfNeeded();
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
/* After inserting text the cursor Bidi level must be set to the level of the inserted text.
|
||||
* This is difficult, because we cannot know what the level is until after the Bidi algorithm
|
||||
|
|
|
@ -203,6 +203,8 @@ protected:
|
|||
PRInt32 mPasswordIMEIndex;
|
||||
nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc
|
||||
nsCOMPtr<nsIDOMNode> mBody; // cached root node
|
||||
nsCOMPtr<nsIDOMNode> mCachedSelectionNode; // cached selected node
|
||||
PRInt32 mCachedSelectionOffset; // cached selected offset
|
||||
PRUint32 mFlags;
|
||||
PRUint32 mActionNesting;
|
||||
PRPackedBool mLockRulesSniffing;
|
||||
|
|
|
@ -54,6 +54,7 @@ EXPORTS = \
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsITextServicesFilter.idl \
|
||||
nsIInlineSpellChecker.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Inline Spellchecking
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Neil Deakin (enndeakin@sympatico.ca)
|
||||
* Scott MacGregor (mscott@mozilla.org)
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsISelection;
|
||||
interface nsIEditor;
|
||||
interface nsIEditorSpellCheck;
|
||||
|
||||
[scriptable, uuid(f5d1ec9e-4d30-11d8-8053-da0cc7df1f20)]
|
||||
|
||||
interface nsIInlineSpellChecker : nsISupports
|
||||
{
|
||||
readonly attribute nsIEditorSpellCheck spellChecker;
|
||||
|
||||
[noscript] void init(in nsIEditor aEditor);
|
||||
[noscript] void cleanup();
|
||||
|
||||
attribute boolean enableRealTimeSpell;
|
||||
|
||||
void spellCheckAfterEditorChange(in PRInt32 aAction,
|
||||
in nsISelection aSelection,
|
||||
in nsIDOMNode aPreviousSelectedNode,
|
||||
in PRInt32 aPreviousSelectedOffset,
|
||||
in nsIDOMNode aStartNode,
|
||||
in PRInt32 aStartOffset,
|
||||
in nsIDOMNode aEndNode,
|
||||
in PRInt32 aEndOffset);
|
||||
|
||||
void spellCheckRange(in nsIDOMRange aSelection);
|
||||
|
||||
nsIDOMRange getMispelledWord(in nsIDOMNode aNode, in PRInt32 aOffset);
|
||||
void replaceWord(in nsIDOMNode aNode, in PRInt32 aOffset, in AString aNewword);
|
||||
void addWordToDictionary(in AString aWord);
|
||||
void ignoreWord(in AString aWord);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define MOZ_INLINESPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker-inline;1"
|
||||
|
||||
%}
|
|
@ -266,6 +266,14 @@ public:
|
|||
*/
|
||||
|
||||
NS_IMETHOD SetDisplayStyle(TSDDisplayStyle aStyle) = 0;
|
||||
|
||||
/**
|
||||
* Returns the DOM range for a given offset and length
|
||||
* @param aOffset offset into string returned by GetCurrentTextBlock().
|
||||
* @param aLength number characters selected.
|
||||
* @return aDOMRange the DOM range that represents the offset and length
|
||||
*/
|
||||
NS_IMETHOD GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange) = 0;
|
||||
};
|
||||
|
||||
#endif // nsITextServicesDocument_h__
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Neil Deakin <neil@mozdevgroup.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"),
|
||||
|
@ -115,8 +116,9 @@ nsTextServicesDocument::nsTextServicesDocument()
|
|||
|
||||
nsTextServicesDocument::~nsTextServicesDocument()
|
||||
{
|
||||
if (mEditor && mNotifier)
|
||||
mEditor->RemoveEditActionListener(mNotifier);
|
||||
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
|
||||
if (editor && mNotifier)
|
||||
editor->RemoveEditActionListener(mNotifier);
|
||||
|
||||
ClearOffsetTable(&mOffsetTable);
|
||||
}
|
||||
|
@ -281,8 +283,7 @@ nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
|
|||
}
|
||||
}
|
||||
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
|
||||
mEditor = do_GetWeakReference(aEditor);
|
||||
nsTSDNotifier *notifier = new nsTSDNotifier(this);
|
||||
|
||||
if (!notifier)
|
||||
|
@ -293,7 +294,7 @@ nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
|
|||
|
||||
mNotifier = do_QueryInterface(notifier);
|
||||
|
||||
result = mEditor->AddEditActionListener(mNotifier);
|
||||
result = aEditor->AddEditActionListener(mNotifier);
|
||||
|
||||
UNLOCK_DOC(this);
|
||||
|
||||
|
@ -321,8 +322,6 @@ nsTextServicesDocument::SetExtent(nsIDOMRange* aDOMRange)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aDOMRange);
|
||||
NS_ENSURE_TRUE(mDOMDocument, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(mNotifier, NS_ERROR_FAILURE);
|
||||
|
||||
LOCK_DOC(this);
|
||||
|
||||
|
@ -548,10 +547,10 @@ nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange)
|
|||
// Now adjust the range so that it uses our new
|
||||
// end points.
|
||||
|
||||
result = aRange->SetStart(rngStartNode, rngStartOffset);
|
||||
result = aRange->SetEnd(rngEndNode, rngEndOffset);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
return aRange->SetEnd(rngEndNode, rngEndOffset);
|
||||
return aRange->SetStart(rngStartNode, rngStartOffset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -569,7 +568,9 @@ nsTextServicesDocument::CanEdit(PRBool *aCanEdit)
|
|||
if (!aCanEdit)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aCanEdit = (mEditor) ? PR_TRUE : PR_FALSE;
|
||||
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
|
||||
|
||||
*aCanEdit = (editor) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1850,11 +1851,11 @@ nsTextServicesDocument::DeleteSelection()
|
|||
nsresult result = NS_OK;
|
||||
|
||||
// We don't allow deletion during a collapsed selection!
|
||||
|
||||
NS_ASSERTION(mEditor, "DeleteSelection called without an editor present!");
|
||||
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
|
||||
NS_ASSERTION(editor, "DeleteSelection called without an editor present!");
|
||||
NS_ASSERTION(SelectionIsValid(), "DeleteSelection called without a valid selection!");
|
||||
|
||||
if (!mEditor || !SelectionIsValid())
|
||||
if (!editor || !SelectionIsValid())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (SelectionIsCollapsed())
|
||||
|
@ -2017,7 +2018,7 @@ nsTextServicesDocument::DeleteSelection()
|
|||
|
||||
// Now delete the actual content!
|
||||
|
||||
result = mEditor->DeleteSelection(nsIEditor::ePrevious);
|
||||
result = editor->DeleteSelection(nsIEditor::ePrevious);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
|
@ -2150,9 +2151,10 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
NS_ASSERTION(mEditor, "InsertText called without an editor present!");
|
||||
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
|
||||
NS_ASSERTION(editor, "InsertText called without an editor present!");
|
||||
|
||||
if (!mEditor || !SelectionIsValid())
|
||||
if (!editor || !SelectionIsValid())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!aText)
|
||||
|
@ -2183,7 +2185,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
LOCK_DOC(this);
|
||||
|
||||
result = mEditor->BeginTransaction();
|
||||
result = editor->BeginTransaction();
|
||||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
|
@ -2191,13 +2193,13 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
return result;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(mEditor, &result));
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(editor, &result));
|
||||
if (textEditor)
|
||||
result = textEditor->InsertText(*aText);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
|
@ -2235,7 +2237,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!itEntry)
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -2245,7 +2247,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2267,7 +2269,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!itEntry)
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2288,7 +2290,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!itEntry)
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -2315,7 +2317,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
|
@ -2324,7 +2326,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
|
@ -2341,7 +2343,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
|
@ -2350,7 +2352,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!itEntry)
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -2360,7 +2362,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex + 1))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2397,7 +2399,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
|
@ -2406,13 +2408,13 @@ nsTextServicesDocument::InsertText(const nsString *aText)
|
|||
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
mEditor->EndTransaction();
|
||||
editor->EndTransaction();
|
||||
UNLOCK_DOC(this);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = mEditor->EndTransaction();
|
||||
result = editor->EndTransaction();
|
||||
|
||||
UNLOCK_DOC(this);
|
||||
|
||||
|
@ -2425,18 +2427,74 @@ nsTextServicesDocument::SetDisplayStyle(TSDDisplayStyle aStyle)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextServicesDocument::GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange)
|
||||
{
|
||||
if (!mSelCon || aOffset < 0 || aLength < 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIDOMNode *sNode = 0, *eNode = 0;
|
||||
PRInt32 i, sOffset = 0, eOffset = 0;
|
||||
OffsetEntry *entry;
|
||||
|
||||
// Find the start
|
||||
for (i = 0; !sNode && i < mOffsetTable.Count(); i++)
|
||||
{
|
||||
entry = (OffsetEntry *)mOffsetTable[i];
|
||||
if (entry->mIsValid)
|
||||
{
|
||||
if (entry->mIsInsertedText)
|
||||
{
|
||||
if (entry->mStrOffset == aOffset)
|
||||
{
|
||||
sNode = entry->mNode;
|
||||
sOffset = entry->mNodeOffset + entry->mLength;
|
||||
}
|
||||
}
|
||||
else if (aOffset >= entry->mStrOffset && aOffset <= entry->mStrOffset + entry->mLength)
|
||||
{
|
||||
sNode = entry->mNode;
|
||||
sOffset = entry->mNodeOffset + aOffset - entry->mStrOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!sNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Now find the end
|
||||
PRInt32 endOffset = aOffset + aLength;
|
||||
|
||||
for (i = mOffsetTable.Count() - 1; !eNode && i >= 0; i--)
|
||||
{
|
||||
entry = (OffsetEntry *)mOffsetTable[i];
|
||||
|
||||
if (entry->mIsValid)
|
||||
{
|
||||
if (entry->mIsInsertedText)
|
||||
{
|
||||
if (entry->mStrOffset == eOffset)
|
||||
{
|
||||
eNode = entry->mNode;
|
||||
eOffset = entry->mNodeOffset + entry->mLength;
|
||||
}
|
||||
}
|
||||
else if (endOffset >= entry->mStrOffset && endOffset <= entry->mStrOffset + entry->mLength)
|
||||
{
|
||||
eNode = entry->mNode;
|
||||
eOffset = entry->mNodeOffset + endOffset - entry->mStrOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CreateRange(sNode, sOffset, eNode, eOffset, aRange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTextServicesDocument::InsertNode(nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aPosition)
|
||||
{
|
||||
//**** KDEBUG ****
|
||||
// printf("** InsertNode: 0x%.8x 0x%.8x %d\n", aNode, aParent, aPosition);
|
||||
// fflush(stdout);
|
||||
//**** KDEBUG ****
|
||||
|
||||
NS_ASSERTION(0, "InsertNode called, offset tables might be out of sync.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2499,7 +2557,6 @@ nsTextServicesDocument::DeleteNode(nsIDOMNode *aChild)
|
|||
|
||||
if (entry->mNode == aChild)
|
||||
{
|
||||
NS_ASSERTION(!entry->mIsValid, "DeleteNode called for a valid node! Offset table is out of sync.");
|
||||
entry->mIsValid = PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -2520,9 +2577,6 @@ nsTextServicesDocument::SplitNode(nsIDOMNode *aExistingRightNode,
|
|||
// printf("** SplitNode: 0x%.8x %d 0x%.8x\n", aExistingRightNode, aOffset, aNewLeftNode);
|
||||
// fflush(stdout);
|
||||
//**** KDEBUG ****
|
||||
|
||||
NS_ASSERTION(0, "SplitNode called, offset tables might be out of sync.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2589,8 +2643,6 @@ nsTextServicesDocument::JoinNodes(nsIDOMNode *aLeftNode,
|
|||
|
||||
if (!rightHasEntry)
|
||||
{
|
||||
// XXX: Not sure if we should be throwing an error here!
|
||||
NS_ASSERTION(0, "JoinNode called with node not listed in offset table.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -4579,6 +4631,13 @@ nsTextServicesDocument::GetWordBreaker(nsIWordBreaker** aResult)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Spellchecker code has this. See bug 211343
|
||||
#ifdef XP_MAC
|
||||
#define IS_NBSP_CHAR(c) (((unsigned char)0xca)==(c))
|
||||
#else
|
||||
#define IS_NBSP_CHAR(c) (((unsigned char)0xa0)==(c))
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsTextServicesDocument::FindWordBounds(nsVoidArray *aOffsetTable,
|
||||
nsString *aBlockStr,
|
||||
|
@ -4628,6 +4687,18 @@ nsTextServicesDocument::FindWordBounds(nsVoidArray *aOffsetTable,
|
|||
&beginWord, &endWord);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
// Strip out the NBSPs at the ends
|
||||
while ((beginWord <= endWord) && (IS_NBSP_CHAR(str[beginWord])))
|
||||
beginWord++;
|
||||
if (str[endWord] == (unsigned char)0x20)
|
||||
{
|
||||
PRUint32 realEndWord = endWord - 1;
|
||||
while ((realEndWord > beginWord) && (IS_NBSP_CHAR(str[realEndWord])))
|
||||
realEndWord--;
|
||||
if (realEndWord < endWord - 1)
|
||||
endWord = realEndWord + 1;
|
||||
}
|
||||
|
||||
// Now that we have the string offsets for the beginning
|
||||
// and end of the word, run through the offset table and
|
||||
// convert them back into dom points.
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsTSDNotifier.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsITextServicesFilter.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsIWordBreaker;
|
||||
class nsIRangeUtils;
|
||||
|
@ -97,7 +98,7 @@ private:
|
|||
|
||||
nsCOMPtr<nsIDOMDocument> mDOMDocument;
|
||||
nsCOMPtr<nsISelectionController>mSelCon;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsWeakPtr mEditor; // avoid a cycle with the spell checker and editor
|
||||
nsCOMPtr<nsIContentIterator> mIterator;
|
||||
TSDIteratorStatus mIteratorStatus;
|
||||
nsCOMPtr<nsIContent> mPrevTextBlock;
|
||||
|
@ -159,6 +160,7 @@ public:
|
|||
NS_IMETHOD DeleteSelection();
|
||||
NS_IMETHOD InsertText(const nsString *aText);
|
||||
NS_IMETHOD SetDisplayStyle(TSDDisplayStyle aStyle);
|
||||
NS_IMETHOD GetDOMRangeFor(PRInt32 aOffset, PRInt32 aLength, nsIDOMRange** aRange);
|
||||
|
||||
/* nsIEditActionListener method implementations. */
|
||||
nsresult InsertNode(nsIDOMNode * aNode,
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Inline Spellchecker
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozdev Group, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Neil Deakin (neil@mozdevgroup.com)
|
||||
* Scott MacGregor (mscott@mozilla.org)
|
||||
*
|
||||
* 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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const kSpellMaxNumSuggestions = 7; // Maximum number of suggested words to fill into the context menu. Most
|
||||
// applications (like Open Office) set this value to 15.
|
||||
|
||||
const kSpellNoMispelling = -1;
|
||||
const kSpellNoSuggestionsFound = 0;
|
||||
|
||||
var InlineSpellChecker =
|
||||
{
|
||||
editor : null,
|
||||
inlineSpellChecker: null,
|
||||
|
||||
Init : function (editor, enable)
|
||||
{
|
||||
this.editor = editor;
|
||||
this.inlineSpellChecker = editor.inlineSpellChecker;
|
||||
this.inlineSpellChecker.enableRealTimeSpell = enable;
|
||||
},
|
||||
|
||||
checkDocument : function(doc)
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return null;
|
||||
|
||||
var range = doc.createRange();
|
||||
range.selectNodeContents(doc.body);
|
||||
this.inlineSpellChecker.spellCheckRange(range);
|
||||
},
|
||||
|
||||
getMispelledWord : function()
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return null;
|
||||
|
||||
var selection = this.editor.selection;
|
||||
return this.inlineSpellChecker.getMispelledWord(selection.anchorNode, selection.anchorOffset);
|
||||
},
|
||||
|
||||
// returns kSpellNoMispelling if the word is spelled correctly
|
||||
// For mispelled words, returns kSpellNoSuggestionsFound when there are no suggestions otherwise the
|
||||
// number of suggestions is returned.
|
||||
// firstNonWordMenuItem is the first element in the menu popup that isn't a dynamically added word
|
||||
// added by updateSuggestionsMenu.
|
||||
updateSuggestionsMenu : function (menupopup, firstNonWordMenuItem, word)
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return kSpellNoMispelling;
|
||||
|
||||
var child = menupopup.firstChild;
|
||||
while (child != firstNonWordMenuItem)
|
||||
{
|
||||
var next = child.nextSibling;
|
||||
menupopup.removeChild(child);
|
||||
child = next;
|
||||
}
|
||||
|
||||
if (!word)
|
||||
{
|
||||
word = this.getMispelledWord();
|
||||
if (!word)
|
||||
return kSpellNoMispelling;
|
||||
}
|
||||
|
||||
var spellChecker = this.inlineSpellChecker.spellChecker;
|
||||
if (!spellChecker)
|
||||
return kSpellNoMispelling;
|
||||
|
||||
var numSuggestedWords = 0;
|
||||
|
||||
var isIncorrect = spellChecker.CheckCurrentWord(word.toString());
|
||||
if (isIncorrect)
|
||||
{
|
||||
do {
|
||||
var suggestion = spellChecker.GetSuggestedWord();
|
||||
if (!suggestion)
|
||||
break;
|
||||
|
||||
var item = document.createElement("menuitem");
|
||||
item.setAttribute("label", suggestion);
|
||||
item.setAttribute("value", suggestion);
|
||||
|
||||
item.setAttribute("oncommand", "InlineSpellChecker.selectSuggestion(event.target.value, null, null);");
|
||||
menupopup.insertBefore(item, firstNonWordMenuItem);
|
||||
numSuggestedWords++;
|
||||
} while (numSuggestedWords < kSpellMaxNumSuggestions);
|
||||
}
|
||||
else
|
||||
numSuggestedWords = kSpellNoMispelling;
|
||||
|
||||
return numSuggestedWords;
|
||||
},
|
||||
|
||||
selectSuggestion : function (newword, node, offset)
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return null;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
var selection = this.editor.selection;
|
||||
node = selection.anchorNode;
|
||||
offset = selection.anchorOffset;
|
||||
}
|
||||
|
||||
this.inlineSpellChecker.replaceWord(node, offset, newword);
|
||||
},
|
||||
|
||||
addToDictionary : function (node, offset)
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return null;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
var selection = this.editor.selection;
|
||||
node = selection.anchorNode;
|
||||
offset = selection.anchorOffset;
|
||||
}
|
||||
|
||||
var word = this.inlineSpellChecker.getMispelledWord(node,offset);
|
||||
if (word) this.inlineSpellChecker.addWordToDictionary(word);
|
||||
},
|
||||
|
||||
ignoreWord : function (node, offset)
|
||||
{
|
||||
if (!this.inlineSpellChecker || !this.inlineSpellChecker.enableRealTimeSpell)
|
||||
return null;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
var selection = this.editor.selection;
|
||||
node = selection.anchorNode;
|
||||
offset = selection.anchorOffset;
|
||||
}
|
||||
|
||||
var word = this.inlineSpellChecker.getMispelledWord(node, offset);
|
||||
if (word)
|
||||
this.inlineSpellChecker.ignoreWord(word);
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ comm.jar:
|
|||
content/editor/pref-composer.xul (composer/content/pref-composer.xul)
|
||||
content/editor/pref-publish.xul (composer/content/pref-publish.xul)
|
||||
content/editor/editorSmileyOverlay.xul (composer/content/editorSmileyOverlay.xul)
|
||||
content/editor/editorInlineSpellCheck.js (composer/content/editorInlineSpellCheck.js)
|
||||
content/editor/editorPrefsOverlay.xul (composer/content/editorPrefsOverlay.xul)
|
||||
content/editor/editorNavigatorOverlay.xul (composer/content/editorNavigatorOverlay.xul)
|
||||
content/editor/editorMailOverlay.xul (composer/content/editorMailOverlay.xul)
|
||||
|
|
Загрузка…
Ссылка в новой задаче