Implement filters for spellchecker, so we can skip certain nodes (like Block Quote "cite") for mail

Bug 173046 r=jfrancis sr=kin a=asa


git-svn-id: svn://10.0.0.236/trunk@135030 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rods%netscape.com
2002-12-10 15:03:04 +00:00
parent 3654c27c31
commit 3f0a190da8
20 changed files with 1074 additions and 42 deletions

View File

@@ -61,6 +61,7 @@ REQUIRES = xpcom \
$(NULL)
CPPSRCS = \
nsComposeTxtSrvFilter.cpp \
nsEditorParserObserver.cpp \
nsComposerController.cpp \
nsComposerCommands.cpp \

View File

@@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* 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 ***** */
#include "nsComposeTxtSrvFilter.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsString.h"
#include "nsINameSpaceManager.h"
nsComposeTxtSrvFilter::nsComposeTxtSrvFilter() :
mIsForMail(PR_FALSE)
{
NS_INIT_ISUPPORTS();
mBlockQuoteAtom = getter_AddRefs(do_GetAtom("blockquote"));
mTypeAtom = getter_AddRefs(do_GetAtom("type"));
mScriptAtom = getter_AddRefs(do_GetAtom("script"));
mTextAreaAtom = getter_AddRefs(do_GetAtom("textarea"));
mSelectAreaAtom = getter_AddRefs(do_GetAtom("select"));
mMapAtom = getter_AddRefs(do_GetAtom("map"));
}
NS_IMPL_ISUPPORTS1(nsComposeTxtSrvFilter, nsITextServicesFilter);
NS_IMETHODIMP
nsComposeTxtSrvFilter::Skip(nsIDOMNode* aNode, PRBool *_retval)
{
*_retval = PR_FALSE;
// Check to see if we can skip this node
// For nodes that are blockquotes, we must make sure
// their type is "cite"
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
if (content) {
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag) {
if (tag == mBlockQuoteAtom) {
if (mIsForMail) {
nsAutoString cite;
if (NS_SUCCEEDED(content->GetAttr(kNameSpaceID_None, mTypeAtom, cite))) {
*_retval = cite.EqualsIgnoreCase("cite");
}
}
} else if (tag == mScriptAtom ||
tag == mTextAreaAtom ||
tag == mSelectAreaAtom ||
tag == mMapAtom) {
*_retval = PR_TRUE;
}
}
}
return NS_OK;
}

View File

@@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* 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 ***** */
#ifndef nsComposeTxtSrvFilter_h__
#define nsComposeTxtSrvFilter_h__
#include "nsITextServicesFilter.h"
#include "nsIAtom.h"
class nsIContent;
/**
* This class implements a filter interface, that enables
* those usnig it to ski;p over certain nodes when traversing content
*
* This filter is used to skip over various form control nodes and
* mail's cite nodes
*/
class nsComposeTxtSrvFilter : public nsITextServicesFilter
{
public:
nsComposeTxtSrvFilter();
virtual ~nsComposeTxtSrvFilter() {};
// nsISupports interface...
NS_DECL_ISUPPORTS
// nsITextServicesFilter
NS_DECL_NSITEXTSERVICESFILTER
// Helper - Intializer
void Init(PRBool aIsForMail) { mIsForMail = aIsForMail; }
protected:
PRBool mIsForMail;
nsCOMPtr<nsIAtom> mBlockQuoteAtom;
nsCOMPtr<nsIAtom> mTypeAtom;
nsCOMPtr<nsIAtom> mScriptAtom;
nsCOMPtr<nsIAtom> mTextAreaAtom;
nsCOMPtr<nsIAtom> mSelectAreaAtom;
nsCOMPtr<nsIAtom> mMapAtom;
};
#define NS_COMPOSERTXTSRVFILTER_CID \
{/* {171E72DB-0F8A-412a-8461-E4C927A3A2AC}*/ \
0x171e72db, 0xf8a, 0x412a, \
{ 0x84, 0x61, 0xe4, 0xc9, 0x27, 0xa3, 0xa2, 0xac} }
// Generic for the editor
#define COMPOSER_TXTSRVFILTER_CONTRACTID "@mozilla.org/editor/txtsrvfilter;1"
// This is the same but includes "cite" typed blocked quotes
#define COMPOSER_TXTSRVFILTERMAIL_CONTRACTID "@mozilla.org/editor/txtsrvfiltermail;1"
#endif

View File

