Bug 1540029 - part 1: Move old edit action listener methods of HTMLEditRules to EditorBase::TopLevelEditSubActionData r=m_kato

The main purpose of them is modifying
`TopLevelEditSubActionData::mChangedRange`.  Therefore, they should be in the
struct.

Differential Revision: https://phabricator.services.mozilla.com/D45783

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2019-09-17 04:27:59 +00:00
parent fae155a924
commit 9ee5b3bbef
5 changed files with 278 additions and 277 deletions

View File

@ -140,6 +140,7 @@ EditorBase::EditorBase()
mPlaceholderBatch(0), mPlaceholderBatch(0),
mDocDirtyState(-1), mDocDirtyState(-1),
mSpellcheckCheckboxState(eTriUnset), mSpellcheckCheckboxState(eTriUnset),
mInitSucceeded(false),
mAllowsTransactionsToChangeSelection(true), mAllowsTransactionsToChangeSelection(true),
mDidPreDestroy(false), mDidPreDestroy(false),
mDidPostCreate(false), mDidPostCreate(false),
@ -1386,9 +1387,8 @@ already_AddRefed<Element> EditorBase::CreateNodeWithTransaction(
aPointToInsert.GetContainer(), aPointToInsert.Offset())); aPointToInsert.GetContainer(), aPointToInsert.Offset()));
} }
if (mRules && mRules->AsHTMLEditRules() && newElement) { if (AsHTMLEditor() && newElement) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidCreateElement(*this, *newElement);
htmlEditRules->DidCreateNode(*newElement);
} }
if (!mActionListeners.IsEmpty()) { if (!mActionListeners.IsEmpty()) {
@ -1447,9 +1447,8 @@ nsresult EditorBase::InsertNodeWithTransaction(
RangeUpdaterRef().SelAdjInsertNode(aPointToInsert); RangeUpdaterRef().SelAdjInsertNode(aPointToInsert);
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidInsertContent(*this, aContentToInsert);
htmlEditRules->DidInsertNode(aContentToInsert);
} }
if (!mActionListeners.IsEmpty()) { if (!mActionListeners.IsEmpty()) {
@ -1585,28 +1584,28 @@ already_AddRefed<nsIContent> EditorBase::SplitNodeWithTransaction(
SplitNodeTransaction::Create(*this, aStartOfRightNode); SplitNodeTransaction::Create(*this, aStartOfRightNode);
aError = DoTransactionInternal(transaction); aError = DoTransactionInternal(transaction);
nsCOMPtr<nsIContent> newNode = transaction->GetNewNode(); nsCOMPtr<nsIContent> newContent = transaction->GetNewNode();
NS_WARNING_ASSERTION(newNode, "Failed to create a new left node"); NS_WARNING_ASSERTION(newContent, "Failed to create a new left node");
// XXX Some other transactions manage range updater by themselves. // XXX Some other transactions manage range updater by themselves.
// Why doesn't SplitNodeTransaction do it? // Why doesn't SplitNodeTransaction do it?
RangeUpdaterRef().SelAdjSplitNode(*aStartOfRightNode.GetContainerAsContent(), RangeUpdaterRef().SelAdjSplitNode(*aStartOfRightNode.GetContainerAsContent(),
newNode); newContent);
if (mRules && mRules->AsHTMLEditRules() && newNode) { if (AsHTMLEditor() && newContent) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidSplitContent(
htmlEditRules->DidSplitNode(*aStartOfRightNode.GetContainer(), *newNode); *this, *aStartOfRightNode.GetContainerAsContent(), *newContent);
} }
if (mInlineSpellChecker) { if (mInlineSpellChecker) {
RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker; RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker;
spellChecker->DidSplitNode(aStartOfRightNode.GetContainer(), newNode); spellChecker->DidSplitNode(aStartOfRightNode.GetContainer(), newContent);
} }
if (!mActionListeners.IsEmpty()) { if (!mActionListeners.IsEmpty()) {
AutoActionListenerArray listeners(mActionListeners); AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) { for (auto& listener : listeners) {
listener->DidSplitNode(aStartOfRightNode.GetContainer(), newNode); listener->DidSplitNode(aStartOfRightNode.GetContainer(), newContent);
} }
} }
@ -1614,7 +1613,7 @@ already_AddRefed<nsIContent> EditorBase::SplitNodeWithTransaction(
return nullptr; return nullptr;
} }
return newNode.forget(); return newContent.forget();
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1639,6 +1638,8 @@ EditorBase::JoinNodes(nsINode* aLeftNode, nsINode* aRightNode, nsINode*) {
nsresult EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode, nsresult EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode,
nsINode& aRightNode) { nsINode& aRightNode) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aLeftNode.IsContent());
MOZ_ASSERT(aRightNode.IsContent());
nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode(); nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode();
MOZ_ASSERT(parent); MOZ_ASSERT(parent);
@ -1652,9 +1653,9 @@ nsresult EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode,
// Find the number of children of the lefthand node // Find the number of children of the lefthand node
uint32_t oldLeftNodeLen = aLeftNode.Length(); uint32_t oldLeftNodeLen = aLeftNode.Length();
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().WillJoinContents(
htmlEditRules->WillJoinNodes(aLeftNode, aRightNode); *this, *aLeftNode.AsContent(), *aRightNode.AsContent());
} }
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -1669,9 +1670,9 @@ nsresult EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode,
RangeUpdaterRef().SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset, RangeUpdaterRef().SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
static_cast<int32_t>(oldLeftNodeLen)); static_cast<int32_t>(oldLeftNodeLen));
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidJoinContents(
htmlEditRules->DidJoinNodes(aLeftNode, aRightNode); *this, *aLeftNode.AsContent(), *aRightNode.AsContent());
} }
if (mInlineSpellChecker) { if (mInlineSpellChecker) {
@ -1714,13 +1715,13 @@ EditorBase::DeleteNode(nsINode* aNode) {
nsresult EditorBase::DeleteNodeWithTransaction(nsINode& aNode) { nsresult EditorBase::DeleteNodeWithTransaction(nsINode& aNode) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aNode.IsContent());
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eDeleteNode, nsIEditor::ePrevious); *this, EditSubAction::eDeleteNode, nsIEditor::ePrevious);
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().WillDeleteContent(*this, *aNode.AsContent());
htmlEditRules->WillDeleteNode(aNode);
} }
// FYI: DeleteNodeTransaction grabs aNode while it's alive. So, it's safe // FYI: DeleteNodeTransaction grabs aNode while it's alive. So, it's safe
@ -2807,10 +2808,10 @@ nsresult EditorBase::InsertTextIntoTextNodeWithTransaction(
nsresult rv = DoTransactionInternal(transaction); nsresult rv = DoTransactionInternal(transaction);
EndUpdateViewBatch(); EndUpdateViewBatch();
if (mRules && mRules->AsHTMLEditRules() && insertedTextNode) { if (AsHTMLEditor() && insertedTextNode) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidInsertText(
htmlEditRules->DidInsertText(*insertedTextNode, insertedOffset, *this, EditorRawDOMPoint(insertedTextNode, insertedOffset),
aStringToInsert); aStringToInsert);
} }
// let listeners know what happened // let listeners know what happened
@ -2951,18 +2952,6 @@ nsresult EditorBase::SetTextNodeWithoutTransaction(const nsAString& aString,
RangeUpdaterRef().SelAdjDeleteText(&aTextNode, 0, length); RangeUpdaterRef().SelAdjDeleteText(&aTextNode, 0, length);
RangeUpdaterRef().SelAdjInsertText(aTextNode, 0, aString); RangeUpdaterRef().SelAdjInsertText(aTextNode, 0, aString);
if (mRules && mRules->AsHTMLEditRules()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
if (length) {
htmlEditRules->DidDeleteText(aTextNode, 0, length);
MOZ_ASSERT(!Destroyed());
}
if (!aString.IsEmpty()) {
htmlEditRules->DidInsertText(aTextNode, 0, aString);
MOZ_ASSERT(!Destroyed());
}
}
// Let listeners know what happened // Let listeners know what happened
if (!mActionListeners.IsEmpty()) { if (!mActionListeners.IsEmpty()) {
AutoActionListenerArray listeners(mActionListeners); AutoActionListenerArray listeners(mActionListeners);
@ -3009,9 +2998,9 @@ nsresult EditorBase::DeleteTextWithTransaction(Text& aTextNode,
nsresult rv = DoTransactionInternal(transaction); nsresult rv = DoTransactionInternal(transaction);
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidDeleteText(
htmlEditRules->DidDeleteText(aTextNode, aOffset, aLength); *this, EditorRawDOMPoint(&aTextNode, aOffset));
} }
// Let listeners know what happened // Let listeners know what happened
@ -5548,4 +5537,189 @@ nsresult EditorBase::TopLevelEditSubActionData::AddRangeToChangedRange(
return NS_OK; return NS_OK;
} }
void EditorBase::TopLevelEditSubActionData::DidCreateElement(
EditorBase& aEditorBase, Element& aNewElement) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored =
AddNodeToChangedRange(*aEditorBase.AsHTMLEditor(), aNewElement);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddNodeToChangedRange() failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::DidInsertContent(
EditorBase& aEditorBase, nsIContent& aNewContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored =
AddNodeToChangedRange(*aEditorBase.AsHTMLEditor(), aNewContent);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddNodeToChangedRange() failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::WillDeleteContent(
EditorBase& aEditorBase, nsIContent& aRemovingContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored =
AddNodeToChangedRange(*aEditorBase.AsHTMLEditor(), aRemovingContent);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddNodeToChangedRange() failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::DidSplitContent(
EditorBase& aEditorBase, nsIContent& aExistingRightContent,
nsIContent& aNewLeftContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored = AddRangeToChangedRange(
*aEditorBase.AsHTMLEditor(), EditorRawDOMPoint(&aNewLeftContent, 0),
EditorRawDOMPoint(&aExistingRightContent, 0));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddRangeToChangedRange() "
"failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::WillJoinContents(
EditorBase& aEditorBase, nsIContent& aLeftContent,
nsIContent& aRightContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
// remember split point
aEditorBase.EditSubActionDataRef().mJoinedLeftNodeLength =
aLeftContent.Length();
}
void EditorBase::TopLevelEditSubActionData::DidJoinContents(
EditorBase& aEditorBase, nsIContent& aLeftContent,
nsIContent& aRightContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored = AddPointToChangedRange(
*aEditorBase.AsHTMLEditor(),
EditorRawDOMPoint(
&aRightContent,
aEditorBase.EditSubActionDataRef().mJoinedLeftNodeLength));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddPointToChangedRange() "
"failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::DidInsertText(
EditorBase& aEditorBase, const EditorRawDOMPoint& aInsertionPoint,
const nsAString& aString) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored = AddRangeToChangedRange(
*aEditorBase.AsHTMLEditor(), aInsertionPoint,
EditorRawDOMPoint(aInsertionPoint.GetContainer(),
aInsertionPoint.Offset() + aString.Length()));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddRangeToChangedRange() "
"failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::DidDeleteText(
EditorBase& aEditorBase, const EditorRawDOMPoint& aStartInTextNode) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored =
AddPointToChangedRange(*aEditorBase.AsHTMLEditor(), aStartInTextNode);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddPointToChangedRange() "
"failed, but ignored");
}
void EditorBase::TopLevelEditSubActionData::WillDeleteRange(
EditorBase& aEditorBase, const EditorRawDOMPoint& aStart,
const EditorRawDOMPoint& aEnd) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
MOZ_ASSERT(aStart.IsSet());
MOZ_ASSERT(aEnd.IsSet());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
return; // We have not been initialized yet or already been destroyed.
}
if (!aEditorBase.EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
// XXX Looks like that this is wrong. We delete multiple selection ranges
// once, but this adds only first range into the changed range.
// Anyway, we should take the range as an argument.
DebugOnly<nsresult> rvIgnored =
AddRangeToChangedRange(*aEditorBase.AsHTMLEditor(), aStart, aEnd);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddRangeToChangedRange() "
"failed, but ignored");
}
} // namespace mozilla } // namespace mozilla

