mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 1430982 - part 10: Make EditorBase store TextServicesDocument for its mInlineSpellChecker for avoiding to run for loops to call nsIEditActionListener methods r=m_kato
Currently, first edit action listener is always TextServicesDocument for EditorBase::mInlineSpellChecker if spell check is enabled and it requires only DidDeleteNode() and DidJoinNodes(). So, in most cases, EditorBase should call only them to avoid running redundant for loops for nsIEditActionListener methods. This patch makes that EditorBase::AddEditActionListener() and RemoveEditActionListener() check whether coming nsIEditActionListener is TextServicesDocument for mInlineSpellChecker. If so, EditorBase should store it as reference to TextServicesDocument. And when edit action occurs, its DidDeleteNode() and DidJoinNodes() should be called directly. Unfortunately, this patch makes TextServiceDocument's maintaining rules complicated. However, it must be really rare case to add new edit action listener because it's really old component. Note that EditorSpellCheck may be created multiple instances for an editor from chrome JS. Therefore, we need to keep TextServicesDocument being derived from nsIEditActionListener because in such case, TextServicesDocument for other EditorSpellCheck instances should be supported via nsIEditActionListener even though such case makes EditorBase slower. MozReview-Commit-ID: KtlXsBCOzKL --HG-- extra : rebase_source : 6827ed09a028f2049fd7afba2f5116d092bd14e5
This commit is contained in:
parent
0c82cf40da
commit
2020349542
@ -399,6 +399,16 @@ EditorSpellCheck::InitSpellChecker(nsIEditor* aEditor,
|
||||
new TextServicesDocument();
|
||||
textServicesDocument->SetFilter(mTxtSrvFilter);
|
||||
|
||||
// EditorBase::AddEditActionListener() needs to access mSpellChecker and
|
||||
// mSpellChecker->GetTextServicesDocument(). Therefore, we need to
|
||||
// initialize them before calling TextServicesDocument::InitWithEditor()
|
||||
// since it calls EditorBase::AddEditActionListener().
|
||||
mSpellChecker = new mozSpellChecker();
|
||||
rv = mSpellChecker->SetDocument(textServicesDocument, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Pass the editor to the text services document
|
||||
rv = textServicesDocument->InitWithEditor(aEditor);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -438,12 +448,8 @@ EditorSpellCheck::InitSpellChecker(nsIEditor* aEditor,
|
||||
}
|
||||
}
|
||||
|
||||
mSpellChecker = new mozSpellChecker();
|
||||
rv = mSpellChecker->Init();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
rv = mSpellChecker->SetDocument(textServicesDocument, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// do not fail if UpdateCurrentDictionary fails because this method may
|
||||
// succeed later.
|
||||
rv = UpdateCurrentDictionary(aCallback);
|
||||
|
@ -27,26 +27,28 @@
|
||||
#include "SplitNodeTransaction.h" // for SplitNodeTransaction
|
||||
#include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc.
|
||||
#include "TextEditUtils.h" // for TextEditUtils
|
||||
#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
|
||||
#include "mozilla/CheckedInt.h" // for CheckedInt
|
||||
#include "mozilla/EditAction.h" // for EditAction
|
||||
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
|
||||
#include "mozilla/EditorSpellCheck.h" // for EditorSpellCheck
|
||||
#include "mozilla/EditorUtils.h" // for AutoRules, etc.
|
||||
#include "mozilla/EditTransactionBase.h" // for EditTransactionBase
|
||||
#include "mozilla/FlushType.h" // for FlushType::Frames
|
||||
#include "mozilla/IMEStateManager.h" // for IMEStateManager
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc.
|
||||
#include "mozilla/mozInlineSpellChecker.h" // for mozInlineSpellChecker
|
||||
#include "mozilla/mozSpellChecker.h" // for mozSpellChecker
|
||||
#include "mozilla/Preferences.h" // for Preferences
|
||||
#include "mozilla/RangeBoundary.h" // for RawRangeBoundary, RangeBoundary
|
||||
#include "mozilla/dom/Selection.h" // for Selection, etc.
|
||||
#include "mozilla/Services.h" // for GetObserverService
|
||||
#include "mozilla/TextComposition.h" // for TextComposition
|
||||
#include "mozilla/TextServicesDocument.h" // for TextServicesDocument
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc.
|
||||
#include "nsAString.h" // for nsAString::Length, etc.
|
||||
#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
|
||||
#include "nsCaret.h" // for nsCaret
|
||||
@ -166,6 +168,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectionController)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextServicesDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
|
||||
@ -188,6 +191,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionController)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextServicesDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers)
|
||||
@ -466,6 +470,7 @@ EditorBase::PreDestroy(bool aDestroyingFrames)
|
||||
mEditorObservers.Clear();
|
||||
mDocStateListeners.Clear();
|
||||
mInlineSpellChecker = nullptr;
|
||||
mTextServicesDocument = nullptr;
|
||||
mSpellcheckCheckboxState = eTriUnset;
|
||||
mRootElement = nullptr;
|
||||
|
||||
@ -1634,6 +1639,11 @@ EditorBase::JoinNodes(nsINode& aLeftNode,
|
||||
htmlEditRules->DidJoinNodes(aLeftNode, aRightNode);
|
||||
}
|
||||
|
||||
if (mTextServicesDocument && NS_SUCCEEDED(rv)) {
|
||||
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
|
||||
textServicesDocument->DidJoinNodes(aLeftNode, aRightNode);
|
||||
}
|
||||
|
||||
if (!mActionListeners.IsEmpty()) {
|
||||
AutoActionListenerArray listeners(mActionListeners);
|
||||
for (auto& listener : listeners) {
|
||||
@ -1673,6 +1683,11 @@ EditorBase::DeleteNode(nsINode* aNode)
|
||||
nsresult rv = deleteNodeTransaction ? DoTransaction(deleteNodeTransaction) :
|
||||
NS_ERROR_FAILURE;
|
||||
|
||||
if (mTextServicesDocument && NS_SUCCEEDED(rv)) {
|
||||
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
|
||||
textServicesDocument->DidDeleteNode(aNode);
|
||||
}
|
||||
|
||||
if (!mActionListeners.IsEmpty()) {
|
||||
AutoActionListenerArray listeners(mActionListeners);
|
||||
for (auto& listener : listeners) {
|
||||
@ -2175,6 +2190,26 @@ EditorBase::AddEditActionListener(nsIEditActionListener* aListener)
|
||||
{
|
||||
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// If given edit action listener is text services document for the inline
|
||||
// spell checker, store it as reference of concrete class for performance
|
||||
// reason.
|
||||
if (mInlineSpellChecker) {
|
||||
EditorSpellCheck* editorSpellCheck =
|
||||
mInlineSpellChecker->GetEditorSpellCheck();
|
||||
if (editorSpellCheck) {
|
||||
mozSpellChecker* spellChecker = editorSpellCheck->GetSpellChecker();
|
||||
if (spellChecker) {
|
||||
TextServicesDocument* textServicesDocument =
|
||||
spellChecker->GetTextServicesDocument();
|
||||
if (static_cast<nsIEditActionListener*>(textServicesDocument) ==
|
||||
aListener) {
|
||||
mTextServicesDocument = textServicesDocument;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the listener isn't already on the list
|
||||
if (!mActionListeners.Contains(aListener)) {
|
||||
mActionListeners.AppendElement(*aListener);
|
||||
@ -2188,6 +2223,11 @@ EditorBase::RemoveEditActionListener(nsIEditActionListener* aListener)
|
||||
{
|
||||
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
|
||||
|
||||
if (static_cast<nsIEditActionListener*>(mTextServicesDocument) == aListener) {
|
||||
mTextServicesDocument = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mActionListeners.RemoveElement(aListener);
|
||||
|
||||
return NS_OK;
|
||||
@ -4392,6 +4432,12 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
|
||||
htmlEditRules->DidDeleteText(deleteNode, deleteCharOffset, 1);
|
||||
}
|
||||
|
||||
if (mTextServicesDocument && NS_SUCCEEDED(rv) &&
|
||||
deleteNode && !deleteCharData) {
|
||||
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
|
||||
textServicesDocument->DidDeleteNode(deleteNode);
|
||||
}
|
||||
|
||||
// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
|
||||
{
|
||||
AutoActionListenerArray listeners(mActionListeners);
|
||||
|
@ -76,6 +76,7 @@ class SplitNodeResult;
|
||||
class SplitNodeTransaction;
|
||||
class TextComposition;
|
||||
class TextEditor;
|
||||
class TextServicesDocument;
|
||||
enum class EditAction : int32_t;
|
||||
|
||||
namespace dom {
|
||||
@ -1385,6 +1386,8 @@ protected:
|
||||
nsCString mContentMIMEType;
|
||||
|
||||
RefPtr<mozInlineSpellChecker> mInlineSpellChecker;
|
||||
// Reference to text services document for mInlineSpellChecker.
|
||||
RefPtr<TextServicesDocument> mTextServicesDocument;
|
||||
|
||||
RefPtr<nsTransactionManager> mTxnMgr;
|
||||
// Cached root node.
|
||||
|
@ -1477,51 +1477,35 @@ TextServicesDocument::InsertText(const nsString* aText)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidInsertNode(nsIDOMNode* aNode,
|
||||
nsresult aResult)
|
||||
void
|
||||
TextServicesDocument::DidDeleteNode(nsINode* aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidDeleteNode(nsIDOMNode* aChild,
|
||||
nsresult aResult)
|
||||
{
|
||||
NS_ENSURE_SUCCESS(aResult, NS_OK);
|
||||
|
||||
NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
|
||||
|
||||
//**** KDEBUG ****
|
||||
// printf("** DeleteNode: 0x%.8x\n", aChild);
|
||||
// fflush(stdout);
|
||||
//**** KDEBUG ****
|
||||
if (NS_WARN_IF(!mIterator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK_DOC(this);
|
||||
|
||||
int32_t nodeIndex = 0;
|
||||
bool hasEntry = false;
|
||||
OffsetEntry *entry;
|
||||
nsCOMPtr<nsINode> child = do_QueryInterface(aChild);
|
||||
|
||||
nsresult rv =
|
||||
NodeHasOffsetEntry(&mOffsetTable, child, &hasEntry, &nodeIndex);
|
||||
|
||||
NodeHasOffsetEntry(&mOffsetTable, aChild, &hasEntry, &nodeIndex);
|
||||
if (NS_FAILED(rv)) {
|
||||
UNLOCK_DOC(this);
|
||||
return rv;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasEntry) {
|
||||
// It's okay if the node isn't in the offset table, the
|
||||
// editor could be cleaning house.
|
||||
UNLOCK_DOC(this);
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
nsINode* node = mIterator->GetCurrentNode();
|
||||
|
||||
if (node && node == child &&
|
||||
if (node && node == aChild &&
|
||||
mIteratorStatus != IteratorStatus::eDone) {
|
||||
// XXX: This should never really happen because
|
||||
// AdjustContentIterator() should have been called prior
|
||||
@ -1533,16 +1517,15 @@ TextServicesDocument::DidDeleteNode(nsIDOMNode* aChild,
|
||||
}
|
||||
|
||||
int32_t tcount = mOffsetTable.Length();
|
||||
|
||||
while (nodeIndex < tcount) {
|
||||
entry = mOffsetTable[nodeIndex];
|
||||
|
||||
if (!entry) {
|
||||
UNLOCK_DOC(this);
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->mNode == child) {
|
||||
if (entry->mNode == aChild) {
|
||||
entry->mIsValid = false;
|
||||
}
|
||||
|
||||
@ -1550,41 +1533,16 @@ TextServicesDocument::DidDeleteNode(nsIDOMNode* aChild,
|
||||
}
|
||||
|
||||
UNLOCK_DOC(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidSplitNode(nsIDOMNode* aExistingRightNode,
|
||||
nsIDOMNode* aNewLeftNode)
|
||||
void
|
||||
TextServicesDocument::DidJoinNodes(nsINode& aLeftNode,
|
||||
nsINode& aRightNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidJoinNodes(nsIDOMNode* aLeftNode,
|
||||
nsIDOMNode* aRightNode,
|
||||
nsIDOMNode* aParent,
|
||||
nsresult aResult)
|
||||
{
|
||||
NS_ENSURE_SUCCESS(aResult, NS_OK);
|
||||
|
||||
//**** KDEBUG ****
|
||||
// printf("** JoinNodes: 0x%.8x 0x%.8x 0x%.8x\n", aLeftNode, aRightNode, aParent);
|
||||
// fflush(stdout);
|
||||
//**** KDEBUG ****
|
||||
|
||||
// Make sure that both nodes are text nodes -- otherwise we don't care.
|
||||
|
||||
nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
|
||||
nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
|
||||
|
||||
if (!leftNode || !leftNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!rightNode || !rightNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return NS_OK;
|
||||
if (!aLeftNode.IsNodeOfType(nsINode::eTEXT) ||
|
||||
!aRightNode.IsNodeOfType(nsINode::eTEXT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: The editor merges the contents of the left node into the
|
||||
@ -1596,31 +1554,34 @@ TextServicesDocument::DidJoinNodes(nsIDOMNode* aLeftNode,
|
||||
bool rightHasEntry = false;
|
||||
|
||||
nsresult rv =
|
||||
NodeHasOffsetEntry(&mOffsetTable, leftNode, &leftHasEntry, &leftIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NodeHasOffsetEntry(&mOffsetTable, &aLeftNode, &leftHasEntry, &leftIndex);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!leftHasEntry) {
|
||||
// It's okay if the node isn't in the offset table, the
|
||||
// editor could be cleaning house.
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
rv = NodeHasOffsetEntry(&mOffsetTable, rightNode,
|
||||
rv = NodeHasOffsetEntry(&mOffsetTable, &aRightNode,
|
||||
&rightHasEntry, &rightIndex);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rightHasEntry) {
|
||||
// It's okay if the node isn't in the offset table, the
|
||||
// editor could be cleaning house.
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(leftIndex < rightIndex, "Indexes out of order.");
|
||||
|
||||
if (leftIndex > rightIndex) {
|
||||
// Don't know how to handle this situation.
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK_DOC(this);
|
||||
@ -1630,26 +1591,23 @@ TextServicesDocument::DidJoinNodes(nsIDOMNode* aLeftNode,
|
||||
|
||||
// Run through the table and change all entries referring to
|
||||
// the left node so that they now refer to the right node:
|
||||
|
||||
uint32_t nodeLength = leftNode->Length();
|
||||
|
||||
uint32_t nodeLength = aLeftNode.Length();
|
||||
for (int32_t i = leftIndex; i < rightIndex; i++) {
|
||||
entry = mOffsetTable[i];
|
||||
if (entry->mNode != leftNode) {
|
||||
if (entry->mNode != &aLeftNode) {
|
||||
break;
|
||||
}
|
||||
if (entry->mIsValid) {
|
||||
entry->mNode = rightNode;
|
||||
entry->mNode = &aRightNode;
|
||||
}
|
||||
}
|
||||
|
||||
// Run through the table and adjust the node offsets
|
||||
// for all entries referring to the right node.
|
||||
|
||||
for (int32_t i = rightIndex;
|
||||
i < static_cast<int32_t>(mOffsetTable.Length()); i++) {
|
||||
entry = mOffsetTable[i];
|
||||
if (entry->mNode != rightNode) {
|
||||
if (entry->mNode != &aRightNode) {
|
||||
break;
|
||||
}
|
||||
if (entry->mIsValid) {
|
||||
@ -1660,13 +1618,11 @@ TextServicesDocument::DidJoinNodes(nsIDOMNode* aLeftNode,
|
||||
// Now check to see if the iterator is pointing to the
|
||||
// left node. If it is, make it point to the right node!
|
||||
|
||||
if (mIterator->GetCurrentNode() == leftNode) {
|
||||
mIterator->PositionAt(rightNode);
|
||||
if (mIterator->GetCurrentNode() == &aLeftNode) {
|
||||
mIterator->PositionAt(&aRightNode);
|
||||
}
|
||||
|
||||
UNLOCK_DOC(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -3249,9 +3205,57 @@ TextServicesDocument::FindWordBounds(nsTArray<OffsetEntry*>* aOffsetTable,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// stubs for unused listen methods
|
||||
// -------------------------------
|
||||
/**
|
||||
* nsIEditActionListener implementation:
|
||||
* Don't implement the behavior directly here. The methods won't be called
|
||||
* if the instance is created for inline spell checker created for editor.
|
||||
* If you need to listen a new edit action, you need to add similar
|
||||
* non-virtual method and you need to call it from EditorBase directly.
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidInsertNode(nsIDOMNode* aNode,
|
||||
nsresult aResult)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidDeleteNode(nsIDOMNode* aChild,
|
||||
nsresult aResult)
|
||||
{
|
||||
if (NS_WARN_IF(NS_FAILED(aResult))) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsINode> child = do_QueryInterface(aChild);
|
||||
DidDeleteNode(child);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidSplitNode(nsIDOMNode* aExistingRightNode,
|
||||
nsIDOMNode* aNewLeftNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidJoinNodes(nsIDOMNode* aLeftNode,
|
||||
nsIDOMNode* aRightNode,
|
||||
nsIDOMNode* aParent,
|
||||
nsresult aResult)
|
||||
{
|
||||
if (NS_WARN_IF(NS_FAILED(aResult))) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
|
||||
nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
|
||||
if (NS_WARN_IF(!leftNode) || NS_WARN_IF(!rightNode)) {
|
||||
return NS_OK;
|
||||
}
|
||||
DidJoinNodes(*leftNode, *rightNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TextServicesDocument::DidCreateNode(const nsAString& aTag,
|
||||
|
@ -218,9 +218,22 @@ public:
|
||||
*/
|
||||
nsresult InsertText(const nsString* aText);
|
||||
|
||||
/* nsIEditActionListener method implementations. */
|
||||
/**
|
||||
* nsIEditActionListener method implementations.
|
||||
*/
|
||||
NS_DECL_NSIEDITACTIONLISTENER
|
||||
|
||||
/**
|
||||
* Actual edit action listeners. When you add new method here for listening
|
||||
* to new edit action, you need to make it called by EditorBase.
|
||||
* Additionally, you need to call it from proper method of
|
||||
* nsIEditActionListener too because if this is created not for inline
|
||||
* spell checker of the editor, edit actions will be notified via
|
||||
* nsIEditActionListener (slow path, though).
|
||||
*/
|
||||
void DidDeleteNode(nsINode* aChild);
|
||||
void DidJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
|
||||
|
||||
static nsresult GetRangeEndPoints(nsRange* aRange,
|
||||
nsINode** aStartContainer,
|
||||
int32_t* aStartOffset,
|
||||
|
Loading…
Reference in New Issue
Block a user