@@ -44,6 +44,7 @@
#include "nsComposerController.h" // for the CID
#include "nsEditorSpellCheck.h" // for the CID
#include "nsEditorService.h"
#include "nsComposeTxtSrvFilter.h"
#include "nsIControllerContext.h"
////////////////////////////////////////////////////////////////////////
@@ -56,39 +57,82 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditingSession)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorSpellCheck)
// There are no macros that enable us to have 2 constructors
// for the same object
//
// Here we are creating the same object with two different contract IDs
// and then initializing it different.
// Basically, we need to tell the filter whether it is doing mail or not
static nsresult
nsComposeTxtSrvFilterConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult, PRBool aIsForMail)
{
*aResult = NULL;
if (NULL != aOuter)
{
return NS_ERROR_NO_AGGREGATION;
}
nsComposeTxtSrvFilter * inst;
NS_NEWXPCOM(inst, nsComposeTxtSrvFilter);
if (NULL == inst)
{
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(inst);
inst->Init(aIsForMail);
nsresult rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
static NS_IMETHODIMP
nsComposeTxtSrvFilterConstructorForComposer(nsISupports *aOuter,
REFNSIID aIID,
void **aResult)
{
return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, PR_TRUE);
}
static NS_IMETHODIMP
nsComposeTxtSrvFilterConstructorForMail(nsISupports *aOuter,
REFNSIID aIID,
void **aResult)
{
return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, PR_FALSE);
}
NS_IMETHODIMP nsEditorDocStateControllerConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
{
static PRBool sDocStateCommandsRegistered = PR_FALSE;
static PRBool sDocStateCommandsRegistered = PR_FALSE;
nsresult rv;
nsCOMPtr<nsIControllerContext> context =
do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv);
if (NS_FAILED(rv))
return rv;
if (!context)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIControllerCommandManager> composerCommandManager(
do_GetService(NS_COMPOSERSCONTROLLERCOMMANDMANAGER_CONTRACTID, &rv));
if (NS_FAILED(rv))
return rv;
if (!composerCommandManager)
return NS_ERROR_OUT_OF_MEMORY;
if (!sDocStateCommandsRegistered)
{
rv = nsComposerController::RegisterEditorDocStateCommands(composerCommandManager);
nsresult rv;
nsCOMPtr<nsIControllerContext> context =
do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv);
if (NS_FAILED(rv))
return rv;
if (!context)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIControllerCommandManager> composerCommandManager(
do_GetService(NS_COMPOSERSCONTROLLERCOMMANDMANAGER_CONTRACTID, &rv));
if (NS_FAILED(rv))
return rv;
if (!composerCommandManager)
return NS_ERROR_OUT_OF_MEMORY;
if (!sDocStateCommandsRegistered)
{
return rv;
rv = nsComposerController::RegisterEditorDocStateCommands(composerCommandManager);
if (NS_FAILED(rv))
{
return rv;
}
sDocStateCommandsRegistered = PR_TRUE;
}
sDocStateCommandsRegistered = PR_TRUE;
}
context->SetControllerCommandManager(composerCommandManager);
return context->QueryInterface(aIID, aResult);
context->SetControllerCommandManager(composerCommandManager);
return context->QueryInterface(aIID, aResult);
}
NS_IMETHODIMP nsHTMLEditorControllerConstructor(nsISupports *aOuter, REFNSIID aIID,
@@ -151,6 +195,12 @@ static const nsModuleComponentInfo components[] = {
{ "Edit Startup Handler", NS_EDITORSERVICE_CID,
"@mozilla.org/commandlinehandler/general-startup;1?type=edit",
nsEditorServiceConstructor, },
{ "TxtSrv Filter", NS_COMPOSERTXTSRVFILTER_CID,
COMPOSER_TXTSRVFILTER_CONTRACTID,
nsComposeTxtSrvFilterConstructorForComposer, },
{ "TxtSrv Filter For Mail", NS_COMPOSERTXTSRVFILTER_CID,
COMPOSER_TXTSRVFILTERMAIL_CONTRACTID,
nsComposeTxtSrvFilterConstructorForMail, },
};
////////////////////////////////////////////////////////////////////////

View File

@@ -53,6 +53,7 @@
#include "nsIChromeRegistry.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsComposeTxtSrvFilter.h"
static NS_DEFINE_CID(kCTextServicesDocumentCID, NS_TEXTSERVICESDOCUMENT_CID);
@@ -88,6 +89,8 @@ nsEditorSpellCheck::InitSpellChecker(nsIEditor* editor)
if (!tsDoc)
return NS_ERROR_NULL_POINTER;
tsDoc->SetFilter(mTxtSrvFilter);
// Pass the editor to the text services document
rv = tsDoc->InitWithEditor(editor);
NS_ENSURE_SUCCESS(rv, rv);
@@ -401,6 +404,14 @@ nsEditorSpellCheck::UninitSpellChecker()
return NS_OK;
}
/* void setFilter (in nsITextServicesFilter filter); */
NS_IMETHODIMP
nsEditorSpellCheck::SetFilter(nsITextServicesFilter *filter)
{
mTxtSrvFilter = filter;
return NS_OK;
}
nsresult
nsEditorSpellCheck::DeleteSuggestedWordList()
{
@@ -408,7 +419,3 @@ nsEditorSpellCheck::DeleteSuggestedWordList()
mSuggestedWordIndex = 0;
return NS_OK;
}