View File

@ -653,23 +653,33 @@ class EditorBase : public nsIEditor,
bool mRestoreContentEditableCount; bool mRestoreContentEditableCount;
/** /**
* Extend mChangedRange to include `aNode`. * The following methods modifies some data of this struct and
* `EditSubActionData` struct. Currently, these are required only
* by `HTMLEditor`. Therefore, for cutting the runtime cost of
* `TextEditor`, these methods should be called only by `HTMLEditor`.
* But it's fine to use these methods in `TextEditor` if necessary.
* If so, you need to call `DidDeleteText()` and `DidInsertText()`
* from `SetTextNodeWithoutTransaction()`.
*/ */
nsresult AddNodeToChangedRange(const HTMLEditor& aHTMLEditor, void DidCreateElement(EditorBase& aEditorBase, Element& aNewElement);
nsINode& aNode); void DidInsertContent(EditorBase& aEditorBase, nsIContent& aNewContent);
void WillDeleteContent(EditorBase& aEditorBase,
/** nsIContent& aRemovingContent);
* Extend mChangedRange to include `aPoint`. void DidSplitContent(EditorBase& aEditorBase,
*/ nsIContent& aExistingRightContent,
nsresult AddPointToChangedRange(const HTMLEditor& aHTMLEditor, nsIContent& aNewLeftContent);
const EditorRawDOMPoint& aPoint); void WillJoinContents(EditorBase& aEditorBase, nsIContent& aLeftContent,
nsIContent& aRightContent);
/** void DidJoinContents(EditorBase& aEditorBase, nsIContent& aLeftContent,
* Extend mChangedRange to include `aStart` and `aEnd`. nsIContent& aRightContent);
*/ void DidInsertText(EditorBase& aEditorBase,
nsresult AddRangeToChangedRange(const HTMLEditor& aHTMLEditor, const EditorRawDOMPoint& aInsertionPoint,
const EditorRawDOMPoint& aStart, const nsAString& aString);
const EditorRawDOMPoint& aEnd); void DidDeleteText(EditorBase& aEditorBase,
const EditorRawDOMPoint& aStartInTextNode);
void WillDeleteRange(EditorBase& aEditorBase,
const EditorRawDOMPoint& aStart,
const EditorRawDOMPoint& aEnd);
private: private:
void Clear() { void Clear() {
@ -690,6 +700,25 @@ class EditorBase : public nsIEditor,
mRestoreContentEditableCount = false; mRestoreContentEditableCount = false;
} }
/**
* Extend mChangedRange to include `aNode`.
*/
nsresult AddNodeToChangedRange(const HTMLEditor& aHTMLEditor,
nsINode& aNode);
/**
* Extend mChangedRange to include `aPoint`.
*/
nsresult AddPointToChangedRange(const HTMLEditor& aHTMLEditor,
const EditorRawDOMPoint& aPoint);
/**
* Extend mChangedRange to include `aStart` and `aEnd`.
*/
nsresult AddRangeToChangedRange(const HTMLEditor& aHTMLEditor,
const EditorRawDOMPoint& aStart,
const EditorRawDOMPoint& aEnd);
TopLevelEditSubActionData() = default; TopLevelEditSubActionData() = default;
TopLevelEditSubActionData(const TopLevelEditSubActionData& aOther) = delete; TopLevelEditSubActionData(const TopLevelEditSubActionData& aOther) = delete;
}; };
@ -2617,6 +2646,8 @@ class EditorBase : public nsIEditor,
// A Tristate value. // A Tristate value.
uint8_t mSpellcheckCheckboxState; uint8_t mSpellcheckCheckboxState;
// If true, initialization was succeeded.
bool mInitSucceeded;
// If false, transactions should not change Selection even after modifying // If false, transactions should not change Selection even after modifying
// the DOM tree. // the DOM tree.
bool mAllowsTransactionsToChangeSelection; bool mAllowsTransactionsToChangeSelection;

