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:
@@ -61,6 +61,7 @@ REQUIRES = xpcom \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsComposeTxtSrvFilter.cpp \
|
||||
nsEditorParserObserver.cpp \
|
||||
nsComposerController.cpp \
|
||||
nsComposerCommands.cpp \
|
||||
|
||||
90
mozilla/editor/composer/src/nsComposeTxtSrvFilter.cpp
Normal file
90
mozilla/editor/composer/src/nsComposeTxtSrvFilter.cpp
Normal 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;
|
||||
}
|
||||
91
mozilla/editor/composer/src/nsComposeTxtSrvFilter.h
Normal file
91
mozilla/editor/composer/src/nsComposeTxtSrvFilter.h
Normal 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
|
||||
@@ -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, },
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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___
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@ REQUIRES = xpcom \
|
||||
layout \
|
||||
content \
|
||||
txmgr \
|
||||
txtsvc \
|
||||
htmlparser \
|
||||
necko \
|
||||
pref \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
1
mozilla/editor/txtsvc/public/MANIFEST_IDL
Normal file
1
mozilla/editor/txtsvc/public/MANIFEST_IDL
Normal file
@@ -0,0 +1 @@
|
||||
nsITextServicesFilter.idl
|
||||
@@ -35,5 +35,9 @@ EXPORTS = \
|
||||
nsTextServicesCID.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsITextServicesFilter.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
@@ -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().
|
||||
|
||||
55
mozilla/editor/txtsvc/public/nsITextServicesFilter.idl
Normal file
55
mozilla/editor/txtsvc/public/nsITextServicesFilter.idl
Normal 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);
|
||||
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ REQUIRES = xpcom \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsFilteredContentIterator.cpp \
|
||||
nsTextServicesDocument.cpp \
|
||||
nsTSDNotifier.cpp \
|
||||
$(NULL)
|
||||
|
||||
480
mozilla/editor/txtsvc/src/nsFilteredContentIterator.cpp
Normal file
480
mozilla/editor/txtsvc/src/nsFilteredContentIterator.cpp
Normal 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);
|
||||
}
|
||||
104
mozilla/editor/txtsvc/src/nsFilteredContentIterator.h
Normal file
104
mozilla/editor/txtsvc/src/nsFilteredContentIterator.h
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user