View File

@@ -46,6 +46,8 @@
#include "nsVoidArray.h"
#include "nsCOMPtr.h"
#include "nsComposeTxtSrvFilter.h"
#define NS_EDITORSPELLCHECK_CID \
{ /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */ \
0x75656ad9, 0xbd13, 0x4c5d, \
@@ -73,6 +75,8 @@ protected:
PRInt32 mDictionaryIndex;
nsresult DeleteSuggestedWordList();
nsCOMPtr<nsITextServicesFilter> mTxtSrvFilter;
};
#endif // nsEditorSpellCheck_h___

View File

@@ -39,6 +39,7 @@
#include "nsISupports.idl"
interface nsIEditor;
interface nsITextServicesFilter;
[scriptable, uuid(87ce8b81-1cf2-11d3-9ce4-c60a16061e7c)]
interface nsIEditorSpellCheck : nsISupports
@@ -58,5 +59,6 @@ interface nsIEditorSpellCheck : nsISupports
wstring GetCurrentDictionary();
void SetCurrentDictionary(in wstring dictionary);
void UninitSpellChecker();
void setFilter(in nsITextServicesFilter filter);
};

View File

@@ -36,6 +36,7 @@ REQUIRES = xpcom \
layout \
content \
txmgr \
txtsvc \
htmlparser \
necko \
pref \

View File

@@ -1000,6 +1000,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposeTxtSrvFilter.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposerController.cpp</PATH>
@@ -1094,6 +1101,11 @@
<PATH>nsComposerCommands.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposeTxtSrvFilter.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>JavaScriptDebug.shlb</PATH>
@@ -2073,6 +2085,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposeTxtSrvFilter.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposerController.cpp</PATH>
@@ -2167,6 +2186,11 @@
<PATH>nsComposerCommands.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposeTxtSrvFilter.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>JavaScript.shlb</PATH>
@@ -2214,6 +2238,12 @@
<PATH>nsComposerCommands.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>ComposerDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsComposeTxtSrvFilter.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>ComposerDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

View File

@@ -981,6 +981,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsFilteredContentIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>NSRuntime.shlb</PATH>
@@ -1057,6 +1064,11 @@
<PATH>nsTextServicesDocument.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsFilteredContentIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>NSRuntime.shlb</PATH>
@@ -2012,6 +2024,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsFilteredContentIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>NSStdLibDebug.shlb</PATH>
@@ -2088,6 +2107,11 @@
<PATH>nsTextServicesDocument.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsFilteredContentIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>NSStdLibDebug.shlb</PATH>
@@ -2130,6 +2154,12 @@
<PATH>nsTextServicesDocument.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>TextServices.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsFilteredContentIterator.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>TextServices.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

View File

@@ -0,0 +1 @@
nsITextServicesFilter.idl

View File

@@ -35,5 +35,9 @@ EXPORTS = \
nsTextServicesCID.h \
$(NULL)
XPIDLSRCS = \
nsITextServicesFilter.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -45,6 +45,7 @@ class nsIDOMDocument;
class nsIPresShell;
class nsIEditor;
class nsString;
class nsITextServicesFilter;
/*
TextServicesDocument interface to outside world
@@ -94,6 +95,12 @@ public:
*/
NS_IMETHOD InitWithEditor(nsIEditor *aEditor) = 0;
/**
* Sets the filter to be used while iterating over content.
* @param aFilter filter to be used while iterating over content.
*/
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter) = 0;
/**
* Returns true if the document can be modified with calls
* to DeleteSelection() and InsertText().

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Rod Spears <rods@netscape.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
* 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 ***** */
#include "nsISupports.idl"
interface nsIDOMNode;
[scriptable, uuid(5BEC321F-59AC-413a-A4AD-8A8D7C50A0D0)]
interface nsITextServicesFilter : nsISupports
{
/**
* Indicates whether the content node should be skipped by the iterator
* @param aNode - node to skip
*/
boolean skip(in nsIDOMNode aNode);
};

View File

@@ -43,6 +43,7 @@ REQUIRES = xpcom \
$(NULL)
CPPSRCS = \
nsFilteredContentIterator.cpp \
nsTextServicesDocument.cpp \
nsTSDNotifier.cpp \
$(NULL)