View File

@ -10386,205 +10386,6 @@ nsresult HTMLEditor::InsertBRElementIfEmptyBlockElement(Element& aElement) {
return brElement ? NS_OK : NS_ERROR_FAILURE; return brElement ? NS_OK : NS_ERROR_FAILURE;
} }
void HTMLEditRules::DidCreateNode(Element& aNewElement) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddNodeToChangedRange(
HTMLEditorRef(), aNewElement);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddNodeToChangedRange() failed");
}
void HTMLEditRules::DidInsertNode(nsIContent& aContent) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddNodeToChangedRange(
HTMLEditorRef(), aContent);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddNodeToChangedRange() failed");
}
void HTMLEditRules::WillDeleteNode(nsINode& aChild) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddNodeToChangedRange(
HTMLEditorRef(), aChild);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddNodeToChangedRange() failed");
}
void HTMLEditRules::DidSplitNode(nsINode& aExistingRightNode,
nsINode& aNewLeftNode) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddRangeToChangedRange(
HTMLEditorRef(), EditorRawDOMPoint(&aNewLeftNode, 0),
EditorRawDOMPoint(&aExistingRightNode, 0));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddRangeToChangedRange() failed");
}
void HTMLEditRules::WillJoinNodes(nsINode& aLeftNode, nsINode& aRightNode) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
// remember split point
HTMLEditorRef().EditSubActionDataRef().mJoinedLeftNodeLength =
aLeftNode.Length();
}
void HTMLEditRules::DidJoinNodes(nsINode& aLeftNode, nsINode& aRightNode) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddPointToChangedRange(
HTMLEditorRef(),
EditorRawDOMPoint(
&aRightNode,
HTMLEditorRef().EditSubActionDataRef().mJoinedLeftNodeLength));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddPointToChangedRange() failed");
}
void HTMLEditRules::DidInsertText(nsINode& aTextNode, int32_t aOffset,
const nsAString& aString) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddRangeToChangedRange(
HTMLEditorRef(), EditorRawDOMPoint(&aTextNode, aOffset),
EditorRawDOMPoint(&aTextNode, aOffset + aString.Length()));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddRangeToChangedRange() failed");
}
void HTMLEditRules::DidDeleteText(nsINode& aTextNode, int32_t aOffset,
int32_t aLength) {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddPointToChangedRange(
HTMLEditorRef(), EditorRawDOMPoint(&aTextNode, aOffset));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddPointToChangedRange() failed");
}
void HTMLEditRules::WillDeleteSelection() {
if (!mInitialized || !mHTMLEditor) {
return; // We've been detached from editor, ignore.
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return;
}
AutoSafeEditorData setData(*this, *mHTMLEditor);
if (!HTMLEditorRef().EditSubActionDataRef().mAdjustChangedRangeFromListener) {
return; // Temporarily disabled by edit sub-action handler.
}
// XXX Looks like that this is wrong. We delete multiple selection ranges
// once, but this adds only first range into the changed range.
DebugOnly<nsresult> rv =
HTMLEditorRef().TopLevelEditSubActionDataRef().AddRangeToChangedRange(
HTMLEditorRef(), EditorBase::GetStartPoint(*SelectionRefPtr()),
EditorBase::GetStartPoint(*SelectionRefPtr()));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddRangeToChangedRange() failed");
}
nsresult HTMLEditor::RemoveAlignFromDescendants(Element& aElement, nsresult HTMLEditor::RemoveAlignFromDescendants(Element& aElement,
const nsAString& aAlignType, const nsAString& aAlignType,
EditTarget aEditTarget) { EditTarget aEditTarget) {

View File

@ -76,17 +76,6 @@ class HTMLEditRules : public TextEditRules {
MOZ_CAN_RUN_SCRIPT MOZ_CAN_RUN_SCRIPT
nsresult GetParagraphState(bool* aMixed, nsAString& outFormat); nsresult GetParagraphState(bool* aMixed, nsAString& outFormat);
void DidCreateNode(Element& aNewElement);
void DidInsertNode(nsIContent& aNode);
void WillDeleteNode(nsINode& aChild);
void DidSplitNode(nsINode& aExistingRightNode, nsINode& aNewLeftNode);
void WillJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
void DidJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
void DidInsertText(nsINode& aTextNode, int32_t aOffset,
const nsAString& aString);
void DidDeleteText(nsINode& aTextNode, int32_t aOffset, int32_t aLength);
void WillDeleteSelection();
protected: protected:
virtual ~HTMLEditRules() = default; virtual ~HTMLEditRules() = default;

View File

@ -205,6 +205,7 @@ nsresult TextEditor::EndEditorInit() {
// we're initializing the editor. // we're initializing the editor.
ClearUndoRedo(); ClearUndoRedo();
EnableUndoRedo(); EnableUndoRedo();
mInitSucceeded = true;
return NS_OK; return NS_OK;
} }
@ -718,13 +719,18 @@ nsresult TextEditor::DeleteSelectionWithTransaction(
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eDeleteSelectedContent, aDirection); *this, EditSubAction::eDeleteSelectedContent, aDirection);
if (mRules && mRules->AsHTMLEditRules()) { if (AsHTMLEditor()) {
if (!deleteNode) { if (!deleteNode) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); // XXX We may remove multiple ranges in the following. Therefore,
htmlEditRules->WillDeleteSelection(); // this must have a bug since we only add the first range into
// the changed range.
TopLevelEditSubActionDataRef().WillDeleteRange(
*this, EditorBase::GetStartPoint(*SelectionRefPtr()),
EditorBase::GetEndPoint(*SelectionRefPtr()));
} else if (!deleteCharData) { } else if (!deleteCharData) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); MOZ_ASSERT(deleteNode->IsContent());
htmlEditRules->WillDeleteNode(*deleteNode); TopLevelEditSubActionDataRef().WillDeleteContent(
*this, *deleteNode->AsContent());
} }
} }
@ -746,10 +752,10 @@ nsresult TextEditor::DeleteSelectionWithTransaction(
// Delete the specified amount // Delete the specified amount
nsresult rv = DoTransactionInternal(deleteSelectionTransaction); nsresult rv = DoTransactionInternal(deleteSelectionTransaction);
if (mRules && mRules->AsHTMLEditRules() && deleteCharData) { if (AsHTMLEditor() && deleteCharData) {
MOZ_ASSERT(deleteNode); MOZ_ASSERT(deleteNode);
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules(); TopLevelEditSubActionDataRef().DidDeleteText(*this,
htmlEditRules->DidDeleteText(*deleteNode, deleteCharOffset, 1); EditorRawDOMPoint(deleteNode));
} }
if (mTextServicesDocument && NS_SUCCEEDED(rv) && deleteNode && if (mTextServicesDocument && NS_SUCCEEDED(rv) && deleteNode &&