View File

@@ -0,0 +1,480 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* 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 ***** */
#include "nsFilteredContentIterator.h"
#include "nsIContentIterator.h"
#include "nsContentCID.h"
#include "nsIContent.h"
#include "nsString.h"
#include "nsIEnumerator.h"
#include "nsTextServicesDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMRange.h"
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
static NS_DEFINE_CID(kCPreContentIteratorCID, NS_PRECONTENTITERATOR_CID);
static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID);
//------------------------------------------------------------
nsFilteredContentIterator::nsFilteredContentIterator(nsITextServicesFilter* aFilter) :
mFilter(aFilter),
mDidSkip(PR_FALSE),
mIsOutOfRange(PR_FALSE),
mDirection(eDirNotSet)
{
NS_INIT_ISUPPORTS();
nsComponentManager::CreateInstance(kCContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(mIterator));
nsComponentManager::CreateInstance(kCPreContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(mPreIterator));
}
//------------------------------------------------------------
nsFilteredContentIterator::~nsFilteredContentIterator()
{
mIterator = nsnull;
}
//------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsFilteredContentIterator, nsIContentIterator);
//------------------------------------------------------------
NS_IMETHODIMP
nsFilteredContentIterator::Init(nsIContent* aRoot)
{
NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
mIsOutOfRange = PR_FALSE;
mDirection = eForward;
mCurrentIterator = mPreIterator;
nsresult rv = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull,
NS_GET_IID(nsIDOMRange),
getter_AddRefs(mRange));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(mRange));
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aRoot));
if (domRange && domNode) {
domRange->SelectNode(domNode);
}
rv = mPreIterator->Init(domRange);
NS_ENSURE_SUCCESS(rv, rv);
return mIterator->Init(domRange);
}
//------------------------------------------------------------
NS_IMETHODIMP
nsFilteredContentIterator::Init(nsIDOMRange* aRange)
{
NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(aRange);
mIsOutOfRange = PR_FALSE;
mDirection = eForward;
mCurrentIterator = mPreIterator;
nsCOMPtr<nsIDOMRange> domRange;
nsresult rv = aRange->CloneRange(getter_AddRefs(domRange));
NS_ENSURE_SUCCESS(rv, rv);
mRange = do_QueryInterface(domRange);
rv = mPreIterator->Init(domRange);
NS_ENSURE_SUCCESS(rv, rv);
return mIterator->Init(domRange);
}
//------------------------------------------------------------
nsresult
nsFilteredContentIterator::SwitchDirections(PRPackedBool aChangeToForward)
{
nsCOMPtr<nsIContent> node;
mCurrentIterator->CurrentNode(getter_AddRefs(node));
if (aChangeToForward) {
mCurrentIterator = mPreIterator;
mDirection = eForward;
} else {
mCurrentIterator = mIterator;
mDirection = eBackward;
}
if (node) {
nsresult rv = mCurrentIterator->PositionAt(node);
if (NS_FAILED(rv)) {
mIsOutOfRange = PR_TRUE;
return rv;
}
}
return NS_OK;
}
//------------------------------------------------------------
NS_IMETHODIMP
nsFilteredContentIterator::First()
{
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
// If we are switching directions then
// we need to switch how we process the nodes
if (mDirection != eForward) {
mCurrentIterator = mPreIterator;
mDirection = eForward;
mIsOutOfRange = PR_FALSE;
}
nsresult rv = mCurrentIterator->First();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_ENUMERATOR_FALSE != mCurrentIterator->IsDone()) {
return NS_OK;
}
nsCOMPtr<nsIContent> currentContent;
rv = mCurrentIterator->CurrentNode(getter_AddRefs(currentContent));
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentContent));
PRPackedBool didCross;
CheckAdvNode(node, didCross, eForward);
return NS_OK;
}
//------------------------------------------------------------
NS_IMETHODIMP
nsFilteredContentIterator::Last()
{
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
// If we are switching directions then
// we need to switch how we process the nodes
if (mDirection != eBackward) {
mCurrentIterator = mIterator;
mDirection = eBackward;
mIsOutOfRange = PR_FALSE;
}
nsresult rv = mCurrentIterator->Last();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_ENUMERATOR_FALSE != mCurrentIterator->IsDone()) {
return NS_OK;
}
nsCOMPtr<nsIContent> currentContent;
rv = mCurrentIterator->CurrentNode(getter_AddRefs(currentContent));
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentContent));
PRPackedBool didCross;
CheckAdvNode(node, didCross, eBackward);
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////
// ContentToParentOffset: returns the content node's parent and offset.
//
static void
ContentToParentOffset(nsIContent *aContent, nsIDOMNode **aParent, PRInt32 *aOffset)
{
if (!aParent || !aOffset)
return;
*aParent = nsnull;
*aOffset = 0;
if (!aContent)
return;
nsCOMPtr<nsIContent> parent;
nsresult rv = aContent->GetParent(*getter_AddRefs(parent));
if (NS_FAILED(rv) || !parent)
return;
rv = parent->IndexOf(aContent, *aOffset);
if (NS_FAILED(rv))
return;
CallQueryInterface(parent, aParent);
}
///////////////////////////////////////////////////////////////////////////
// ContentIsInTraversalRange: returns true if content is visited during
// the traversal of the range in the specified mode.
//
static PRBool
ContentIsInTraversalRange(nsIContent *aContent, PRBool aIsPreMode,
nsIDOMNode *aStartNode, PRInt32 aStartOffset,
nsIDOMNode *aEndNode, PRInt32 aEndOffset)
{
if (!aStartNode || !aEndNode || !aContent)
return PR_FALSE;
nsCOMPtr<nsIDOMNode> parentNode;
PRInt32 indx = 0;
ContentToParentOffset(aContent, getter_AddRefs(parentNode), &indx);
if (!parentNode)
return PR_FALSE;
if (!aIsPreMode)
++indx;
PRInt32 startRes;
PRInt32 endRes;
nsresult rv = nsTextServicesDocument::ComparePoints(aStartNode, aStartOffset, parentNode, indx, &startRes);
if (NS_FAILED(rv)) return PR_FALSE;
rv = nsTextServicesDocument::ComparePoints(aEndNode, aEndOffset, parentNode, indx, &endRes);
if (NS_FAILED(rv)) return PR_FALSE;
return (startRes <= 0) && (endRes >= 0);
}
static PRBool
ContentIsInTraversalRange(nsIDOMNSRange *aRange, nsIDOMNode* aNextNode, PRBool aIsPreMode)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
nsCOMPtr<nsIDOMRange> range(do_QueryInterface(aRange));
if (!content || !range)
return PR_FALSE;
nsCOMPtr<nsIDOMNode> sNode;
nsCOMPtr<nsIDOMNode> eNode;
PRInt32 sOffset;
PRInt32 eOffset;
range->GetStartContainer(getter_AddRefs(sNode));
range->GetStartOffset(&sOffset);
range->GetEndContainer(getter_AddRefs(eNode));
range->GetEndOffset(&eOffset);
return ContentIsInTraversalRange(content, aIsPreMode, sNode, sOffset, eNode, eOffset);
}
//------------------------------------------------------------
// Helper function to advance to the next or previous node
nsresult
nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
{
nsCOMPtr<nsIDOMNode> nextNode;
if (aDir == eForward) {
aNode->GetNextSibling(getter_AddRefs(nextNode));
} else {
aNode->GetPreviousSibling(getter_AddRefs(nextNode));
}
if (nextNode) {
// If we got here, that means we found the nxt/prv node
// make sure it is in our DOMRange
PRBool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
if (intersects) {
aNewNode = nextNode;
NS_ADDREF(aNewNode);
return NS_OK;
}
} else {
// The next node was null so we need to walk up the parent(s)
nsCOMPtr<nsIDOMNode> parent;
aNode->GetParentNode(getter_AddRefs(parent));
NS_ASSERTION(parent, "parent can't be NULL");
// Make sure the parent is in the DOMRange before going further
PRBool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
if (intersects) {
// Now find the nxt/prv node after/before this node
nsresult rv = AdvanceNode(parent, aNewNode, aDir);
if (NS_SUCCEEDED(rv) && aNewNode) {
return NS_OK;
}
}
}
// if we get here it pretty much means
// we went out of the DOM Range
mIsOutOfRange = PR_TRUE;
return NS_ERROR_FAILURE;
}
//------------------------------------------------------------
// Helper function to see if the next/prev node should be skipped
void
nsFilteredContentIterator::CheckAdvNode(nsIDOMNode* aNode, PRPackedBool& aDidSkip, eDirectionType aDir)
{
aDidSkip = PR_FALSE;
mIsOutOfRange = PR_FALSE;
if (aNode && mFilter) {
nsCOMPtr<nsIDOMNode> currentNode = aNode;
PRBool skipIt;
while (1) {
nsresult rv = mFilter->Skip(aNode, &skipIt);
if (NS_SUCCEEDED(rv) && skipIt) {
aDidSkip = PR_TRUE;
// Get the next/prev node and then
// see if we should skip that
nsCOMPtr<nsIDOMNode> advNode;
rv = AdvanceNode(aNode, *getter_AddRefs(advNode), aDir);
if (NS_SUCCEEDED(rv) && advNode) {
aNode = advNode;
} else {
return; // fell out of range
}
} else {
if (aNode != currentNode) {
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
mCurrentIterator->PositionAt(content);
}
return; // found something
}
}
}
}
NS_IMETHODIMP
nsFilteredContentIterator::Next()
{
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
if (mIsOutOfRange) {
return NS_OK;
}
// If we are switching directions then
// we need to switch how we process the nodes
if (mDirection != eForward) {
nsresult rv = SwitchDirections(PR_TRUE);
if (NS_FAILED(rv)) {
return NS_OK;
}
}
nsresult rv = mCurrentIterator->Next();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_ENUMERATOR_FALSE != mCurrentIterator->IsDone()) {
return NS_OK;
}
// If we can't get the current node then
// don't check to see if we can skip it
nsCOMPtr<nsIContent> currentContent;
rv = mCurrentIterator->CurrentNode(getter_AddRefs(currentContent));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentContent));
CheckAdvNode(node, mDidSkip, eForward);
}
return NS_OK;
}
NS_IMETHODIMP
nsFilteredContentIterator::Prev()
{
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
if (mIsOutOfRange) {
return NS_OK;
}
// If we are switching directions then
// we need to switch how we process the nodes
if (mDirection != eBackward) {
nsresult rv = SwitchDirections(PR_FALSE);
if (NS_FAILED(rv)) {
return NS_OK;
}
}
nsresult rv = mCurrentIterator->Prev();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_ENUMERATOR_FALSE != mCurrentIterator->IsDone()) {
return NS_OK;
}
// If we can't get the current node then
// don't check to see if we can skip it
nsCOMPtr<nsIContent> currentContent;
rv = mCurrentIterator->CurrentNode(getter_AddRefs(currentContent));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentContent));
CheckAdvNode(node, mDidSkip, eBackward);
}
return NS_OK;
}
NS_IMETHODIMP
nsFilteredContentIterator::CurrentNode(nsIContent **aNode)
{
if (mIsOutOfRange) {
return NS_ERROR_FAILURE;
}
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
return mCurrentIterator->CurrentNode(aNode);
}
NS_IMETHODIMP
nsFilteredContentIterator::IsDone()
{
if (mIsOutOfRange) {
return NS_OK;
}
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
return mCurrentIterator->IsDone();
}
NS_IMETHODIMP
nsFilteredContentIterator::PositionAt(nsIContent* aCurNode)
{
NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
mIsOutOfRange = PR_FALSE;
return mCurrentIterator->PositionAt(aCurNode);
}

View File

@@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* 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 ***** */
#ifndef nsFilteredContentIterator_h__
#define nsFilteredContentIterator_h__
#include "nsIContentIterator.h"
#include "nsCOMPtr.h"
#include "nsIAtom.h"
#include "nsITextServicesFilter.h"
#include "nsIDOMNSRange.h"
#include "nsIRangeUtils.h"
/**
*
*/
class nsFilteredContentIterator : public nsIContentIterator
{
public:
// nsISupports interface...
NS_DECL_ISUPPORTS
nsFilteredContentIterator(nsITextServicesFilter* aFilter);
virtual ~nsFilteredContentIterator();
/* nsIContentIterator */
NS_IMETHOD Init(nsIContent* aRoot);
NS_IMETHOD Init(nsIDOMRange* aRange);
NS_IMETHOD First();
NS_IMETHOD Last();
NS_IMETHOD Next();
NS_IMETHOD Prev();
NS_IMETHOD CurrentNode(nsIContent **aNode);
NS_IMETHOD IsDone();
NS_IMETHOD PositionAt(nsIContent* aCurNode);
/* Helpers */
PRPackedBool DidSkip() { return mDidSkip; }
void ClearDidSkip() { mDidSkip = PR_FALSE; }
protected:
nsFilteredContentIterator() { }
// enum to give us the direction
typedef enum {eDirNotSet, eForward, eBackward} eDirectionType;
nsresult AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir);
void CheckAdvNode(nsIDOMNode* aNode, PRPackedBool& aDidSkip, eDirectionType aDir);
nsresult SwitchDirections(PRPackedBool aChangeToForward);
nsCOMPtr<nsIContentIterator> mCurrentIterator;
nsCOMPtr<nsIContentIterator> mIterator;
nsCOMPtr<nsIContentIterator> mPreIterator;
nsCOMPtr<nsIAtom> mBlockQuoteAtom;
nsCOMPtr<nsIAtom> mScriptAtom;
nsCOMPtr<nsIAtom> mTextAreaAtom;
nsCOMPtr<nsIAtom> mSelectAreaAtom;
nsCOMPtr<nsIAtom> mMapAtom;
nsCOMPtr<nsITextServicesFilter> mFilter;
nsCOMPtr<nsIDOMNSRange> mRange;
PRPackedBool mDidSkip;
PRPackedBool mIsOutOfRange;
eDirectionType mDirection;
};
#endif

View File

@@ -49,6 +49,7 @@
#include "nsISelection.h"
#include "nsIPlaintextEditor.h"
#include "nsTextServicesDocument.h"
#include "nsFilteredContentIterator.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLElement.h"
@@ -390,6 +391,15 @@ nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
return result;
}
NS_IMETHODIMP
nsTextServicesDocument::SetFilter(nsITextServicesFilter *aFilter)
{
// Hang on to the filter so we can set it into the filtered iterator.
mTxtSvcFilter = aFilter;
return NS_OK;
}
NS_IMETHODIMP
nsTextServicesDocument::CanEdit(PRBool *aCanEdit)
{
@@ -2580,12 +2590,19 @@ nsTextServicesDocument::CreateContentIterator(nsIDOMRange *aRange, nsIContentIte
*aIterator = 0;
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
NS_GET_IID(nsIContentIterator),
(void **)aIterator);
if (NS_FAILED(result))
return result;
// Create a nsFilteredContentIterator
// This class wraps the ContentIterator in order to give itself a chance
// to filter out certain content nodes
nsFilteredContentIterator* filter = new nsFilteredContentIterator(mTxtSvcFilter);
*aIterator = NS_STATIC_CAST(nsIContentIterator *, filter);
if (*aIterator) {
NS_IF_ADDREF(*aIterator);
result = filter ? NS_OK : NS_ERROR_FAILURE;
} else {
delete filter;
result = NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(result, result);
if (!*aIterator)
return NS_ERROR_NULL_POINTER;
@@ -2928,6 +2945,33 @@ nsTextServicesDocument::AdjustContentIterator()
return NS_OK;
}
PRBool
nsTextServicesDocument::DidSkip(nsIContentIterator* aFilteredIter)
{
// We can assume here that the Iterator is a nsFilteredContentIterator because
// all the iterator are created in CreateContentIterator which create a
// nsFilteredContentIterator
// So if the iterator bailed on one of the "filtered" content nodes then we
// consider that to be a block and bail with PR_TRUE
if (aFilteredIter) {
nsFilteredContentIterator* filter = NS_STATIC_CAST(nsFilteredContentIterator *, aFilteredIter);
if (filter && filter->DidSkip()) {
return PR_TRUE;
}
}
return PR_FALSE;
}
void
nsTextServicesDocument::ClearDidSkip(nsIContentIterator* aFilteredIter)
{
// Clear filter's skip flag
if (aFilteredIter) {
nsFilteredContentIterator* filter = NS_STATIC_CAST(nsFilteredContentIterator *, aFilteredIter);
filter->ClearDidSkip();
}
}
PRBool
nsTextServicesDocument::IsBlockNode(nsIContent *aContent)
{
@@ -4024,6 +4068,8 @@ nsTextServicesDocument::FirstTextNodeInCurrentBlock(nsIContentIterator *iter)
if (!iter)
return NS_ERROR_NULL_POINTER;
ClearDidSkip(iter);
nsCOMPtr<nsIContent> content;
nsCOMPtr<nsIContent> last;
@@ -4055,6 +4101,9 @@ nsTextServicesDocument::FirstTextNodeInCurrentBlock(nsIContentIterator *iter)
if (NS_FAILED(result))
return result;
if (DidSkip(iter))
break;
}
if (last)
@@ -4107,6 +4156,8 @@ nsTextServicesDocument::FirstTextNodeInNextBlock(nsIContentIterator *aIterator)
if (!aIterator)
return NS_ERROR_NULL_POINTER;
ClearDidSkip(aIterator);
while (NS_ENUMERATOR_FALSE == aIterator->IsDone())
{
result = aIterator->CurrentNode(getter_AddRefs(content));
@@ -4122,15 +4173,17 @@ nsTextServicesDocument::FirstTextNodeInNextBlock(nsIContentIterator *aIterator)
prev = content;
else
break;
}
else if (IsBlockNode(content))
else if (!crossedBlockBoundary && IsBlockNode(content))
crossedBlockBoundary = PR_TRUE;
result = aIterator->Next();
if (NS_FAILED(result))
return result;
if (!crossedBlockBoundary && DidSkip(aIterator))
crossedBlockBoundary = PR_TRUE;
}
return NS_OK;
@@ -4255,6 +4308,8 @@ nsTextServicesDocument::CreateOffsetTable(nsString *aStr)
PRInt32 offset = 0;
ClearDidSkip(mIterator);
while (NS_ENUMERATOR_FALSE == mIterator->IsDone())
{
result = mIterator->CurrentNode(getter_AddRefs(content));
@@ -4318,6 +4373,9 @@ nsTextServicesDocument::CreateOffsetTable(nsString *aStr)
if (NS_FAILED(result))
return result;
if (DidSkip(mIterator))
break;
}
if (first)

View File

@@ -51,6 +51,7 @@
#include "nsVoidArray.h"
#include "nsTSDNotifier.h"
#include "nsISelectionController.h"
#include "nsITextServicesFilter.h"
/** implementation of a text services object.
*
@@ -109,6 +110,8 @@ private:
PRInt32 mSelEndIndex;
PRInt32 mSelEndOffset;
nsCOMPtr<nsITextServicesFilter> mTxtSvcFilter;
public:
/** The default constructor.
@@ -125,6 +128,7 @@ public:
/* nsITextServicesDocument method implementations. */
NS_IMETHOD InitWithDocument(nsIDOMDocument *aDOMDocument, nsIPresShell *aPresShell);
NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
NS_IMETHOD CanEdit(PRBool *aCanEdit);
NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
NS_IMETHOD FirstBlock();
@@ -152,6 +156,11 @@ public:
nsIDOMNode *aRightNode,
nsIDOMNode *aParent);
/* Helper functions */
static nsresult ComparePoints(nsIDOMNode *aParent1, PRInt32 aOffset1, nsIDOMNode *aParent2, PRInt32 aOffset2, PRInt32 *aResult);
static nsresult GetRangeEndPoints(nsIDOMRange *aRange, nsIDOMNode **aParent1, PRInt32 *aOffset1, nsIDOMNode **aParent2, PRInt32 *aOffset2);
static nsresult CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset, nsIDOMNode *aEndParent, PRInt32 aEndOffset, nsIDOMRange **aRange);
private:
/* nsTextServicesDocument private methods. */
@@ -174,6 +183,8 @@ private:
PRBool IsBlockNode(nsIContent *aContent);
PRBool IsTextNode(nsIContent *aContent);
PRBool IsTextNode(nsIDOMNode *aNode);
PRBool DidSkip(nsIContentIterator* aFilteredIter);
void ClearDidSkip(nsIContentIterator* aFilteredIter);
PRBool HasSameBlockNodeParent(nsIContent *aContent1, nsIContent *aContent2);
@@ -185,10 +196,6 @@ private:
PRBool SelectionIsCollapsed();
PRBool SelectionIsValid();
nsresult ComparePoints(nsIDOMNode *aParent1, PRInt32 aOffset1, nsIDOMNode *aParent2, PRInt32 aOffset2, PRInt32 *aResult);
nsresult GetRangeEndPoints(nsIDOMRange *aRange, nsIDOMNode **aParent1, PRInt32 *aOffset1, nsIDOMNode **aParent2, PRInt32 *aOffset2);
nsresult CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset, nsIDOMNode *aEndParent, PRInt32 aEndOffset, nsIDOMRange **aRange);
nsresult RemoveInvalidOffsetEntries();
nsresult CreateOffsetTable(nsString *aStr=0);
nsresult ClearOffsetTable();

View File

@@ -37,6 +37,7 @@ function Startup()
window.close();
return;
}
// Get the spellChecker shell
gSpellChecker = Components.classes['@mozilla.org/editor/editorspellchecker;1'].createInstance(Components.interfaces.nsIEditorSpellCheck);
if (!gSpellChecker)
@@ -48,7 +49,16 @@ function Startup()
// Start the spell checker module.
try {
gSpellChecker.InitSpellChecker(GetCurrentEditor());
// TxtSrv Filter Contract Id
var filterContractId;
gSendMailMessageMode = window.arguments[0];
if (gSendMailMessageMode)
filterContractId = "@mozilla.org/editor/txtsrvfiltermail;1";
else
filterContractId = "@mozilla.org/editor/txtsrvfilter;1";
gSpellChecker.setFilter(Components.classes[filterContractId].createInstance(Components.interfaces.nsITextServicesFilter));
gSpellChecker.InitSpellChecker(GetCurrentEditor());
// XXX: We need to read in a pref here so we can set the
// default language for the spellchecker!
@@ -88,7 +98,6 @@ function Startup()
// When startup param is true, setup different UI when spell checking
// just before sending mail message
gSendMailMessageMode = window.arguments[0];
if (gSendMailMessageMode)
{
// If no misspelled words found, simply close dialog and send message