--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -1638,17 +1638,17 @@ IMEContentObserver::IsSafeToNotifyIME()
// If it's in reflow, we should wait to finish the reflow.
// FYI: This should be called again from Reflow() or ReflowInterruptible().
if (IsReflowLocked()) {
return false;
}
// If we're in handling an edit action, this method will be called later.
- if (mEditorBase && mEditorBase->IsInEditAction()) {
+ if (mEditorBase && mEditorBase->IsInEditSubAction()) {
return false;
}
return true;
}
void
IMEContentObserver::FlushMergeableNotifications()
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -2010,17 +2010,17 @@ nsTextEditorState::UnbindFromFrame(nsTex
// If it was, however, it should be unbounded from the same frame.
MOZ_ASSERT(aFrame == mBoundFrame, "Unbinding from the wrong frame");
NS_ENSURE_TRUE_VOID(!aFrame || aFrame == mBoundFrame);
// If the editor is modified but nsIEditorObserver::EditAction() hasn't been
// called yet, we need to notify it here because editor may be destroyed
// before EditAction() is called if selection listener causes flushing layout.
if (mTextListener && mTextEditor && mEditorInitialized &&
- mTextEditor->IsInEditAction()) {
+ mTextEditor->IsInEditSubAction()) {
mTextListener->OnEditActionHandled();
}
// We need to start storing the value outside of the editor if we're not
// going to use it anymore, so retrieve it for now.
nsAutoString value;
GetValue(value, true);
--- a/editor/libeditor/EditAction.h
+++ b/editor/libeditor/EditAction.h
@@ -7,17 +7,17 @@
#define mozilla_EditAction_h
namespace mozilla {
// This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
// spellCheckAfterEditorChange is defined to take it as a long.
// TODO: Make each name eFoo and investigate whether the numeric values
// still have some meaning.
-enum class EditAction : int32_t
+enum class EditSubAction : int32_t
{
ignore = -1,
none = 0,
undo,
redo,
insertNode,
createNode,
@@ -54,14 +54,14 @@ enum class EditAction : int32_t
setAbsolutePosition,
removeAbsolutePosition,
decreaseZIndex,
increaseZIndex,
};
} // namespace mozilla
-inline bool operator!(const mozilla::EditAction& aOp)
+inline bool operator!(const mozilla::EditSubAction& aEditSubAction)
{
- return aOp == mozilla::EditAction::none;
+ return aEditSubAction == mozilla::EditSubAction::none;
}
#endif // #ifdef mozilla_EditAction_h
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -24,20 +24,20 @@
#include "InsertTextTransaction.h" // for InsertTextTransaction
#include "JoinNodeTransaction.h" // for JoinNodeTransaction
#include "PlaceholderTransaction.h" // for PlaceholderTransaction
#include "SplitNodeTransaction.h" // for SplitNodeTransaction
#include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc.
#include "TextEditUtils.h" // for TextEditUtils
#include "mozilla/CheckedInt.h" // for CheckedInt
#include "mozilla/ComputedStyle.h" // for ComputedStyle
-#include "mozilla/EditAction.h" // for EditAction
+#include "mozilla/EditAction.h" // for EditSubAction
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
#include "mozilla/EditorSpellCheck.h" // for EditorSpellCheck
-#include "mozilla/EditorUtils.h" // for AutoRules, etc.
+#include "mozilla/EditorUtils.h" // for various helper classes.
#include "mozilla/EditTransactionBase.h" // for EditTransactionBase
#include "mozilla/FlushType.h" // for FlushType::Frames
#include "mozilla/IMEContentObserver.h" // for IMEContentObserver
#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
@@ -155,25 +155,25 @@ EditorBase::MoveNodeWithTransaction(nsIC
const EditorRawDOMPoint& aPointToInsert);
EditorBase::EditorBase()
: mPlaceholderName(nullptr)
, mModCount(0)
, mFlags(0)
, mUpdateCount(0)
, mPlaceholderBatch(0)
- , mAction(EditAction::none)
+ , mTopLevelEditSubAction(EditSubAction::none)
, mDirection(eNone)
, mDocDirtyState(-1)
, mSpellcheckCheckboxState(eTriUnset)
, mShouldTxnSetSelection(true)
, mDidPreDestroy(false)
, mDidPostCreate(false)
, mDispatchInputEvent(true)
- , mIsInEditAction(false)
+ , mIsInEditSubAction(false)
, mHidingCaret(false)
, mSpellCheckerDictionaryUpdated(true)
, mIsHTMLEditorClass(false)
{
}
EditorBase::~EditorBase()
{
@@ -253,17 +253,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorB
nsresult
EditorBase::Init(nsIDocument& aDocument,
Element* aRoot,
nsISelectionController* aSelectionController,
uint32_t aFlags,
const nsAString& aValue)
{
- MOZ_ASSERT(mAction == EditAction::none,
+ MOZ_ASSERT(mTopLevelEditSubAction == EditSubAction::none,
"Initializing during an edit action is an error");
// First only set flags, but other stuff shouldn't be initialized now.
// Don't move this call after initializing mDocument.
// SetFlags() can check whether it's called during initialization or not by
// them. Note that SetFlags() will be called by PostCreate().
#ifdef DEBUG
nsresult rv =
@@ -1351,17 +1351,19 @@ EditorBase::CreateNodeWithTransaction(
{
MOZ_ASSERT(aPointToInsert.IsSetAndValid());
// XXX We need offset at new node for mRangeUpdater. Therefore, we need
// to compute the offset now but this is expensive. So, if it's possible,
// we need to redesign mRangeUpdater as avoiding using indices.
Unused << aPointToInsert.Offset();
- AutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::createNode,
+ nsIEditor::eNext);
RefPtr<Element> newElement;
RefPtr<CreateElementTransaction> transaction =
CreateElementTransaction::Create(*this, aTagName, aPointToInsert);
nsresult rv = DoTransaction(transaction);
if (NS_WARN_IF(NS_FAILED(rv))) {
// XXX Why do we do this even when DoTransaction() returned error?
@@ -1427,17 +1429,19 @@ EditorBase::InsertNodeWithTransaction(
nsIContent& aContentToInsert,
const EditorDOMPointBase<PT, CT>& aPointToInsert)
{
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
return NS_ERROR_INVALID_ARG;
}
MOZ_ASSERT(aPointToInsert.IsSetAndValid());
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
RefPtr<InsertNodeTransaction> transaction =
InsertNodeTransaction::Create(*this, aContentToInsert, aPointToInsert);
nsresult rv = DoTransaction(transaction);
mRangeUpdater.SelAdjInsertNode(aPointToInsert);
if (mRules && mRules->AsHTMLEditRules()) {
@@ -1489,17 +1493,19 @@ EditorBase::SplitNodeWithTransaction(
{
if (NS_WARN_IF(!aStartOfRightNode.IsSet()) ||
NS_WARN_IF(!aStartOfRightNode.GetContainerAsContent())) {
aError.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
}
MOZ_ASSERT(aStartOfRightNode.IsSetAndValid());
- AutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::splitNode,
+ nsIEditor::eNext);
// XXX Unfortunately, storing offset of the split point in
// SplitNodeTransaction is necessary for now. We should fix this
// in a follow up bug.
Unused << aStartOfRightNode.Offset();
RefPtr<SplitNodeTransaction> transaction =
SplitNodeTransaction::Create(*this, aStartOfRightNode);
@@ -1554,18 +1560,19 @@ EditorBase::JoinNodes(nsINode* aLeftNode
nsresult
EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode,
nsINode& aRightNode)
{
nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode();
MOZ_ASSERT(parent);
- AutoRules beginRulesSniffing(this, EditAction::joinNode,
- nsIEditor::ePrevious);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::joinNode,
+ nsIEditor::ePrevious);
// Remember some values; later used for saved selection updating.
// Find the offset between the nodes to be joined.
int32_t offset = parent->ComputeIndexOf(&aRightNode);
// Find the number of children of the lefthand node
uint32_t oldLeftNodeLen = aLeftNode.Length();
if (mRules && mRules->AsHTMLEditRules()) {
@@ -1622,18 +1629,19 @@ EditorBase::DeleteNode(nsINode* aNode)
return NS_ERROR_INVALID_ARG;
}
return DeleteNodeWithTransaction(*aNode);
}
nsresult
EditorBase::DeleteNodeWithTransaction(nsINode& aNode)
{
- AutoRules beginRulesSniffing(this, EditAction::createNode,
- nsIEditor::ePrevious);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::createNode,
+ nsIEditor::ePrevious);
if (mRules && mRules->AsHTMLEditRules()) {
Selection* selection = GetSelection();
if (selection) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
htmlEditRules->WillDeleteNode(*selection, aNode);
} else {
NS_WARNING("Selection has gone");
@@ -2110,17 +2118,17 @@ private:
bool mIsComposing;
};
void
EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
{
switch (aNotification) {
case eNotifyEditorObserversOfEnd:
- mIsInEditAction = false;
+ mIsInEditSubAction = false;
if (mTextInputListener) {
RefPtr<TextInputListener> listener = mTextInputListener;
listener->OnEditActionHandled();
}
if (mIMEContentObserver) {
RefPtr<IMEContentObserver> observer = mIMEContentObserver;
@@ -2137,29 +2145,29 @@ EditorBase::NotifyEditorObservers(Notifi
if (!mDispatchInputEvent) {
return;
}
FireInputEvent();
break;
case eNotifyEditorObserversOfBefore:
- if (NS_WARN_IF(mIsInEditAction)) {
+ if (NS_WARN_IF(mIsInEditSubAction)) {
break;
}
- mIsInEditAction = true;
+ mIsInEditSubAction = true;
if (mIMEContentObserver) {
RefPtr<IMEContentObserver> observer = mIMEContentObserver;
observer->BeforeEditAction();
}
break;
case eNotifyEditorObserversOfCancel:
- mIsInEditAction = false;
+ mIsInEditSubAction = false;
if (mIMEContentObserver) {
RefPtr<IMEContentObserver> observer = mIMEContentObserver;
observer->CancelEditAction();
}
break;
default:
MOZ_CRASH("Handle all notifications here");
@@ -2405,39 +2413,30 @@ EditorBase::GetRootElement(Element** aRo
{
NS_ENSURE_ARG_POINTER(aRootElement);
NS_ENSURE_TRUE(mRootElement, NS_ERROR_NOT_AVAILABLE);
RefPtr<Element> rootElement = mRootElement;
rootElement.forget(aRootElement);
return NS_OK;
}
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-nsresult
-EditorBase::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
+void
+EditorBase::OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection)
{
- mAction = opID;
+ mTopLevelEditSubAction = aEditSubAction;
mDirection = aDirection;
- return NS_OK;
}
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-nsresult
-EditorBase::EndOperation()
+void
+EditorBase::OnEndHandlingTopLevelEditSubAction()
{
- mAction = EditAction::none;
+ mTopLevelEditSubAction = EditSubAction::none;
mDirection = eNone;
- return NS_OK;
}
NS_IMETHODIMP
EditorBase::CloneAttribute(const nsAString& aAttribute,
Element* aDestElement,
Element* aSourceElement)
{
NS_ENSURE_TRUE(aDestElement && aSourceElement, NS_ERROR_NULL_POINTER);
@@ -2909,18 +2908,19 @@ EditorBase::NotifyDocumentListeners(
}
nsresult
EditorBase::SetTextImpl(Selection& aSelection, const nsAString& aString,
Text& aCharData)
{
const uint32_t length = aCharData.Length();
- AutoRules beginRulesSniffing(this, EditAction::setText,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::setText,
+ nsIEditor::eNext);
// Let listeners know what's up
if (!mActionListeners.IsEmpty() && length) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
listener->WillDeleteText(&aCharData, 0, length);
}
}
@@ -2982,18 +2982,19 @@ EditorBase::DeleteTextWithTransaction(Ch
uint32_t aLength)
{
RefPtr<DeleteTextTransaction> transaction =
DeleteTextTransaction::MaybeCreate(*this, aCharData, aOffset, aLength);
if (NS_WARN_IF(!transaction)) {
return NS_ERROR_FAILURE;
}
- AutoRules beginRulesSniffing(this, EditAction::deleteText,
- nsIEditor::ePrevious);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteText,
+ nsIEditor::ePrevious);
// Let listeners know what's up
if (!mActionListeners.IsEmpty()) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
listener->WillDeleteText(&aCharData, aOffset, aLength);
}
}
@@ -4574,30 +4575,30 @@ EditorBase::HandleKeyPressEvent(WidgetKe
case NS_VK_ALT:
aKeyboardEvent->PreventDefault(); // consumed
return NS_OK;
}
return NS_OK;
}
nsresult
-EditorBase::HandleInlineSpellCheck(EditAction action,
+EditorBase::HandleInlineSpellCheck(EditSubAction aEditSubAction,
Selection& aSelection,
nsINode* previousSelectedNode,
uint32_t previousSelectedOffset,
nsINode* aStartContainer,
uint32_t aStartOffset,
nsINode* aEndContainer,
uint32_t aEndOffset)
{
if (!mInlineSpellChecker) {
return NS_OK;
}
return mInlineSpellChecker->SpellCheckAfterEditorChange(
- action, aSelection,
+ aEditSubAction, aSelection,
previousSelectedNode, previousSelectedOffset,
aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
}
already_AddRefed<nsIContent>
EditorBase::FindSelectionRoot(nsINode* aNode)
{
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -46,18 +46,18 @@ class nsIPresShell;
class nsISupports;
class nsITransaction;
class nsITransactionListener;
class nsIWidget;
class nsRange;
namespace mozilla {
class AddStyleSheetTransaction;
-class AutoRules;
class AutoSelectionRestorer;
+class AutoTopLevelEditSubActionNotifier;
class AutoTransactionsConserveSelection;
class AutoUpdateViewBatch;
class ChangeAttributeTransaction;
class CompositionTransaction;
class CreateElementTransaction;
class CSSEditUtils;
class DeleteNodeTransaction;
class DeleteTextTransaction;
@@ -77,17 +77,17 @@ class SplitNodeResult;
class SplitNodeTransaction;
class TextComposition;
class TextEditor;
class TextEditRules;
class TextInputListener;
class TextServicesDocument;
class TypeInState;
class WSRunObject;
-enum class EditAction : int32_t;
+enum class EditSubAction : int32_t;
namespace dom {
class DataTransfer;
class DragEvent;
class Element;
class EventTarget;
class Text;
} // namespace dom
@@ -581,20 +581,20 @@ public:
}
bool IsModifiable() const
{
return !IsReadonly();
}
/**
- * IsInEditAction() return true while the instance is handling an edit action.
- * Otherwise, false.
+ * IsInEditSubAction() return true while the instance is handling an edit
+ * sub-action. Otherwise, false.
*/
- bool IsInEditAction() const { return mIsInEditAction; }
+ bool IsInEditSubAction() const { return mIsInEditSubAction; }
/**
* SuppressDispatchingInputEvent() suppresses or unsuppresses dispatching
* "input" event.
*/
void SuppressDispatchingInputEvent(bool aSuppress)
{
mDispatchInputEvent = !aSuppress;
@@ -1528,17 +1528,17 @@ protected: // May be called by friends.
nsresult CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
nsINode* aEndContainer, int32_t aEndOffset,
nsRange** aRange);
static bool IsPreformatted(nsINode* aNode);
bool GetShouldTxnSetSelection();
- nsresult HandleInlineSpellCheck(EditAction action,
+ nsresult HandleInlineSpellCheck(EditSubAction aEditSubAction,
Selection& aSelection,
nsINode* previousSelectedNode,
uint32_t previousSelectedOffset,
nsINode* aStartContainer,
uint32_t aStartOffset,
nsINode* aEndContainer,
uint32_t aEndOffset);
@@ -1580,28 +1580,35 @@ protected: // May be called by friends.
/**
* HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
* with nsCaret::RemoveForceHide(). This does NOT set visibility of
* nsCaret. Therefore, this is stateless.
*/
void HideCaret(bool aHide);
protected: // Called by helper classes.
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- virtual nsresult StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection);
/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
+ * OnStartToHandleTopLevelEditSubAction() is called when
+ * mTopLevelEditSubAction is EditSubAction::none and somebody starts to
+ * handle aEditSubAction.
+ *
+ * @param aEditSubAction Top level edit sub action which will be
+ * handled soon.
+ * @param aDirection Direction of aEditSubAction.
*/
- virtual nsresult EndOperation();
+ virtual void
+ OnStartToHandleTopLevelEditSubAction(EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection);
+
+ /**
+ * OnEndHandlingTopLevelEditSubAction() is called after
+ * mTopLevelEditSubAction is handled.
+ */
+ virtual void OnEndHandlingTopLevelEditSubAction();
/**
* Routines for managing the preservation of selection across
* various editor actions.
*/
bool ArePreservingSelection();
void PreserveSelectionAcrossActions(Selection* aSel);
nsresult RestorePreservedSelection(Selection* aSel);
@@ -1878,45 +1885,45 @@ protected:
uint32_t mModCount;
// Behavior flags. See nsIPlaintextEditor.idl for the flags we use.
uint32_t mFlags;
int32_t mUpdateCount;
// Nesting count for batching.
int32_t mPlaceholderBatch;
- // The current editor action.
- EditAction mAction;
+ // The top level edit sub-action.
+ EditSubAction mTopLevelEditSubAction;
- // The current direction of editor action.
+ // The top level edit sub-action's direction.
EDirection mDirection;
// -1 = not initialized
int8_t mDocDirtyState;
// A Tristate value.
uint8_t mSpellcheckCheckboxState;
// Turn off for conservative selection adjustment by transactions.
bool mShouldTxnSetSelection;
// Whether PreDestroy has been called.
bool mDidPreDestroy;
// Whether PostCreate has been called.
bool mDidPostCreate;
bool mDispatchInputEvent;
- // True while the instance is handling an edit action.
- bool mIsInEditAction;
+ // True while the instance is handling an edit sub-action.
+ bool mIsInEditSubAction;
// Whether caret is hidden forcibly.
bool mHidingCaret;
// Whether spellchecker dictionary is initialized after focused.
bool mSpellCheckerDictionaryUpdated;
// Whether we are an HTML editor class.
bool mIsHTMLEditorClass;
friend class AutoPlaceholderBatch;
- friend class AutoRules;
friend class AutoSelectionRestorer;
+ friend class AutoTopLevelEditSubActionNotifier;
friend class AutoTransactionsConserveSelection;
friend class AutoUpdateViewBatch;
friend class CompositionTransaction;
friend class CreateElementTransaction;
friend class CSSEditUtils;
friend class DeleteTextTransaction;
friend class HTMLEditRules;
friend class HTMLEditUtils;
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -524,45 +524,51 @@ public:
/**
* Abort() cancels to restore the selection.
*/
void Abort();
};
/***************************************************************************
- * stack based helper class for StartOperation()/EndOperation() sandwich
+ * AutoTopLevelEditSubActionNotifier notifies editor of start to handle
+ * top level edit sub-action and end handling top level edit sub-action.
*/
-class MOZ_RAII AutoRules final
+class MOZ_RAII AutoTopLevelEditSubActionNotifier final
{
public:
- AutoRules(EditorBase* aEditorBase, EditAction aAction,
- nsIEditor::EDirection aDirection
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ AutoTopLevelEditSubActionNotifier(EditorBase& aEditorBase,
+ EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mEditorBase(aEditorBase)
, mDoNothing(false)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- // mAction will already be set if this is nested call
- if (mEditorBase && !mEditorBase->mAction) {
- mEditorBase->StartOperation(aAction, aDirection);
+ // mTopLevelEditSubAction will already be set if this is nested call
+ // XXX Looks like that this is not aware of unexpected nested edit action
+ // handling via selectionchange event listener or mutation event
+ // listener.
+ if (!mEditorBase.mTopLevelEditSubAction) {
+ mEditorBase.OnStartToHandleTopLevelEditSubAction(aEditSubAction,
+ aDirection);
} else {
mDoNothing = true; // nested calls will end up here
}
}
- ~AutoRules()
+ ~AutoTopLevelEditSubActionNotifier()
{
- if (mEditorBase && !mDoNothing) {
- mEditorBase->EndOperation();
+ if (!mDoNothing) {
+ mEditorBase.OnEndHandlingTopLevelEditSubAction();
}
}
protected:
- EditorBase* mEditorBase;
+ EditorBase& mEditorBase;
bool mDoNothing;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/***************************************************************************
* stack based helper class for turning off active selection adjustment
* by low level transactions
*/
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -45,37 +45,41 @@
namespace mozilla {
using namespace dom;
nsresult
HTMLEditor::SetSelectionToAbsoluteOrStatic(bool aEnabled)
{
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this,
- aEnabled ? EditAction::setAbsolutePosition :
- EditAction::removeAbsolutePosition,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this,
+ aEnabled ?
+ EditSubAction::setAbsolutePosition :
+ EditSubAction::removeAbsolutePosition,
+ nsIEditor::eNext);
// the line below does not match the code; should it be removed?
// Find out if the selection is collapsed:
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(aEnabled ? EditAction::setAbsolutePosition :
- EditAction::removeAbsolutePosition);
+ EditSubActionInfo subActionInfo(
+ aEnabled ? EditSubAction::setAbsolutePosition :
+ EditSubAction::removeAbsolutePosition);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (NS_FAILED(rv) || cancel) {
return rv;
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
already_AddRefed<Element>
HTMLEditor::GetAbsolutelyPositionedSelectionContainer()
{
nsAutoString positionStr;
RefPtr<Element> element = GetSelectionContainer();
@@ -134,36 +138,39 @@ HTMLEditor::SetZIndex(Element& aElement,
mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::z_index, zIndexStr);
}
nsresult
HTMLEditor::AddZIndex(int32_t aChange)
{
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this,
- (aChange < 0) ? EditAction::decreaseZIndex :
- EditAction::increaseZIndex,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this,
+ aChange < 0 ?
+ EditSubAction::decreaseZIndex :
+ EditSubAction::increaseZIndex,
+ nsIEditor::eNext);
// brade: can we get rid of this comment?
// Find out if the selection is collapsed:
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(aChange < 0 ? EditAction::decreaseZIndex :
- EditAction::increaseZIndex);
+ EditSubActionInfo subActionInfo(aChange < 0 ? EditSubAction::decreaseZIndex :
+ EditSubAction::increaseZIndex);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
int32_t
HTMLEditor::GetZIndex(Element& aElement)
{
nsAutoString zIndexStr;
nsresult rv =
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -59,18 +59,16 @@
#ifdef SetProp
#undef SetProp
#endif
class nsISupports;
namespace mozilla {
-class RulesInfo;
-
using namespace dom;
//const static char* kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
//const static char* kMOZEditorBogusNodeValue="TRUE";
enum
{
kLonely = 0,
@@ -79,29 +77,29 @@ enum
kBothSibs = 3
};
/********************************************************
* first some helpful functors we will use
********************************************************/
static bool
-IsStyleCachePreservingAction(EditAction action)
-{
- return action == EditAction::deleteSelection ||
- action == EditAction::insertBreak ||
- action == EditAction::makeList ||
- action == EditAction::indent ||
- action == EditAction::outdent ||
- action == EditAction::align ||
- action == EditAction::makeBasicBlock ||
- action == EditAction::removeList ||
- action == EditAction::makeDefListItem ||
- action == EditAction::insertElement ||
- action == EditAction::insertQuotation;
+IsStyleCachePreservingSubAction(EditSubAction aEditSubAction)
+{
+ return aEditSubAction == EditSubAction::deleteSelection ||
+ aEditSubAction == EditSubAction::insertBreak ||
+ aEditSubAction == EditSubAction::makeList ||
+ aEditSubAction == EditSubAction::indent ||
+ aEditSubAction == EditSubAction::outdent ||
+ aEditSubAction == EditSubAction::align ||
+ aEditSubAction == EditSubAction::makeBasicBlock ||
+ aEditSubAction == EditSubAction::removeList ||
+ aEditSubAction == EditSubAction::makeDefListItem ||
+ aEditSubAction == EditSubAction::insertElement ||
+ aEditSubAction == EditSubAction::insertQuotation;
}
static nsAtom&
ParagraphSeparatorElement(ParagraphSeparator separator)
{
switch (separator) {
default:
MOZ_FALLTHROUGH_ASSERT("Unexpected paragraph separator!");
@@ -299,31 +297,31 @@ HTMLEditRules::Init(TextEditor* aTextEdi
nsresult rv = InsertBRElementToEmptyListItemsAndTableCellsInChangedRange();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to insert <br> elements to empty list items and table cells");
}
- StartToListenToEditActions();
+ StartToListenToEditSubActions();
return NS_OK;
}
nsresult
HTMLEditRules::DetachEditor()
{
- EndListeningToEditActions();
+ EndListeningToEditSubActions();
mHTMLEditor = nullptr;
return TextEditRules::DetachEditor();
}
nsresult
-HTMLEditRules::BeforeEdit(EditAction aAction,
+HTMLEditRules::BeforeEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection)
{
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (mLockRulesSniffing) {
return NS_OK;
@@ -367,20 +365,20 @@ HTMLEditRules::BeforeEdit(EditAction aAc
mDocChangeRange->Reset();
}
if (mUtilRange) {
// Ditto for mUtilRange.
mUtilRange->Reset();
}
// Remember current inline styles for deletion and normal insertion ops
- if (aAction == EditAction::insertText ||
- aAction == EditAction::insertIMEText ||
- aAction == EditAction::deleteSelection ||
- IsStyleCachePreservingAction(aAction)) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::deleteSelection ||
+ IsStyleCachePreservingSubAction(aEditSubAction)) {
nsCOMPtr<nsINode> selNode =
aDirection == nsIEditor::eNext ? selEndNode : selStartNode;
nsresult rv = CacheInlineStyles(selNode);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
@@ -395,24 +393,24 @@ HTMLEditRules::BeforeEdit(EditAction aAc
}
// Check that selection is in subtree defined by body node
nsresult rv = ConfirmSelectionInBody();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
// Let rules remember the top level action
- mTheAction = aAction;
+ mTopLevelEditSubAction = aEditSubAction;
}
return NS_OK;
}
nsresult
-HTMLEditRules::AfterEdit(EditAction aAction,
+HTMLEditRules::AfterEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection)
{
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (mLockRulesSniffing) {
return NS_OK;
@@ -427,17 +425,17 @@ HTMLEditRules::AfterEdit(EditAction aAct
Selection* selection = mHTMLEditor->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
// Do all the tricky stuff
- rv = AfterEditInner(aAction, aDirection);
+ rv = AfterEditInner(aEditSubAction, aDirection);
// Perhaps, we need to do the following jobs even if the editor has been
// destroyed since they adjust some states of HTML document but don't
// modify the DOM tree nor Selection.
// Free up selectionState range item
HTMLEditorRef().mRangeUpdater.DropRangeItem(mRangeItem);
// Reset the contenteditable count to its previous value
@@ -455,27 +453,27 @@ HTMLEditRules::AfterEdit(EditAction aAct
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
-HTMLEditRules::AfterEditInner(EditAction aAction,
+HTMLEditRules::AfterEditInner(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection)
{
MOZ_ASSERT(IsEditorDataAvailable());
nsresult rv = ConfirmSelectionInBody();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to normalize Selection");
- if (aAction == EditAction::ignore) {
+ if (aEditSubAction == EditSubAction::ignore) {
return NS_OK;
}
nsCOMPtr<nsINode> rangeStartContainer, rangeEndContainer;
uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
// do we have a real range to act on?
bool bDamagedRange = false;
if (mDocChangeRange) {
@@ -483,70 +481,71 @@ HTMLEditRules::AfterEditInner(EditAction
rangeEndContainer = mDocChangeRange->GetEndContainer();
rangeStartOffset = mDocChangeRange->StartOffset();
rangeEndOffset = mDocChangeRange->EndOffset();
if (rangeStartContainer && rangeEndContainer) {
bDamagedRange = true;
}
}
- if (bDamagedRange && !((aAction == EditAction::undo) ||
- (aAction == EditAction::redo))) {
+ if (bDamagedRange && !((aEditSubAction == EditSubAction::undo) ||
+ (aEditSubAction == EditSubAction::redo))) {
// don't let any txns in here move the selection around behind our back.
// Note that this won't prevent explicit selection setting from working.
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
// expand the "changed doc range" as needed
- PromoteRange(*mDocChangeRange, aAction);
+ PromoteRange(*mDocChangeRange, aEditSubAction);
// if we did a ranged deletion or handling backspace key, make sure we have
// a place to put caret.
// Note we only want to do this if the overall operation was deletion,
- // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc.
- // That's why this is here rather than DidDeleteSelection().
- if (aAction == EditAction::deleteSelection && mDidRangedDelete) {
+ // not if deletion was done along the way for EditSubAction::loadHTML,
+ // EditSubAction::insertText, etc. That's why this is here rather than
+ // DidDeleteSelection().
+ if (aEditSubAction == EditSubAction::deleteSelection && mDidRangedDelete) {
nsresult rv = InsertBRIfNeeded();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// add in any needed <br>s, and remove any unneeded ones.
nsresult rv = InsertBRElementToEmptyListItemsAndTableCellsInChangedRange();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to insert <br> elements to empty list items and table cells");
// merge any adjacent text nodes
- if (aAction != EditAction::insertText &&
- aAction != EditAction::insertIMEText) {
+ if (aEditSubAction != EditSubAction::insertText &&
+ aEditSubAction != EditSubAction::insertIMEText) {
nsresult rv = HTMLEditorRef().CollapseAdjacentTextNodes(mDocChangeRange);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// clean up any empty nodes in the selection
rv = RemoveEmptyNodesInChangedRange();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// attempt to transform any unneeded nbsp's into spaces after doing various operations
- if (aAction == EditAction::insertText ||
- aAction == EditAction::insertIMEText ||
- aAction == EditAction::deleteSelection ||
- aAction == EditAction::insertBreak ||
- aAction == EditAction::htmlPaste ||
- aAction == EditAction::loadHTML) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::deleteSelection ||
+ aEditSubAction == EditSubAction::insertBreak ||
+ aEditSubAction == EditSubAction::htmlPaste ||
+ aEditSubAction == EditSubAction::loadHTML) {
rv = AdjustWhitespace();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// also do this for original selection endpoints.
NS_ENSURE_STATE(mRangeItem->mStartContainer);
NS_ENSURE_STATE(mRangeItem->mEndContainer);
@@ -567,43 +566,43 @@ HTMLEditRules::AfterEditInner(EditAction
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to pin selection to the new block");
mNewBlock = nullptr;
}
// adjust selection for insert text, html paste, and delete actions
- if (aAction == EditAction::insertText ||
- aAction == EditAction::insertIMEText ||
- aAction == EditAction::deleteSelection ||
- aAction == EditAction::insertBreak ||
- aAction == EditAction::htmlPaste ||
- aAction == EditAction::loadHTML) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::deleteSelection ||
+ aEditSubAction == EditSubAction::insertBreak ||
+ aEditSubAction == EditSubAction::htmlPaste ||
+ aEditSubAction == EditSubAction::loadHTML) {
rv = AdjustSelection(aDirection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// check for any styles which were removed inappropriately
- if (aAction == EditAction::insertText ||
- aAction == EditAction::insertIMEText ||
- aAction == EditAction::deleteSelection ||
- IsStyleCachePreservingAction(aAction)) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::deleteSelection ||
+ IsStyleCachePreservingSubAction(aEditSubAction)) {
HTMLEditorRef().mTypeInState->UpdateSelState(&SelectionRef());
rv = ReapplyCachedStyles();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
ClearCachedStyles();
}
}
- rv = HTMLEditorRef().HandleInlineSpellCheck(aAction, SelectionRef(),
+ rv = HTMLEditorRef().HandleInlineSpellCheck(aEditSubAction, SelectionRef(),
mRangeItem->mStartContainer,
mRangeItem->mStartOffset,
rangeStartContainer,
rangeStartOffset,
rangeEndContainer,
rangeEndOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -620,38 +619,38 @@ HTMLEditRules::AfterEditInner(EditAction
CheckInterlinePosition();
}
return NS_OK;
}
nsresult
HTMLEditRules::WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
bool* aCancel,
bool* aHandled)
{
- if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aInfo)) {
+ if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
MOZ_ASSERT(aCancel);
MOZ_ASSERT(aHandled);
*aCancel = false;
*aHandled = false;
// Deal with actions for which we don't need to check whether the selection is
// editable.
- if (aInfo->action == EditAction::outputText ||
- aInfo->action == EditAction::undo ||
- aInfo->action == EditAction::redo) {
+ if (aInfo.mEditSubAction == EditSubAction::outputText ||
+ aInfo.mEditSubAction == EditSubAction::undo ||
+ aInfo.mEditSubAction == EditSubAction::redo) {
return TextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
}
AutoSafeEditorData setData(*this, *mHTMLEditor, *aSelection);
// Nothing to do if there's no selection to act on
if (NS_WARN_IF(!SelectionRef().RangeCount())) {
return NS_OK;
@@ -675,105 +674,105 @@ HTMLEditRules::WillDoAction(Selection* a
NS_ENSURE_STATE(mHTMLEditor);
if (!HTMLEditorRef().IsModifiableNode(range->GetCommonAncestor())) {
*aCancel = true;
return NS_OK;
}
}
- switch (aInfo->action) {
- case EditAction::insertText:
- case EditAction::insertIMEText:
+ switch (aInfo.mEditSubAction) {
+ case EditSubAction::insertText:
+ case EditSubAction::insertIMEText:
UndefineCaretBidiLevel();
- return WillInsertText(aInfo->action, aCancel, aHandled,
- aInfo->inString, aInfo->outString,
- aInfo->maxLength);
- case EditAction::loadHTML:
+ return WillInsertText(aInfo.mEditSubAction, aCancel, aHandled,
+ aInfo.inString, aInfo.outString,
+ aInfo.maxLength);
+ case EditSubAction::loadHTML:
return WillLoadHTML();
- case EditAction::insertBreak:
+ case EditSubAction::insertBreak:
UndefineCaretBidiLevel();
return WillInsertBreak(aCancel, aHandled);
- case EditAction::deleteSelection:
- return WillDeleteSelection(aInfo->collapsedAction, aInfo->stripWrappers,
+ case EditSubAction::deleteSelection:
+ return WillDeleteSelection(aInfo.collapsedAction, aInfo.stripWrappers,
aCancel, aHandled);
- case EditAction::makeList:
- return WillMakeList(aInfo->blockType, aInfo->entireList,
- aInfo->bulletType, aCancel, aHandled);
- case EditAction::indent:
+ case EditSubAction::makeList:
+ return WillMakeList(aInfo.blockType, aInfo.entireList,
+ aInfo.bulletType, aCancel, aHandled);
+ case EditSubAction::indent:
return WillIndent(aCancel, aHandled);
- case EditAction::outdent:
+ case EditSubAction::outdent:
return WillOutdent(aCancel, aHandled);
- case EditAction::setAbsolutePosition:
+ case EditSubAction::setAbsolutePosition:
return WillAbsolutePosition(aCancel, aHandled);
- case EditAction::removeAbsolutePosition:
+ case EditSubAction::removeAbsolutePosition:
return WillRemoveAbsolutePosition(aCancel, aHandled);
- case EditAction::align:
- return WillAlign(*aInfo->alignType, aCancel, aHandled);
- case EditAction::makeBasicBlock:
- return WillMakeBasicBlock(*aInfo->blockType, aCancel, aHandled);
- case EditAction::removeList: {
+ case EditSubAction::align:
+ return WillAlign(*aInfo.alignType, aCancel, aHandled);
+ case EditSubAction::makeBasicBlock:
+ return WillMakeBasicBlock(*aInfo.blockType, aCancel, aHandled);
+ case EditSubAction::removeList: {
nsresult rv = WillRemoveList(aCancel, aHandled);
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED) ||
NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
- case EditAction::makeDefListItem:
- return WillMakeDefListItem(aInfo->blockType,
- aInfo->entireList, aCancel, aHandled);
- case EditAction::insertElement: {
+ case EditSubAction::makeDefListItem:
+ return WillMakeDefListItem(aInfo.blockType,
+ aInfo.entireList, aCancel, aHandled);
+ case EditSubAction::insertElement: {
nsresult rv = WillInsert(aCancel);
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WillInsert() failed");
return NS_OK;
}
- case EditAction::decreaseZIndex:
+ case EditSubAction::decreaseZIndex:
return WillRelativeChangeZIndex(-1, aCancel, aHandled);
- case EditAction::increaseZIndex:
+ case EditSubAction::increaseZIndex:
return WillRelativeChangeZIndex(1, aCancel, aHandled);
default:
return TextEditRules::WillDoAction(&SelectionRef(), aInfo,
aCancel, aHandled);
}
}
nsresult
HTMLEditRules::DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
nsresult aResult)
{
- if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aInfo)) {
+ if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
AutoSafeEditorData setData(*this, *mHTMLEditor, *aSelection);
- switch (aInfo->action) {
- case EditAction::insertText:
- case EditAction::insertBreak:
- case EditAction::insertIMEText:
+ switch (aInfo.mEditSubAction) {
+ case EditSubAction::insertText:
+ case EditSubAction::insertBreak:
+ case EditSubAction::insertIMEText:
return NS_OK;
- case EditAction::deleteSelection:
+ case EditSubAction::deleteSelection:
return DidDeleteSelection();
- case EditAction::makeBasicBlock:
- case EditAction::indent:
- case EditAction::outdent:
- case EditAction::align:
+ case EditSubAction::makeBasicBlock:
+ case EditSubAction::indent:
+ case EditSubAction::outdent:
+ case EditSubAction::align:
return DidMakeBasicBlock();
- case EditAction::setAbsolutePosition: {
+ case EditSubAction::setAbsolutePosition: {
nsresult rv = DidMakeBasicBlock();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return DidAbsolutePosition();
}
default:
return TextEditRules::DidDoAction(aSelection, aInfo, aResult);
@@ -974,22 +973,22 @@ HTMLEditRules::GetAlignment(bool* aMixed
atStartOfSelection.Offset() == static_cast<uint32_t>(rootOffset)) {
// If we have selected the body, let's look at the first editable node
nodeToExamine = HTMLEditorRef().GetNextEditableNode(atStartOfSelection);
if (NS_WARN_IF(!nodeToExamine)) {
return NS_ERROR_FAILURE;
}
} else {
nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(arrayOfRanges, EditAction::align);
+ GetPromotedRanges(arrayOfRanges, EditSubAction::align);
// Use these ranges to construct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
- EditAction::align, TouchContent::no);
+ EditSubAction::align, TouchContent::no);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nodeToExamine = arrayOfNodes.SafeElementAt(0);
if (NS_WARN_IF(!nodeToExamine)) {
return NS_ERROR_FAILURE;
}
}
@@ -1122,17 +1121,18 @@ HTMLEditRules::GetIndentState(bool* aCan
return NS_ERROR_FAILURE;
}
AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
// contruct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsresult rv =
- GetNodesFromSelection(EditAction::indent, arrayOfNodes, TouchContent::no);
+ GetNodesFromSelection(EditSubAction::indent, arrayOfNodes,
+ TouchContent::no);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// examine nodes in selection for blockquotes or list elements;
// these we can outdent. Note that we return true for canOutdent
// if *any* of the selection is outdentable, rather than all of it.
bool useCSS = HTMLEditorRef().IsCSSEnabled();
@@ -1409,34 +1409,34 @@ HTMLEditRules::WillInsert(bool* aCancel)
}
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
}
if (mDidDeleteSelection &&
- (mTheAction == EditAction::insertText ||
- mTheAction == EditAction::insertIMEText ||
- mTheAction == EditAction::deleteSelection)) {
+ (mTopLevelEditSubAction == EditSubAction::insertText ||
+ mTopLevelEditSubAction == EditSubAction::insertIMEText ||
+ mTopLevelEditSubAction == EditSubAction::deleteSelection)) {
nsresult rv = ReapplyCachedStyles();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// For most actions we want to clear the cached styles, but there are
// exceptions
- if (!IsStyleCachePreservingAction(mTheAction)) {
+ if (!IsStyleCachePreservingSubAction(mTopLevelEditSubAction)) {
ClearCachedStyles();
}
return NS_OK;
}
nsresult
-HTMLEditRules::WillInsertText(EditAction aAction,
+HTMLEditRules::WillInsertText(EditSubAction aEditSubAction,
bool* aCancel,
bool* aHandled,
const nsAString* inString,
nsAString* outString,
int32_t aMaxLength)
{
MOZ_ASSERT(IsEditorDataAvailable());
@@ -1494,17 +1494,17 @@ HTMLEditRules::WillInsertText(EditAction
// dont put text in places that can't have it
if (!EditorBase::IsTextNode(pointToInsert.GetContainer()) &&
!HTMLEditorRef().CanContainTag(*pointToInsert.GetContainer(),
*nsGkAtoms::textTagName)) {
return NS_ERROR_FAILURE;
}
- if (aAction == EditAction::insertIMEText) {
+ if (aEditSubAction == EditSubAction::insertIMEText) {
// Right now the WSRunObject code bails on empty strings, but IME needs
// the InsertTextWithTransaction() call to still happen since empty strings
// are meaningful there.
// If there is one or more IME selections, its minimum offset should be
// the insertion point.
int32_t IMESelectionOffset =
HTMLEditorRef().GetIMESelectionStartOffsetIn(
pointToInsert.GetContainer());
@@ -1530,17 +1530,17 @@ HTMLEditRules::WillInsertText(EditAction
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
- // aAction == kInsertText
+ // aEditSubAction == kInsertText
// find where we are
EditorDOMPoint currentPoint(pointToInsert);
// is our text going to be PREformatted?
// We remember this so that we know how to handle tabs.
bool isPRE = EditorBase::IsPreformatted(pointToInsert.GetContainer());
@@ -3796,17 +3796,17 @@ HTMLEditRules::MoveBlock(Element& aLeftB
int32_t aLeftOffset,
int32_t aRightOffset)
{
MOZ_ASSERT(IsEditorDataAvailable());
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
// GetNodesFromPoint is the workhorse that figures out what we wnat to move.
nsresult rv = GetNodesFromPoint(EditorDOMPoint(&aRightBlock, aRightOffset),
- EditAction::makeList, arrayOfNodes,
+ EditSubAction::makeList, arrayOfNodes,
TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return EditActionIgnored(rv);
}
EditActionResult ret(NS_OK);
for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
// get the node to act on
@@ -4500,17 +4500,17 @@ HTMLEditRules::WillRemoveList(bool* aCan
nsresult rv = NormalizeSelection();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(arrayOfRanges, EditAction::makeList);
+ GetPromotedRanges(arrayOfRanges, EditSubAction::makeList);
// use these ranges to contruct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
rv = GetListActionNodes(arrayOfNodes, EntireList::no, TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -4606,17 +4606,17 @@ HTMLEditRules::MakeBasicBlock(nsAtom& bl
return rv;
}
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
// Contruct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetNodesFromSelection(EditAction::makeBasicBlock, arrayOfNodes,
+ rv = GetNodesFromSelection(EditSubAction::makeBasicBlock, arrayOfNodes,
TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// If nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes)) {
nsRange* firstRange = SelectionRef().GetRangeAt(0);
@@ -4882,17 +4882,17 @@ HTMLEditRules::IndentAroundSelectionWith
if (liNode) {
arrayOfNodes.AppendElement(*liNode);
} else {
// convert the selection ranges into "promoted" selection ranges:
// this basically just expands the range to include the immediate
// block parent, and then further expands to include any ancestors
// whose children are all in the range
nsresult rv =
- GetNodesFromSelection(EditAction::indent, arrayOfNodes,
+ GetNodesFromSelection(EditSubAction::indent, arrayOfNodes,
TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// if nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes)) {
@@ -5165,22 +5165,22 @@ HTMLEditRules::IndentAroundSelectionWith
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
// convert the selection ranges into "promoted" selection ranges:
// this basically just expands the range to include the immediate
// block parent, and then further expands to include any ancestors
// whose children are all in the range
nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(arrayOfRanges, EditAction::indent);
+ GetPromotedRanges(arrayOfRanges, EditSubAction::indent);
// use these ranges to contruct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsresult rv =
- GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent,
+ GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditSubAction::indent,
TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// if nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes)) {
nsRange* firstRange = SelectionRef().GetRangeAt(0);
@@ -5547,17 +5547,18 @@ HTMLEditRules::OutdentAroundSelection()
bool useCSS = HTMLEditorRef().IsCSSEnabled();
// Convert the selection ranges into "promoted" selection ranges: this
// basically just expands the range to include the immediate block parent,
// and then further expands to include any ancestors whose children are all
// in the range
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsresult rv =
- GetNodesFromSelection(EditAction::outdent, arrayOfNodes, TouchContent::yes);
+ GetNodesFromSelection(EditSubAction::outdent, arrayOfNodes,
+ TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return SplitRangeOffFromNodeResult(rv);
}
// Okay, now go through all the nodes and remove a level of blockquoting,
// or whatever is appropriate. Wohoo!
nsCOMPtr<nsIContent> leftContentOfLastOutdented;
@@ -6185,17 +6186,17 @@ HTMLEditRules::AlignContentsAtSelection(
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
// Convert the selection ranges into "promoted" selection ranges: This
// basically just expands the range to include the immediate block parent,
// and then further expands to include any ancestors whose children are all
// in the range
nsTArray<OwningNonNull<nsINode>> nodeArray;
nsresult rv =
- GetNodesFromSelection(EditAction::align, nodeArray, TouchContent::yes);
+ GetNodesFromSelection(EditSubAction::align, nodeArray, TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// If we don't have any nodes, or we have only a single br, then we are
// creating an empty alignment div. We have to do some different things for
// these.
bool emptyDiv = nodeArray.IsEmpty();
@@ -7118,26 +7119,26 @@ HTMLEditRules::NormalizeSelection()
"Failed to extend selection");
return NS_OK;
}
EditorDOMPoint
HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere,
nsINode& aNode,
int32_t aOffset,
- EditAction actionID)
+ EditSubAction aEditSubAction)
{
MOZ_ASSERT(IsEditorDataAvailable());
// we do one thing for text actions, something else entirely for other
// actions
- if (actionID == EditAction::insertText ||
- actionID == EditAction::insertIMEText ||
- actionID == EditAction::insertBreak ||
- actionID == EditAction::deleteText) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::insertBreak ||
+ aEditSubAction == EditSubAction::deleteText) {
bool isSpace, isNBSP;
nsCOMPtr<nsIContent> content =
aNode.IsContent() ? aNode.AsContent() : nullptr;
nsCOMPtr<nsIContent> temp;
int32_t newOffset = aOffset;
// for text actions, we want to look backwards (or forwards, as
// appropriate) for additional whitespace or nbsp's. We may have to act on
// these later even though they are outside of the initial selection. Even
@@ -7199,29 +7200,29 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
while (!nearNode &&
!point.IsContainerHTMLElement(nsGkAtoms::body) &&
point.GetContainer()->GetParentNode()) {
// some cutoffs are here: we don't need to also include them in the
// aWhere == kEnd case. as long as they are in one or the other it will
// work. special case for outdent: don't keep looking up if we have
// found a blockquote element to act on
- if (actionID == EditAction::outdent &&
+ if (aEditSubAction == EditSubAction::outdent &&
point.IsContainerHTMLElement(nsGkAtoms::blockquote)) {
break;
}
// Don't walk past the editable section. Note that we need to check
// before walking up to a parent because we need to return the parent
// object, so the parent itself might not be in the editable area, but
// it's OK if we're not performing a block-level action.
- bool blockLevelAction = actionID == EditAction::indent ||
- actionID == EditAction::outdent ||
- actionID == EditAction::align ||
- actionID == EditAction::makeBasicBlock;
+ bool blockLevelAction = aEditSubAction == EditSubAction::indent ||
+ aEditSubAction == EditSubAction::outdent ||
+ aEditSubAction == EditSubAction::align ||
+ aEditSubAction == EditSubAction::makeBasicBlock;
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
point.GetContainer()->GetParentNode()) &&
(blockLevelAction ||
!HTMLEditorRef().IsDescendantOfEditorRoot(point.GetContainer()))) {
break;
}
point.Set(point.GetContainer());
@@ -7245,19 +7246,19 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
}
// look ahead through any further inline nodes that aren't across a <br> from
// us, and that are enclosed in the same block.
// XXX Currently, we stop block-extending when finding visible <br> element.
// This might be different from "block-extend" of execCommand spec.
// However, the spec is really unclear.
// XXX Probably, scanning only editable nodes is wrong for
- // EditAction::makeBasicBlock because it might be better to wrap existing
- // inline elements even if it's non-editable. For example, following
- // examples with insertParagraph causes different result:
+ // EditSubAction::makeBasicBlock because it might be better to wrap
+ // existing inline elements even if it's non-editable. For example,
+ // following examples with insertParagraph causes different result:
// * <div contenteditable>foo[]<b contenteditable="false">bar</b></div>
// * <div contenteditable>foo[]<b>bar</b></div>
// * <div contenteditable>foo[]<b contenteditable="false">bar</b>baz</div>
// Only in the first case, after the caret position isn't wrapped with
// new <div> element.
nsCOMPtr<nsIContent> nextNode =
HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
@@ -7310,41 +7311,41 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
}
nearNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
}
return point;
}
void
HTMLEditRules::GetPromotedRanges(nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
- EditAction inOperationType)
+ EditSubAction aEditSubAction)
{
MOZ_ASSERT(IsEditorDataAvailable());
uint32_t rangeCount = SelectionRef().RangeCount();
for (uint32_t i = 0; i < rangeCount; i++) {
RefPtr<nsRange> selectionRange = SelectionRef().GetRangeAt(i);
MOZ_ASSERT(selectionRange);
// Clone range so we don't muck with actual selection ranges
RefPtr<nsRange> opRange = selectionRange->CloneRange();
// Make a new adjusted range to represent the appropriate block content.
// The basic idea is to push out the range endpoints to truly enclose the
// blocks that we will affect. This call alters opRange.
- PromoteRange(*opRange, inOperationType);
+ PromoteRange(*opRange, aEditSubAction);
// Stuff new opRange into array
outArrayOfRanges.AppendElement(opRange);
}
}
void
HTMLEditRules::PromoteRange(nsRange& aRange,
- EditAction aOperationType)
+ EditSubAction aEditSubAction)
{
MOZ_ASSERT(IsEditorDataAvailable());
MOZ_ASSERT(!aRange.IsInSelection());
if (!aRange.IsPositioned()) {
return;
}
@@ -7373,20 +7374,20 @@ HTMLEditRules::PromoteRange(nsRange& aRa
startNode = block;
endNode = block;
startOffset = 0;
endOffset = block->Length();
}
}
}
- if (aOperationType == EditAction::insertText ||
- aOperationType == EditAction::insertIMEText ||
- aOperationType == EditAction::insertBreak ||
- aOperationType == EditAction::deleteText) {
+ if (aEditSubAction == EditSubAction::insertText ||
+ aEditSubAction == EditSubAction::insertIMEText ||
+ aEditSubAction == EditSubAction::insertBreak ||
+ aEditSubAction == EditSubAction::deleteText) {
if (!startNode->IsContent() ||
!endNode->IsContent()) {
// GetPromotedPoint cannot promote node when action type is text
// operation and selected node isn't content node.
return;
}
}
@@ -7394,23 +7395,23 @@ HTMLEditRules::PromoteRange(nsRange& aRa
// This is tricky. The basic idea is to push out the range endpoints to
// truly enclose the blocks that we will affect.
// Make sure that the new range ends up to be in the editable section.
// XXX Looks like that this check wastes the time. Perhaps, we should
// implement a method which checks both two DOM points in the editor
// root.
EditorDOMPoint startPoint =
- GetPromotedPoint(kStart, *startNode, startOffset, aOperationType);
+ GetPromotedPoint(kStart, *startNode, startOffset, aEditSubAction);
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
return;
}
EditorDOMPoint endPoint =
- GetPromotedPoint(kEnd, *endNode, endOffset, aOperationType);
+ GetPromotedPoint(kEnd, *endNode, endOffset, aEditSubAction);
EditorRawDOMPoint lastRawPoint(endPoint);
lastRawPoint.RewindOffset();
if (!HTMLEditorRef().IsDescendantOfEditorRoot(
EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
return;
}
DebugOnly<nsresult> rv = aRange.SetStartAndEnd(startPoint, endPoint);
@@ -7434,17 +7435,17 @@ public:
private:
nsTArray<OwningNonNull<nsINode>>& mArray;
};
nsresult
HTMLEditRules::GetNodesForOperation(
nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EditAction aOperationType,
+ EditSubAction aEditSubAction,
TouchContent aTouchContent)
{
MOZ_ASSERT(IsEditorDataAvailable());
if (aTouchContent == TouchContent::yes) {
// Split text nodes. This is necessary, since GetPromotedPoint() may return a
// range ending in a text node in case where part of a pre-formatted
// elements needs to be moved.
@@ -7525,17 +7526,17 @@ HTMLEditRules::GetNodesForOperation(
nsTArray<OwningNonNull<nsINode>> nodes;
iter.AppendList(UniqueFunctor(aOutArrayOfNodes), nodes);
aOutArrayOfNodes.AppendElements(nodes);
}
}
// Certain operations should not act on li's and td's, but rather inside
// them. Alter the list as needed.
- if (aOperationType == EditAction::makeBasicBlock) {
+ if (aEditSubAction == EditSubAction::makeBasicBlock) {
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
if (HTMLEditUtils::IsListItem(node)) {
int32_t j = i;
aOutArrayOfNodes.RemoveElementAt(i);
GetInnerContent(*node, aOutArrayOfNodes, &j);
}
}
@@ -7546,50 +7547,50 @@ HTMLEditRules::GetNodesForOperation(
if (!HTMLEditorRef().IsVisibleTextNode(*text)) {
aOutArrayOfNodes.RemoveElementAt(i);
}
}
}
}
// Indent/outdent already do something special for list items, but we still
// need to make sure we don't act on table elements
- else if (aOperationType == EditAction::outdent ||
- aOperationType == EditAction::indent ||
- aOperationType == EditAction::setAbsolutePosition) {
+ else if (aEditSubAction == EditSubAction::outdent ||
+ aEditSubAction == EditSubAction::indent ||
+ aEditSubAction == EditSubAction::setAbsolutePosition) {
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
if (HTMLEditUtils::IsTableElementButNotTable(node)) {
int32_t j = i;
aOutArrayOfNodes.RemoveElementAt(i);
GetInnerContent(*node, aOutArrayOfNodes, &j);
}
}
}
// Outdent should look inside of divs.
- if (aOperationType == EditAction::outdent &&
+ if (aEditSubAction == EditSubAction::outdent &&
!HTMLEditorRef().IsCSSEnabled()) {
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
if (node->IsHTMLElement(nsGkAtoms::div)) {
int32_t j = i;
aOutArrayOfNodes.RemoveElementAt(i);
GetInnerContent(*node, aOutArrayOfNodes, &j, Lists::no, Tables::no);
}
}
}
// Post-process the list to break up inline containers that contain br's, but
// only for operations that might care, like making lists or paragraphs
- if (aOperationType == EditAction::makeBasicBlock ||
- aOperationType == EditAction::makeList ||
- aOperationType == EditAction::align ||
- aOperationType == EditAction::setAbsolutePosition ||
- aOperationType == EditAction::indent ||
- aOperationType == EditAction::outdent) {
+ if (aEditSubAction == EditSubAction::makeBasicBlock ||
+ aEditSubAction == EditSubAction::makeList ||
+ aEditSubAction == EditSubAction::align ||
+ aEditSubAction == EditSubAction::setAbsolutePosition ||
+ aEditSubAction == EditSubAction::indent ||
+ aEditSubAction == EditSubAction::outdent) {
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
// XXX Why do we run this loop even when aTouchContent is "no"?
if (aTouchContent == TouchContent::yes && IsInlineNode(node) &&
HTMLEditorRef().IsContainer(node) && !EditorBase::IsTextNode(node)) {
nsTArray<OwningNonNull<nsINode>> arrayOfInlines;
nsresult rv = BustUpInlinesAtBRs(*node->AsContent(), arrayOfInlines);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -7645,17 +7646,17 @@ HTMLEditRules::GetListActionNodes(
}
}
{
// We don't like other people messing with our selection!
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
// contruct a list of nodes to act on.
- nsresult rv = GetNodesFromSelection(EditAction::makeList,
+ nsresult rv = GetNodesFromSelection(EditSubAction::makeList,
aOutArrayOfNodes, aTouchContent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// Pre-process our list of nodes
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
@@ -7756,17 +7757,17 @@ HTMLEditRules::GetDefinitionListItemType
nsresult
HTMLEditRules::GetParagraphFormatNodes(
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes)
{
MOZ_ASSERT(IsEditorDataAvailable());
// Contruct a list of nodes to act on.
nsresult rv =
- GetNodesFromSelection(EditAction::makeBasicBlock,
+ GetNodesFromSelection(EditSubAction::makeBasicBlock,
outArrayOfNodes, TouchContent::no);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Pre-process our list of nodes
for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) {
OwningNonNull<nsINode> testNode = outArrayOfNodes[i];
@@ -7950,65 +7951,65 @@ HTMLEditRules::GetHighestInlineParent(ns
content = parent;
}
return content;
}
nsresult
HTMLEditRules::GetNodesFromPoint(
const EditorDOMPoint& aPoint,
- EditAction aOperation,
+ EditSubAction aEditSubAction,
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent)
{
if (NS_WARN_IF(!aPoint.IsSet())) {
return NS_ERROR_INVALID_ARG;
}
RefPtr<nsRange> range = new nsRange(aPoint.GetContainer());
IgnoredErrorResult ignoredError;
range->SetStart(aPoint, ignoredError);
// error will assert on failure, because we are not cleaning it up,
// but we're asserting in that case anyway.
MOZ_ASSERT(!ignoredError.Failed());
// Expand the range to include adjacent inlines
- PromoteRange(*range, aOperation);
+ PromoteRange(*range, aEditSubAction);
// Make array of ranges
nsTArray<RefPtr<nsRange>> arrayOfRanges;
// Stuff new opRange into array
arrayOfRanges.AppendElement(range);
// Use these ranges to contruct a list of nodes to act on
nsresult rv =
- GetNodesForOperation(arrayOfRanges, outArrayOfNodes, aOperation,
+ GetNodesForOperation(arrayOfRanges, outArrayOfNodes, aEditSubAction,
aTouchContent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
HTMLEditRules::GetNodesFromSelection(
- EditAction aOperation,
+ EditSubAction aEditSubAction,
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent)
{
MOZ_ASSERT(IsEditorDataAvailable());
// Promote selection ranges
nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(arrayOfRanges, aOperation);
+ GetPromotedRanges(arrayOfRanges, aEditSubAction);
// Use these ranges to contruct a list of nodes to act on.
nsresult rv = GetNodesForOperation(arrayOfRanges, outArrayOfNodes,
- aOperation, aTouchContent);
+ aEditSubAction, aTouchContent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
void
@@ -9459,17 +9460,17 @@ HTMLEditRules::ReapplyCachedStyles()
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// This style has disappeared through deletion. Let's add the styles to
// mTypeInState when same style isn't applied to the node already.
- if ((!bAny || IsStyleCachePreservingAction(mTheAction)) &&
+ if ((!bAny || IsStyleCachePreservingSubAction(mTopLevelEditSubAction)) &&
(!styleAtInsertionPoint[i].mPresent ||
styleAtInsertionPoint[i].value != mCachedStyles[i].value)) {
HTMLEditorRef().mTypeInState->SetProp(mCachedStyles[i].tag,
mCachedStyles[i].attr,
mCachedStyles[i].value);
}
}
}
@@ -11061,22 +11062,22 @@ HTMLEditRules::PrepareToMakeElementAbsol
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
// Convert the selection ranges into "promoted" selection ranges: this
// basically just expands the range to include the immediate block parent,
// and then further expands to include any ancestors whose children are all
// in the range.
nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(arrayOfRanges, EditAction::setAbsolutePosition);
+ GetPromotedRanges(arrayOfRanges, EditSubAction::setAbsolutePosition);
// Use these ranges to contruct a list of nodes to act on.
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
- EditAction::setAbsolutePosition,
+ EditSubAction::setAbsolutePosition,
TouchContent::yes);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// If nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes)) {
nsRange* firstRange = SelectionRef().GetRangeAt(0);
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -21,20 +21,19 @@ class nsAtom;
class nsIEditor;
class nsINode;
class nsRange;
namespace mozilla {
class EditActionResult;
class HTMLEditor;
-class RulesInfo;
class SplitNodeResult;
class TextEditor;
-enum class EditAction : int32_t;
+enum class EditSubAction : int32_t;
namespace dom {
class Element;
class Selection;
} // namespace dom
struct StyleCache final : public PropItem
{
@@ -92,26 +91,26 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditRules, TextEditRules)
HTMLEditRules();
// TextEditRules methods
virtual nsresult Init(TextEditor* aTextEditor) override;
virtual nsresult DetachEditor() override;
- virtual nsresult BeforeEdit(EditAction aAction,
+ virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection) override;
- virtual nsresult AfterEdit(EditAction aAction,
+ virtual nsresult AfterEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection) override;
virtual nsresult WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
bool* aCancel,
bool* aHandled) override;
virtual nsresult DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
nsresult aResult) override;
virtual bool DocumentIsEmpty() override;
virtual nsresult DocumentModified() override;
nsresult GetListState(bool* aMixed, bool* aOL, bool* aUL, bool* aDL);
nsresult GetListItemState(bool* aMixed, bool* aLI, bool* aDT, bool* aDD);
nsresult GetIndentState(bool* aCanIndent, bool* aCanOutdent);
nsresult GetAlignment(bool* aMixed, nsIHTMLEditor::EAlignment* aAlign);
@@ -139,18 +138,18 @@ public:
nsINode& aLeftNode, nsINode& aRightNode);
void DidInsertText(Selection& aSelection,
nsINode& aTextNode, int32_t aOffset,
const nsAString& aString);
void DidDeleteText(Selection& aSelection,
nsINode& aTextNode, int32_t aOffset, int32_t aLength);
void WillDeleteSelection(Selection& aSelection);
- void StartToListenToEditActions() { mListenerEnabled = true; }
- void EndListeningToEditActions() { mListenerEnabled = false; }
+ void StartToListenToEditSubActions() { mListenerEnabled = true; }
+ void EndListeningToEditSubActions() { mListenerEnabled = false; }
protected:
virtual ~HTMLEditRules();
HTMLEditor& HTMLEditorRef() const
{
MOZ_ASSERT(mData);
return mData->HTMLEditorRef();
@@ -183,27 +182,27 @@ protected:
*/
MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
/**
* Called before inserting text.
* This method may actually inserts text into the editor. Therefore, this
* might cause destroying the editor.
*
- * @param aAction Must be EditAction::insertIMEText or
- * EditAction::insertText.
+ * @param aEditSubAction Must be EditSubAction::insertIMEText or
+ * EditSubAction::insertText.
* @param aCancel Returns true if the operation is canceled.
* @param aHandled Returns true if the edit action is handled.
* @param inString String to be inserted.
* @param outString String actually inserted.
* @param aMaxLength The maximum string length which the editor
* allows to set.
*/
MOZ_MUST_USE nsresult
- WillInsertText(EditAction aAction, bool* aCancel, bool* aHandled,
+ WillInsertText(EditSubAction aEditSubAction, bool* aCancel, bool* aHandled,
const nsAString* inString, nsAString* outString,
int32_t aMaxLength);
/**
* WillLoadHTML() is called before loading enter document from source.
* This removes bogus node if there is.
*/
MOZ_MUST_USE nsresult WillLoadHTML();
@@ -700,17 +699,18 @@ protected:
MOZ_MUST_USE nsresult
ReturnInListItem(Element& aListItem, nsINode& aNode, int32_t aOffset);
/**
* Called after handling edit action. This may adjust Selection, remove
* unnecessary empty nodes, create <br> elements if needed, etc.
*/
MOZ_MUST_USE nsresult
- AfterEditInner(EditAction action, nsIEditor::EDirection aDirection);
+ AfterEditInner(EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection);
/**
* IndentAroundSelectionWithCSS() indents around Selection with CSS.
* This method creates AutoSelectionRestorer. Therefore, each caller
* need to check if the editor is still available even if this returns
* NS_OK.
*/
MOZ_MUST_USE nsresult IndentAroundSelectionWithCSS();
@@ -897,64 +897,66 @@ protected:
* where the other methods easier to handle edit action.
*/
MOZ_MUST_USE nsresult NormalizeSelection();
/**
* GetPromotedPoint() figures out where a start or end point for a block
* operation really is.
*/
- EditorDOMPoint GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode,
- int32_t aOffset, EditAction actionID);
+ EditorDOMPoint
+ GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode, int32_t aOffset,
+ EditSubAction aEditSubAction);
/**
* GetPromotedRanges() runs all the selection range endpoint through
* GetPromotedPoint().
*/
void GetPromotedRanges(nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
- EditAction inOperationType);
+ EditSubAction aEditSubAction);
/**
* PromoteRange() expands a range to include any parents for which all
* editable children are already in range.
*/
- void PromoteRange(nsRange& aRange, EditAction inOperationType);
+ void PromoteRange(nsRange& aRange, EditSubAction aEditSubAction);
/**
* GetNodesForOperation() runs through the ranges in the array and construct a
* new array of nodes to be acted on.
*
* XXX This name stats with "Get" but actually this modifies the DOM tree with
* transaction. We should rename this to making clearer what this does.
*/
enum class TouchContent { no, yes };
MOZ_MUST_USE nsresult
GetNodesForOperation(nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EditAction aOperationType, TouchContent aTouchContent);
+ EditSubAction aEditSubAction,
+ TouchContent aTouchContent);
void GetChildNodesForOperation(
nsINode& aNode,
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
/**
* GetNodesFromPoint() constructs a list of nodes from a point that will be
* operated on.
*/
MOZ_MUST_USE nsresult
- GetNodesFromPoint(const EditorDOMPoint& aPoint, EditAction aOperation,
+ GetNodesFromPoint(const EditorDOMPoint& aPoint, EditSubAction aEditSubAction,
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent);
/**
* GetNodesFromSelection() constructs a list of nodes from the selection that
* will be operated on.
*/
MOZ_MUST_USE nsresult
- GetNodesFromSelection(EditAction aOperation,
+ GetNodesFromSelection(EditSubAction aEditSubAction,
nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent);
enum class EntireList { no, yes };
MOZ_MUST_USE nsresult
GetListActionNodes(nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
EntireList aEntireList, TouchContent aTouchContent);
void GetDefinitionListItemTypes(Element* aElement, bool* aDT, bool* aDD);
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -151,17 +151,17 @@ HTMLEditor::HTMLEditor()
? ParagraphSeparator::div : ParagraphSeparator::br)
{
mIsHTMLEditorClass = true;
}
HTMLEditor::~HTMLEditor()
{
if (mRules && mRules->AsHTMLEditRules()) {
- mRules->AsHTMLEditRules()->EndListeningToEditActions();
+ mRules->AsHTMLEditRules()->EndListeningToEditSubActions();
}
mTypeInState = nullptr;
if (mLinkHandler && IsInitialized()) {
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (ps && ps->GetPresContext()) {
@@ -1149,17 +1149,19 @@ HTMLEditor::TabInTable(bool inIsShift,
return NS_OK;
}
nsresult
HTMLEditor::InsertBrElementAtSelectionWithTransaction()
{
// calling it text insertion to trigger moz br treatment by rules
- AutoRules beginRulesSniffing(this, EditAction::insertText, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertText,
+ nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
if (!selection->IsCollapsed()) {
nsresult rv = DeleteSelectionAsAction(eNone, eStrip);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -1216,24 +1218,28 @@ HTMLEditor::CollapseSelectionToDeepestNo
* This is mostly like InsertHTMLWithCharsetAndContext, but we can't use that
* because it is selection-based and the rules code won't let us edit under the
* <head> node
*/
NS_IMETHODIMP
HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
{
// don't do any post processing, rules get confused
- AutoRules beginRulesSniffing(this, EditAction::ignore, nsIEditor::eNone);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::ignore,
+ nsIEditor::eNone);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
CommitComposition();
- // Do not use AutoRules -- rules code won't let us insert in <head>. Use
- // the head node as a parent and delete/insert directly.
+ // Do not use AutoTopLevelEditSubActionNotifier -- rules code won't let us
+ // insert in <head>. Use the head node as a parent and delete/insert
+ // directly.
+ // XXX We're using AutoTopLevelEditSubActionNotifier above...
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<nsContentList> nodeList =
document->GetElementsByTagName(NS_LITERAL_STRING("head"));
NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
@@ -1549,28 +1555,30 @@ HTMLEditor::InsertElementAtSelection(Ele
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
CommitComposition();
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertElement,
+ nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
if (!selection) {
return NS_ERROR_FAILURE;
}
// hand off to the rules system, see if it has anything to say about this
bool cancel, handled;
- RulesInfo ruleInfo(EditAction::insertElement);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (!handled) {
if (aDeleteSelection) {
if (!IsBlockNode(aElement)) {
// E.g., inserting an image. In this case we don't need to delete any
@@ -1632,17 +1640,17 @@ HTMLEditor::InsertElementAtSelection(Ele
RefPtr<Element> newBrElement =
InsertBrElementWithTransaction(*selection, insertedPoint, ePrevious);
if (NS_WARN_IF(!newBrElement)) {
return NS_ERROR_FAILURE;
}
}
}
}
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
return rv;
}
template<typename PT, typename CT>
EditorDOMPoint
HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
nsIContent& aNode,
const EditorDOMPointBase<PT, CT>& aPointToInsert,
@@ -2005,27 +2013,30 @@ HTMLEditor::MakeOrChangeList(const nsASt
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
bool cancel, handled;
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeList, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::makeList,
+ nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(EditAction::makeList);
- ruleInfo.blockType = &aListType;
- ruleInfo.entireList = entireList;
- ruleInfo.bulletType = &aBulletType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(EditSubAction::makeList);
+ subActionInfo.blockType = &aListType;
+ subActionInfo.entireList = entireList;
+ subActionInfo.bulletType = &aBulletType;
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (!handled && selection->IsCollapsed()) {
nsRange* firstRange = selection->GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return NS_ERROR_FAILURE;
@@ -2081,52 +2092,55 @@ HTMLEditor::MakeOrChangeList(const nsASt
}
ErrorResult error;
selection->Collapse(RawRangeBoundary(newItem, 0), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
NS_IMETHODIMP
HTMLEditor::RemoveList(const nsAString& aListType)
{
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
bool cancel, handled;
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::removeList, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::removeList,
+ nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(EditAction::removeList);
+ EditSubActionInfo subActionInfo(EditSubAction::removeList);
if (aListType.LowerCaseEqualsLiteral("ol")) {
- ruleInfo.bOrdered = true;
+ subActionInfo.bOrdered = true;
} else {
- ruleInfo.bOrdered = false;
- }
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ subActionInfo.bOrdered = false;
+ }
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
// no default behavior for this yet. what would it mean?
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
nsresult
HTMLEditor::MakeDefinitionListItemWithTransaction(nsAtom& aTagName)
{
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -2135,37 +2149,39 @@ HTMLEditor::MakeDefinitionListItemWithTr
&aTagName == nsGkAtoms::dd);
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
bool cancel, handled;
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeDefListItem,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::makeDefListItem,
+ nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
nsDependentAtomString tagName(&aTagName);
- RulesInfo ruleInfo(EditAction::makeDefListItem);
- ruleInfo.blockType = &tagName;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(EditSubAction::makeDefListItem);
+ subActionInfo.blockType = &tagName;
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (!handled) {
// todo: no default for now. we count on rules to handle it.
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
nsresult
HTMLEditor::InsertBasicBlockWithTransaction(nsAtom& aTagName)
{
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -2174,26 +2190,28 @@ HTMLEditor::InsertBasicBlockWithTransact
&aTagName != nsGkAtoms::dt);
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
bool cancel, handled;
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeBasicBlock,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::makeBasicBlock,
+ nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
nsDependentAtomString tagName(&aTagName);
- RulesInfo ruleInfo(EditAction::makeBasicBlock);
- ruleInfo.blockType = &tagName;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(EditSubAction::makeBasicBlock);
+ subActionInfo.blockType = &tagName;
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (!handled && selection->IsCollapsed()) {
nsRange* firstRange = selection->GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return NS_ERROR_FAILURE;
@@ -2244,43 +2262,45 @@ HTMLEditor::InsertBasicBlockWithTransact
// reposition selection to inside the block
ErrorResult error;
selection->Collapse(RawRangeBoundary(newBlock, 0), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
NS_IMETHODIMP
HTMLEditor::Indent(const nsAString& aIndent)
{
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
bool cancel, handled;
- EditAction opID = EditAction::indent;
+ EditSubAction editSubAction = EditSubAction::indent;
if (aIndent.LowerCaseEqualsLiteral("outdent")) {
- opID = EditAction::outdent;
+ editSubAction = EditSubAction::outdent;
}
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, editSubAction, nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(opID);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(editSubAction);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (!handled && selection->IsCollapsed() && aIndent.EqualsLiteral("indent")) {
nsRange* firstRange = selection->GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return NS_ERROR_FAILURE;
@@ -2345,43 +2365,46 @@ HTMLEditor::Indent(const nsAString& aInd
return NS_ERROR_FAILURE;
}
selection->Collapse(RawRangeBoundary(firstRange->GetStartContainer(), 0),
error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
//TODO: IMPLEMENT ALIGNMENT!
NS_IMETHODIMP
HTMLEditor::Align(const nsAString& aAlignType)
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::align, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::align,
+ nsIEditor::eNext);
bool cancel, handled;
// Find out if the selection is collapsed:
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- RulesInfo ruleInfo(EditAction::align);
- ruleInfo.alignType = &aAlignType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ EditSubActionInfo subActionInfo(EditSubAction::align);
+ subActionInfo.alignType = &aAlignType;
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
already_AddRefed<Element>
HTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName,
nsINode* aNode)
{
MOZ_ASSERT(!aTagName.IsEmpty());
@@ -3356,17 +3379,17 @@ HTMLEditor::DoContentInserted(nsIContent
if (ShouldReplaceRootElement()) {
UpdateRootElement();
nsContentUtils::AddScriptRunner(
NewRunnableMethod("HTMLEditor::NotifyRootChanged",
this,
&HTMLEditor::NotifyRootChanged));
}
// We don't need to handle our own modifications
- else if (!mAction && container->IsEditable()) {
+ else if (!mTopLevelEditSubAction && container->IsEditable()) {
if (IsMozEditorBogusNode(aChild)) {
// Ignore insertion of the bogus node
return;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
rules->DocumentModified();
@@ -3399,17 +3422,17 @@ HTMLEditor::ContentRemoved(nsIContent* a
if (SameCOMIdentity(aChild, mRootElement)) {
mRootElement = nullptr;
nsContentUtils::AddScriptRunner(
NewRunnableMethod("HTMLEditor::NotifyRootChanged",
this,
&HTMLEditor::NotifyRootChanged));
// We don't need to handle our own modifications
- } else if (!mAction && aChild->GetParentNode()->IsEditable()) {
+ } else if (!mTopLevelEditSubAction && aChild->GetParentNode()->IsEditable()) {
if (aChild && IsMozEditorBogusNode(aChild)) {
// Ignore removal of the bogus node
return;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
rules->DocumentModified();
}
@@ -3465,48 +3488,51 @@ HTMLEditor::StyleSheetLoaded(StyleSheet*
// Also save in our arrays of urls and sheets
AddNewStyleSheetToList(mLastStyleSheetURL, aSheet);
}
}
return NS_OK;
}
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-nsresult
-HTMLEditor::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
+void
+HTMLEditor::OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection)
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- EditorBase::StartOperation(opID, aDirection); // will set mAction, mDirection
- if (rules) {
- return rules->BeforeEdit(mAction, mDirection);
- }
- return NS_OK;
+ EditorBase::OnStartToHandleTopLevelEditSubAction(aEditSubAction, aDirection);
+ if (!rules) {
+ return;
+ }
+
+ MOZ_ASSERT(mTopLevelEditSubAction == aEditSubAction);
+ MOZ_ASSERT(mDirection == aDirection);
+ DebugOnly<nsresult> rv =
+ rules->BeforeEdit(mTopLevelEditSubAction, mDirection);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "HTMLEditRules::BeforeEdit() failed to handle something");
}
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-nsresult
-HTMLEditor::EndOperation()
+void
+HTMLEditor::OnEndHandlingTopLevelEditSubAction()
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
// post processing
- nsresult rv = rules ? rules->AfterEdit(mAction, mDirection) : NS_OK;
- EditorBase::EndOperation(); // will clear mAction, mDirection
- return rv;
+ DebugOnly<nsresult> rv =
+ rules ? rules->AfterEdit(mTopLevelEditSubAction, mDirection) : NS_OK;
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "HTMLEditRules::AfterEdit() failed to handle something");
+ EditorBase::OnEndHandlingTopLevelEditSubAction();
+ MOZ_ASSERT(!mTopLevelEditSubAction);
+ MOZ_ASSERT(mDirection == eNone);
}
bool
HTMLEditor::TagCanContainTag(nsAtom& aParentTag,
nsAtom& aChildTag) const
{
int32_t childTagEnum;
// XXX Should this handle #cdata-section too?
@@ -4338,25 +4364,29 @@ HTMLEditor::SetCSSBackgroundColorWithTra
RefPtr<TextEditRules> rules(mRules);
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
bool isCollapsed = selection->IsCollapsed();
AutoPlaceholderBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertElement,
+ nsIEditor::eNext);
AutoSelectionRestorer selectionRestorer(selection, this);
AutoTransactionsConserveSelection dontChangeMySelection(this);
bool cancel, handled;
- RulesInfo ruleInfo(EditAction::setTextProperty);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ EditSubActionInfo subActionInfo(EditSubAction::setTextProperty);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (!cancel && !handled) {
// Loop through the ranges in the selection
for (uint32_t i = 0; i < selection->RangeCount(); i++) {
RefPtr<nsRange> range = selection->GetRangeAt(i);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
nsCOMPtr<Element> cachedBlockParent;
@@ -4467,17 +4497,17 @@ HTMLEditor::SetCSSBackgroundColorWithTra
false);
}
}
}
}
}
if (!cancel) {
// Post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::SetBackgroundColor(const nsAString& aColor)
{
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -40,17 +40,17 @@ class nsIClipboard;
class nsILinkHandler;
class nsTableWrapperFrame;
class nsRange;
namespace mozilla {
class AutoSelectionSetterAfterTableEdit;
class EmptyEditableFunctor;
class ResizerSelectionListener;
-enum class EditAction : int32_t;
+enum class EditSubAction : int32_t;
struct PropItem;
template<class T> class OwningNonNull;
namespace dom {
class DocumentFragment;
class Event;
class MouseEvent;
} // namespace dom
namespace widget {
@@ -731,28 +731,20 @@ protected: // May be called by friends.
nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
nsAtom* aProperty, nsAtom* aAttribute);
nsresult SetPositionToAbsolute(Element& aElement);
nsresult SetPositionToStatic(Element& aElement);
protected: // Called by helper classes.
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- virtual nsresult StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection) override;
-
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- virtual nsresult EndOperation() override;
+ virtual void
+ OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
+ virtual void OnEndHandlingTopLevelEditSubAction() override;
virtual nsresult EndUpdateViewBatch() override;
protected: // Shouldn't be used by friend classes
virtual ~HTMLEditor();
/**
* InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -87,28 +87,33 @@ static nsresult FindTargetNode(nsINode*
nsresult
HTMLEditor::LoadHTML(const nsAString& aInputString)
{
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
// force IME commit; set up rules sniffing and batching
CommitComposition();
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::loadHTML, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::loadHTML,
+ nsIEditor::eNext);
// Get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
- RulesInfo ruleInfo(EditAction::loadHTML);
+ EditSubActionInfo subActionInfo(EditSubAction::loadHTML);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (cancel) {
return NS_OK; // rules canceled the operation
}
if (!handled) {
// Delete Selection, but only if it isn't collapsed, see bug #106269
if (!selection->IsCollapsed()) {
rv = DeleteSelectionAsAction(eNone, eStrip);
@@ -153,17 +158,17 @@ HTMLEditor::LoadHTML(const nsAString& aI
if (NS_WARN_IF(!pointToInsert.Offset())) {
// Append the remaining children to the container if offset is
// overflown.
pointToInsert.SetToEndOf(pointToInsert.GetContainer());
}
}
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
NS_IMETHODIMP
HTMLEditor::InsertHTML(const nsAString& aInString)
{
const nsString& empty = EmptyString();
return DoInsertHTMLWithContext(aInString, empty, empty, empty,
@@ -202,17 +207,19 @@ HTMLEditor::DoInsertHTMLWithContext(cons
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
// Prevent the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
// force IME commit; set up rules sniffing and batching
CommitComposition();
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::htmlPaste, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::htmlPaste,
+ nsIEditor::eNext);
// Get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
// create a dom document fragment that represents the structure to paste
nsCOMPtr<nsINode> fragmentAsNode, streamStartParent, streamEndParent;
int32_t streamStartOffset = 0, streamEndOffset = 0;
@@ -328,19 +335,19 @@ HTMLEditor::DoInsertHTMLWithContext(cons
rv = DeleteTableCell(1);
NS_ENSURE_SUCCESS(rv, rv);
}
// collapse selection to beginning of deleted table content
selection->CollapseToStart(IgnoreErrors());
}
// give rules a chance to handle or cancel
- RulesInfo ruleInfo(EditAction::insertElement);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(rv, rv);
if (cancel) {
return NS_OK; // rules canceled the operation
}
if (!handled) {
// Adjust position based on the first node we are going to insert.
// FYI: WillDoAction() above might have changed the selection.
@@ -684,17 +691,17 @@ HTMLEditor::DoInsertHTMLWithContext(cons
if (afterLeftLink.AdvanceOffset()) {
selection->Collapse(afterLeftLink);
}
}
}
}
}
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
bool
HTMLEditor::IsInLink(nsINode* aNode,
nsCOMPtr<nsINode>* outLink)
{
NS_ENSURE_TRUE(aNode, false);
if (outLink) {
@@ -1577,46 +1584,51 @@ HTMLEditor::PasteAsQuotation(int32_t aSe
return PasteAsCitedQuotation(citation, aSelectionType);
}
NS_IMETHODIMP
HTMLEditor::PasteAsCitedQuotation(const nsAString& aCitation,
int32_t aSelectionType)
{
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertQuotation,
+ nsIEditor::eNext);
// get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// give rules a chance to handle or cancel
- RulesInfo ruleInfo(EditAction::insertElement);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (cancel || handled) {
return NS_OK; // rules canceled the operation
}
nsCOMPtr<Element> newNode =
DeleteSelectionAndCreateElement(*nsGkAtoms::blockquote);
NS_ENSURE_TRUE(newNode, NS_ERROR_NULL_POINTER);
// Try to set type=cite. Ignore it if this fails.
newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("cite"), true);
// Set the selection to the underneath the node we just inserted:
rv = selection->Collapse(newNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
+ // XXX Why don't we call HTMLEditRules::DidDoAction() after Paste()?
return Paste(aSelectionType);
}
/**
* Paste a plaintext quotation.
*/
nsresult
HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType)
@@ -1782,26 +1794,30 @@ HTMLEditor::InsertAsPlaintextQuotation(c
bool aAddCites,
nsINode** aNodeInserted)
{
// get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertQuotation,
+ nsIEditor::eNext);
// give rules a chance to handle or cancel
- RulesInfo ruleInfo(EditAction::insertElement);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (cancel || handled) {
return NS_OK; // rules canceled the operation
}
// Wrap the inserted quote in a <span> so we can distinguish it. If we're
// inserting into the <body>, we use a <span> which is displayed as a block
// and sized to the screen using 98 viewport width units.
// We could use 100vw, but 98vw avoids a horizontal scroll bar where possible.
@@ -1851,16 +1867,18 @@ HTMLEditor::InsertAsPlaintextQuotation(c
// Set the selection to just after the inserted node:
if (NS_SUCCEEDED(rv) && newNode) {
EditorRawDOMPoint afterNewNode(newNode);
if (afterNewNode.AdvanceOffset()) {
selection->Collapse(afterNewNode);
}
}
+
+ // XXX Why don't we call HTMLEditRules::DidDoAction() here?
return rv;
}
NS_IMETHODIMP
HTMLEditor::StripCites()
{
return TextEditor::StripCites();
}
@@ -1883,26 +1901,30 @@ HTMLEditor::InsertAsCitedQuotation(const
return InsertAsPlaintextQuotation(aQuotedText, true, aNodeInserted);
}
// get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertQuotation,
+ nsIEditor::eNext);
// give rules a chance to handle or cancel
- RulesInfo ruleInfo(EditAction::insertElement);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
bool cancel, handled;
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (cancel || handled) {
return NS_OK; // rules canceled the operation
}
nsCOMPtr<Element> newNode =
DeleteSelectionAndCreateElement(*nsGkAtoms::blockquote);
NS_ENSURE_TRUE(newNode, NS_ERROR_NULL_POINTER);
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -80,26 +80,30 @@ HTMLEditor::SetInlineProperty(nsAtom* aP
if (selection->IsCollapsed()) {
// Manipulating text attributes on a collapsed selection only sets state
// for the next text insertion
mTypeInState->SetProp(aProperty, aAttribute, aValue);
return NS_OK;
}
AutoPlaceholderBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertElement,
+ nsIEditor::eNext);
AutoSelectionRestorer selectionRestorer(selection, this);
AutoTransactionsConserveSelection dontChangeMySelection(this);
bool cancel, handled;
- RulesInfo ruleInfo(EditAction::setTextProperty);
+ EditSubActionInfo subActionInfo(EditSubAction::setTextProperty);
// Protect the edit rules object from dying
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (!cancel && !handled) {
// Loop through the ranges in the selection
AutoRangeArray arrayOfRanges(selection);
for (auto& range : arrayOfRanges.mRanges) {
// Adjust range to include any ancestors whose children are entirely
// selected
rv = PromoteInlineRange(*range);
NS_ENSURE_SUCCESS(rv, rv);
@@ -170,17 +174,17 @@ HTMLEditor::SetInlineProperty(nsAtom* aP
range->EndOffset(), *aProperty,
aAttribute, aValue);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
if (!cancel) {
// Post-process
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
return NS_OK;
}
// Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>,
// <span style="">, etc. that we can reuse instead of creating a new one?
bool
HTMLEditor::IsSimpleModifiableNode(nsIContent* aContent,
@@ -1184,18 +1188,19 @@ HTMLEditor::GetInlinePropertyWithAttrVal
val = &aValue;
return GetInlinePropertyBase(*aProperty, aAttribute, val, aFirst, aAny, aAll, &outValue);
}
NS_IMETHODIMP
HTMLEditor::RemoveAllInlineProperties()
{
AutoPlaceholderBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::resetTextProperties,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::resetTextProperties,
+ nsIEditor::eNext);
nsresult rv = RemoveInlineProperty(nullptr, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::RemoveInlineProperty(const nsAString& aProperty,
@@ -1229,27 +1234,31 @@ HTMLEditor::RemoveInlineProperty(nsAtom*
mTypeInState->ClearProp(aProperty, aAttribute);
} else {
mTypeInState->ClearAllProps();
}
return NS_OK;
}
AutoPlaceholderBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::removeTextProperty,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::removeTextProperty,
+ nsIEditor::eNext);
AutoSelectionRestorer selectionRestorer(selection, this);
AutoTransactionsConserveSelection dontChangeMySelection(this);
bool cancel, handled;
- RulesInfo ruleInfo(EditAction::removeTextProperty);
+ EditSubActionInfo subActionInfo(EditSubAction::removeTextProperty);
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (!cancel && !handled) {
// Loop through the ranges in the selection
// Since ranges might be modified by SplitStyleAboveRange, we need hold
// current ranges
AutoRangeArray arrayOfRanges(selection);
for (auto& range : arrayOfRanges.mRanges) {
if (aProperty == nsGkAtoms::name) {
// Promote range if it starts or end in a named anchor and we want to
@@ -1334,17 +1343,17 @@ HTMLEditor::RemoveInlineProperty(nsAtom*
SetInlinePropertyOnNode(node, *aProperty, aAttribute, value);
}
}
}
}
}
if (!cancel) {
// Post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
HTMLEditor::IncreaseFontSize()
{
@@ -1386,18 +1395,19 @@ HTMLEditor::RelativeFontChange(FontSize
// Manipulating text attributes on a collapsed selection only sets state
// for the next text insertion
mTypeInState->SetProp(&atom, nullptr, EmptyString());
return NS_OK;
}
// Wrap with txn batching, rules sniffing, and selection preservation code
AutoPlaceholderBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::setTextProperty,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::setTextProperty,
+ nsIEditor::eNext);
AutoSelectionRestorer selectionRestorer(selection, this);
AutoTransactionsConserveSelection dontChangeMySelection(this);
// Loop through the ranges in the selection
AutoRangeArray arrayOfRanges(selection);
for (auto& range : arrayOfRanges.mRanges) {
// Adjust range to include any ancestors with entirely selected children
nsresult rv = PromoteInlineRange(*range);
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -370,17 +370,19 @@ HTMLEditor::InsertTableColumn(int32_t aN
&curStartRowIndex, &curStartColIndex,
&rowSpan, &colSpan,
&actualRowSpan, &actualColSpan, &isSelected);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(curCell, NS_ERROR_FAILURE);
AutoPlaceholderBatch beginBatching(this);
// Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
// Use column after current cell if requested
if (aAfter) {
startColIndex += actualColSpan;
//Detect when user is adding after a COLSPAN=0 case
// Assume they want to stop the "0" behavior and
// really add a new column. Thus we set the
// colspan to its true value
@@ -503,17 +505,19 @@ HTMLEditor::InsertTableRow(int32_t aNumb
NS_ENSURE_TRUE(curCell, NS_ERROR_FAILURE);
int32_t rowCount, colCount;
rv = GetTableSize(table, &rowCount, &colCount);
NS_ENSURE_SUCCESS(rv, rv);
AutoPlaceholderBatch beginBatching(this);
// Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
if (aAfter) {
// Use row after current cell
startRowIndex += actualRowSpan;
//Detect when user is adding after a ROWSPAN=0 case
// Assume they want to stop the "0" behavior and
// really add a new row. Thus we set the
@@ -714,17 +718,19 @@ HTMLEditor::DeleteTableCell(int32_t aNum
&startRowIndex, &startColIndex);
NS_ENSURE_SUCCESS(rv, rv);
// Don't fail if we didn't find a table or cell
NS_ENSURE_TRUE(table && cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
AutoPlaceholderBatch beginBatching(this);
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
RefPtr<Element> firstCell;
rv = GetFirstSelectedCell(nullptr, getter_AddRefs(firstCell));
NS_ENSURE_SUCCESS(rv, rv);
if (firstCell && selection->RangeCount() > 1) {
// When > 1 selected cell,
// ignore aNumber and use selected cells
@@ -898,17 +904,19 @@ HTMLEditor::DeleteTableCellContents()
&startRowIndex, &startColIndex);
NS_ENSURE_SUCCESS(rv, rv);
// Don't fail if no cell found
NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
AutoPlaceholderBatch beginBatching(this);
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
//Don't let Rules System change the selection
AutoTransactionsConserveSelection dontChangeSelection(this);
RefPtr<Element> firstCell;
rv = GetFirstSelectedCell(nullptr, getter_AddRefs(firstCell));
NS_ENSURE_SUCCESS(rv, rv);
@@ -935,17 +943,19 @@ HTMLEditor::DeleteTableCellContents()
}
return NS_OK;
}
nsresult
HTMLEditor::DeleteCellContents(Element* aCell)
{
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
while (nsCOMPtr<nsINode> child = aCell->GetLastChild()) {
nsresult rv = DeleteNodeWithTransaction(*child);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
@@ -975,17 +985,19 @@ HTMLEditor::DeleteTableColumn(int32_t aN
return DeleteTable2(table, selection);
}
// Check for counts too high
aNumber = std::min(aNumber,(colCount-startColIndex));
AutoPlaceholderBatch beginBatching(this);
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
// Test if deletion is controlled by selected cells
RefPtr<Element> firstCell;
rv = GetFirstSelectedCell(nullptr, getter_AddRefs(firstCell));
NS_ENSURE_SUCCESS(rv, rv);
uint32_t rangeCount = selection->RangeCount();
@@ -1138,17 +1150,19 @@ HTMLEditor::DeleteTableRow(int32_t aNumb
// Shortcut the case of deleting all rows in table
if (!startRowIndex && aNumber >= rowCount) {
return DeleteTable2(table, selection);
}
AutoPlaceholderBatch beginBatching(this);
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
RefPtr<Element> firstCell;
rv = GetFirstSelectedCell(nullptr, getter_AddRefs(firstCell));
NS_ENSURE_SUCCESS(rv, rv);
uint32_t rangeCount = selection->RangeCount();
if (firstCell && rangeCount > 1) {
@@ -1217,17 +1231,19 @@ HTMLEditor::DeleteRow(Element* aTable,
RefPtr<Element> cell;
RefPtr<Element> cellInDeleteRow;
int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
bool isSelected;
int32_t colIndex = 0;
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(*
+ this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
// The list of cells we will change rowspan in
// and the new rowspan values for each
nsTArray<RefPtr<Element> > spanCellList;
nsTArray<int32_t> newSpanList;
int32_t rowCount, colCount;
nsresult rv = GetTableSize(aTable, &rowCount, &colCount);
@@ -1657,17 +1673,19 @@ HTMLEditor::SplitTableCell()
// Must have some span to split
if (actualRowSpan <= 1 && actualColSpan <= 1) {
return NS_OK;
}
AutoPlaceholderBatch beginBatching(this);
// Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
// We reset selection
AutoSelectionSetterAfterTableEdit setCaret(*this, table, startRowIndex,
startColIndex, ePreviousColumn,
false);
//...so suppress Rules System selection munging
AutoTransactionsConserveSelection dontChangeSelection(this);
@@ -1890,17 +1908,19 @@ HTMLEditor::SwitchTableCellHeaderType(El
{
if (NS_WARN_IF(!aSourceCell)) {
return NS_ERROR_INVALID_ARG;
}
AutoPlaceholderBatch beginBatching(this);
// Prevent auto insertion of BR in new cell created by
// ReplaceContainerAndCloneAttributesWithTransaction().
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
// Save current selection to restore when done.
// This is needed so ReplaceContainerAndCloneAttributesWithTransaction()
// can monitor selection when replacing nodes.
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
@@ -2131,18 +2151,19 @@ HTMLEditor::JoinTableCells(bool aMergeNo
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
}
// All cell contents are merged. Delete the empty cells we accumulated
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode,
- nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
for (uint32_t i = 0, n = deleteList.Length(); i < n; i++) {
RefPtr<Element> nodeToBeRemoved = deleteList[i];
if (nodeToBeRemoved) {
rv = DeleteNodeWithTransaction(*nodeToBeRemoved);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -2246,17 +2267,19 @@ HTMLEditor::JoinTableCells(bool aMergeNo
nsresult
HTMLEditor::MergeCells(RefPtr<Element> aTargetCell,
RefPtr<Element> aCellToMerge,
bool aDeleteCellToMerge)
{
NS_ENSURE_TRUE(aTargetCell && aCellToMerge, NS_ERROR_NULL_POINTER);
// Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteNode,
+ nsIEditor::eNext);
// Don't need to merge if cell is empty
if (!IsEmptyCell(aCellToMerge)) {
// Get index of last child in target cell
// If we fail or don't have children,
// we insert at index 0
int32_t insertIndex = 0;
@@ -2455,17 +2478,19 @@ HTMLEditor::NormalizeTable(Element* aTab
nsresult rv = GetTableSize(table, &rowCount, &colCount);
NS_ENSURE_SUCCESS(rv, rv);
// Save current selection
AutoSelectionRestorer selectionRestorer(selection, this);
AutoPlaceholderBatch beginBatching(this);
// Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertNode,
+ nsIEditor::eNext);
RefPtr<Element> cell;
int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
bool isSelected;
// Scan all cells in each row to detect bad rowspan values
for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
rv = FixBadRowSpan(table, rowIndex, rowCount);
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -67,17 +67,17 @@ TextEditRules::TextEditRules()
, mData(nullptr)
, mPasswordIMEIndex(0)
, mCachedSelectionOffset(0)
, mActionNesting(0)
, mLockRulesSniffing(false)
, mDidExplicitlySetInterline(false)
, mDeleteBidiImmediately(false)
, mIsHTMLEditRules(false)
- , mTheAction(EditAction::none)
+ , mTopLevelEditSubAction(EditSubAction::none)
, mLastStart(0)
, mLastLength(0)
{
InitFields();
}
void
TextEditRules::InitFields()
@@ -88,17 +88,17 @@ TextEditRules::InitFields()
mPasswordIMEIndex = 0;
mBogusNode = nullptr;
mCachedSelectionNode = nullptr;
mCachedSelectionOffset = 0;
mActionNesting = 0;
mLockRulesSniffing = false;
mDidExplicitlySetInterline = false;
mDeleteBidiImmediately = false;
- mTheAction = EditAction::none;
+ mTopLevelEditSubAction = EditSubAction::none;
mTimer = nullptr;
mLastStart = 0;
mLastLength = 0;
}
TextEditRules::~TextEditRules()
{
// do NOT delete mTextEditor here. We do not hold a ref count to
@@ -196,36 +196,36 @@ TextEditRules::DetachEditor()
if (mTimer) {
mTimer->Cancel();
}
mTextEditor = nullptr;
return NS_OK;
}
nsresult
-TextEditRules::BeforeEdit(EditAction aAction,
+TextEditRules::BeforeEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection)
{
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (mLockRulesSniffing) {
return NS_OK;
}
AutoLockRulesSniffing lockIt(this);
mDidExplicitlySetInterline = false;
if (!mActionNesting) {
// let rules remember the top level action
- mTheAction = aAction;
+ mTopLevelEditSubAction = aEditSubAction;
}
mActionNesting++;
- if (aAction == EditAction::setText) {
+ if (aEditSubAction == EditSubAction::setText) {
// setText replaces all text, so mCachedSelectionNode might be invalid on
// AfterEdit.
// Since this will be used as start position of spellchecker, we should
// use root instead.
mCachedSelectionNode = mTextEditor->GetRoot();
mCachedSelectionOffset = 0;
} else {
Selection* selection = mTextEditor->GetSelection();
@@ -235,17 +235,17 @@ TextEditRules::BeforeEdit(EditAction aAc
mCachedSelectionNode = selection->GetAnchorNode();
mCachedSelectionOffset = selection->AnchorOffset();
}
return NS_OK;
}
nsresult
-TextEditRules::AfterEdit(EditAction aAction,
+TextEditRules::AfterEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection)
{
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (mLockRulesSniffing) {
return NS_OK;
@@ -258,17 +258,17 @@ TextEditRules::AfterEdit(EditAction aAct
Selection* selection = mTextEditor->GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
AutoSafeEditorData setData(*this, *mTextEditor, *selection);
nsresult rv =
- TextEditorRef().HandleInlineSpellCheck(aAction, *selection,
+ TextEditorRef().HandleInlineSpellCheck(aEditSubAction, *selection,
mCachedSelectionNode,
mCachedSelectionOffset,
nullptr, 0, nullptr, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// no longer uses mCachedSelectionNode, so release it.
@@ -301,96 +301,96 @@ TextEditRules::AfterEdit(EditAction aAct
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to selection to after the text node in TextEditor");
}
return NS_OK;
}
nsresult
TextEditRules::WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
bool* aCancel,
bool* aHandled)
{
- if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aInfo)) {
+ if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
MOZ_ASSERT(aCancel);
MOZ_ASSERT(aHandled);
*aCancel = false;
*aHandled = false;
AutoSafeEditorData setData(*this, *mTextEditor, *aSelection);
// my kingdom for dynamic cast
- switch (aInfo->action) {
- case EditAction::insertBreak:
+ switch (aInfo.mEditSubAction) {
+ case EditSubAction::insertBreak:
UndefineCaretBidiLevel();
- return WillInsertBreak(aCancel, aHandled, aInfo->maxLength);
- case EditAction::insertText:
- case EditAction::insertIMEText:
+ return WillInsertBreak(aCancel, aHandled, aInfo.maxLength);
+ case EditSubAction::insertText:
+ case EditSubAction::insertIMEText:
UndefineCaretBidiLevel();
- return WillInsertText(aInfo->action, aCancel, aHandled,
- aInfo->inString, aInfo->outString,
- aInfo->maxLength);
- case EditAction::setText:
+ return WillInsertText(aInfo.mEditSubAction, aCancel, aHandled,
+ aInfo.inString, aInfo.outString,
+ aInfo.maxLength);
+ case EditSubAction::setText:
UndefineCaretBidiLevel();
- return WillSetText(aCancel, aHandled, aInfo->inString,
- aInfo->maxLength);
- case EditAction::deleteSelection:
- return WillDeleteSelection(aInfo->collapsedAction, aCancel, aHandled);
- case EditAction::undo:
+ return WillSetText(aCancel, aHandled, aInfo.inString,
+ aInfo.maxLength);
+ case EditSubAction::deleteSelection:
+ return WillDeleteSelection(aInfo.collapsedAction, aCancel, aHandled);
+ case EditSubAction::undo:
return WillUndo(aCancel, aHandled);
- case EditAction::redo:
+ case EditSubAction::redo:
return WillRedo(aCancel, aHandled);
- case EditAction::setTextProperty:
+ case EditSubAction::setTextProperty:
return WillSetTextProperty(aCancel, aHandled);
- case EditAction::removeTextProperty:
+ case EditSubAction::removeTextProperty:
return WillRemoveTextProperty(aCancel, aHandled);
- case EditAction::outputText:
- return WillOutputText(aInfo->outputFormat, aInfo->outString, aInfo->flags,
+ case EditSubAction::outputText:
+ return WillOutputText(aInfo.outputFormat, aInfo.outString, aInfo.flags,
aCancel, aHandled);
- case EditAction::insertElement:
+ case EditSubAction::insertElement:
// i had thought this would be html rules only. but we put pre elements
// into plaintext mail when doing quoting for reply! doh!
return WillInsert(aCancel);
default:
return NS_ERROR_FAILURE;
}
}
nsresult
TextEditRules::DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
nsresult aResult)
{
- if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aInfo)) {
+ if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
AutoSafeEditorData setData(*this, *mTextEditor, *aSelection);
// don't let any txns in here move the selection around behind our back.
// Note that this won't prevent explicit selection setting from working.
AutoTransactionsConserveSelection dontChangeMySelection(&TextEditorRef());
- switch (aInfo->action) {
- case EditAction::deleteSelection:
+ switch (aInfo.mEditSubAction) {
+ case EditSubAction::deleteSelection:
return DidDeleteSelection();
- case EditAction::undo:
+ case EditSubAction::undo:
return DidUndo(aResult);
- case EditAction::redo:
+ case EditSubAction::redo:
return DidRedo(aResult);
default:
// Don't fail on transactions we don't handle here!
return NS_OK;
}
}
bool
@@ -663,30 +663,30 @@ TextEditRules::HandleNewLines(nsString&
case nsIPlaintextEditor::eNewlinesPasteIntact:
// even if we're pasting newlines, don't paste leading/trailing ones
aString.Trim(CRLF, true, true);
break;
}
}
nsresult
-TextEditRules::WillInsertText(EditAction aAction,
+TextEditRules::WillInsertText(EditSubAction aEditSubAction,
bool* aCancel,
bool* aHandled,
const nsAString* inString,
nsAString* outString,
int32_t aMaxLength)
{
MOZ_ASSERT(IsEditorDataAvailable());
if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
return NS_ERROR_INVALID_ARG;
}
- if (inString->IsEmpty() && aAction != EditAction::insertIMEText) {
+ if (inString->IsEmpty() && aEditSubAction != EditSubAction::insertIMEText) {
// HACK: this is a fix for bug 19395
// I can't outlaw all empty insertions
// because IME transaction depend on them
// There is more work to do to make the
// world safe for IME.
*aCancel = true;
*aHandled = false;
return NS_OK;
@@ -702,17 +702,17 @@ TextEditRules::WillInsertText(EditAction
nsresult rv =
TruncateInsertionIfNeeded(inString, outString, aMaxLength, &truncated);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// If we're exceeding the maxlength when composing IME, we need to clean up
// the composing text, so we shouldn't return early.
if (truncated && outString->IsEmpty() &&
- aAction != EditAction::insertIMEText) {
+ aEditSubAction != EditSubAction::insertIMEText) {
*aCancel = true;
return NS_OK;
}
uint32_t start = 0;
uint32_t end = 0;
// handle password field docs
@@ -738,17 +738,17 @@ TextEditRules::WillInsertText(EditAction
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// handle password field data
// this has the side effect of changing all the characters in aOutString
// to the replacement character
if (IsPasswordEditor() &&
- aAction == EditAction::insertIMEText) {
+ aEditSubAction == EditSubAction::insertIMEText) {
RemoveIMETextFromPWBuf(start, outString);
}
// People have lots of different ideas about what text fields
// should do with multiline pastes. See bugs 21032, 23485, 23485, 50935.
// The six possible options are:
// 0. paste newlines intact
// 1. paste up to the first newline (default)
@@ -805,17 +805,17 @@ TextEditRules::WillInsertText(EditAction
}
// we need to get the doc
nsCOMPtr<nsIDocument> doc = TextEditorRef().GetDocument();
if (NS_WARN_IF(!doc)) {
return NS_ERROR_NOT_INITIALIZED;
}
- if (aAction == EditAction::insertIMEText) {
+ if (aEditSubAction == EditSubAction::insertIMEText) {
// Find better insertion point to insert text.
EditorRawDOMPoint betterInsertionPoint =
TextEditorRef().FindBetterInsertionPoint(atStartOfSelection);
// If there is one or more IME selections, its minimum offset should be
// the insertion point.
int32_t IMESelectionOffset =
TextEditorRef().GetIMESelectionStartOffsetIn(
betterInsertionPoint.GetContainer());
@@ -827,17 +827,17 @@ TextEditRules::WillInsertText(EditAction
betterInsertionPoint);
if (NS_WARN_IF(!CanHandleEditAction())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
- // aAction == EditAction::insertText
+ // aEditSubAction == EditSubAction::insertText
// don't change my selection in subtransactions
AutoTransactionsConserveSelection dontChangeMySelection(&TextEditorRef());
EditorRawDOMPoint pointAfterStringInserted;
rv = TextEditorRef().InsertTextWithTransaction(*doc, *outString,
atStartOfSelection,
&pointAfterStringInserted);
@@ -1494,18 +1494,19 @@ TextEditRules::CreateBogusNodeIfNeeded()
MOZ_ASSERT(IsEditorDataAvailable());
if (mBogusNode) {
// Let's not create more than one, ok?
return NS_OK;
}
// tell rules system to not do any post-processing
- AutoRules beginRulesSniffing(&TextEditorRef(), EditAction::ignore,
- nsIEditor::eNone);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ TextEditorRef(), EditSubAction::ignore,
+ nsIEditor::eNone);
RefPtr<Element> rootElement = TextEditorRef().GetRoot();
if (!rootElement) {
// We don't even have a body yet, don't insert any bogus nodes at
// this point.
return NS_OK;
}
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -18,19 +18,19 @@
#include "nsISupportsImpl.h"
#include "nsITimer.h"
#include "nsString.h"
#include "nscore.h"
namespace mozilla {
class AutoLockRulesSniffing;
+class EditSubActionInfo;
class HTMLEditor;
class HTMLEditRules;
-class RulesInfo;
namespace dom {
class Selection;
} // namespace dom
/**
* Object that encapsulates HTML text-specific editing rules.
*
* To be a good citizen, edit rules must live by these restrictions:
@@ -71,26 +71,26 @@ public:
TextEditRules();
HTMLEditRules* AsHTMLEditRules();
const HTMLEditRules* AsHTMLEditRules() const;
virtual nsresult Init(TextEditor* aTextEditor);
virtual nsresult SetInitialValue(const nsAString& aValue);
virtual nsresult DetachEditor();
- virtual nsresult BeforeEdit(EditAction aAction,
+ virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection);
- virtual nsresult AfterEdit(EditAction aAction,
+ virtual nsresult AfterEdit(EditSubAction aEditSubAction,
nsIEditor::EDirection aDirection);
virtual nsresult WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
bool* aCancel,
bool* aHandled);
virtual nsresult DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
+ EditSubActionInfo& aInfo,
nsresult aResult);
/**
* Return false if the editor has non-empty text nodes or non-text
* nodes. Otherwise, i.e., there is no meaningful content,
* return true.
*/
virtual bool DocumentIsEmpty();
@@ -150,27 +150,27 @@ protected:
// TextEditRules implementation methods
/**
* Called before inserting text.
* This method may actually inserts text into the editor. Therefore, this
* might cause destroying the editor.
*
- * @param aAction Must be EditAction::insertIMEText or
- * EditAction::insertText.
+ * @param aEditSubAction Must be EditSubAction::insertIMEText or
+ * EditSubAction::insertText.
* @param aCancel Returns true if the operation is canceled.
* @param aHandled Returns true if the edit action is handled.
* @param inString String to be inserted.
* @param outString String actually inserted.
* @param aMaxLength The maximum string length which the editor
* allows to set.
*/
MOZ_MUST_USE nsresult
- WillInsertText(EditAction aAction, bool* aCancel, bool* aHandled,
+ WillInsertText(EditSubAction aEditSubAction, bool* aCancel, bool* aHandled,
const nsAString* inString, nsAString* outString,
int32_t aMaxLength);
/**
* Called before inserting a line break into the editor.
* This method removes selected text if selection isn't collapsed.
* Therefore, this might cause destroying the editor.
*
@@ -494,81 +494,81 @@ protected:
uint32_t mActionNesting;
bool mLockRulesSniffing;
bool mDidExplicitlySetInterline;
// In bidirectional text, delete characters not visually adjacent to the
// caret without moving the caret first.
bool mDeleteBidiImmediately;
bool mIsHTMLEditRules;
// The top level editor action.
- EditAction mTheAction;
+ EditSubAction mTopLevelEditSubAction;
nsCOMPtr<nsITimer> mTimer;
uint32_t mLastStart;
uint32_t mLastLength;
// friends
friend class AutoLockRulesSniffing;
};
/**
* An object to encapsulate any additional info needed to be passed
* to rules system by the editor.
* TODO: This class (almost struct, though) is ugly and its size isn't
* optimized. Should be refined later.
*/
-class RulesInfo final
+class MOZ_STACK_CLASS EditSubActionInfo final
{
public:
- explicit RulesInfo(EditAction aAction)
- : action(aAction)
+ explicit EditSubActionInfo(EditSubAction aEditSubAction)
+ : mEditSubAction(aEditSubAction)
, inString(nullptr)
, outString(nullptr)
, outputFormat(nullptr)
, maxLength(-1)
, flags(0)
, collapsedAction(nsIEditor::eNext)
, stripWrappers(nsIEditor::eStrip)
, bOrdered(false)
, entireList(false)
, bulletType(nullptr)
, alignType(nullptr)
, blockType(nullptr)
{}
- EditAction action;
+ EditSubAction mEditSubAction;
- // EditAction::insertText / EditAction::insertIMEText
+ // EditSubAction::insertText / EditSubAction::insertIMEText
const nsAString* inString;
nsAString* outString;
const nsAString* outputFormat;
int32_t maxLength;
- // EditAction::outputText
+ // EditSubAction::outputText
uint32_t flags;
- // EditAction::deleteSelection
+ // EditSubAction::deleteSelection
nsIEditor::EDirection collapsedAction;
nsIEditor::EStripWrappers stripWrappers;
- // EditAction::removeList
+ // EditSubAction::removeList
bool bOrdered;
- // EditAction::makeList
+ // EditSubAction::makeList
bool entireList;
const nsAString* bulletType;
- // EditAction::align
+ // EditSubAction::align
const nsAString* alignType;
- // EditAction::makeBasicBlock
+ // EditSubAction::makeBasicBlock
const nsAString* blockType;
};
/**
- * Stack based helper class for StartOperation()/EndOperation() sandwich.
+ * Stack based helper class for managing TextEditRules::mLockRluesSniffing.
* This class sets a bool letting us know to ignore any rules sniffing
* that tries to occur reentrantly.
*/
class MOZ_STACK_CLASS AutoLockRulesSniffing final
{
public:
explicit AutoLockRulesSniffing(TextEditRules* aRules)
: mRules(aRules)
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -8,17 +8,17 @@
#include "EditAggregateTransaction.h"
#include "HTMLEditRules.h"
#include "InternetCiter.h"
#include "TextEditUtils.h"
#include "gfxFontUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/EditAction.h"
#include "mozilla/EditorDOMPoint.h"
-#include "mozilla/EditorUtils.h" // AutoPlaceholderBatch, AutoRules
+#include "mozilla/EditorUtils.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/mozalloc.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextEditRules.h"
#include "mozilla/TextComposition.h"
#include "mozilla/TextEvents.h"
#include "mozilla/TextServicesDocument.h"
@@ -663,17 +663,19 @@ TextEditor::DeleteSelectionAsAction(EDir
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
// delete placeholder txns merge.
AutoPlaceholderBatch batch(this, nsGkAtoms::DeleteTxnName);
- AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aDirection);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteSelection,
+ aDirection);
// pre-process
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// If there is an existing selection when an extended delete is requested,
// platforms that use "caret-style" caret positioning collapse the
// selection to the start and then create a new selection.
@@ -696,28 +698,31 @@ TextEditor::DeleteSelectionAsAction(EDir
}
break;
}
default:
break;
}
}
- RulesInfo ruleInfo(EditAction::deleteSelection);
- ruleInfo.collapsedAction = aDirection;
- ruleInfo.stripWrappers = aStripWrappers;
+ EditSubActionInfo subActionInfo(EditSubAction::deleteSelection);
+ subActionInfo.collapsedAction = aDirection;
+ subActionInfo.stripWrappers = aStripWrappers;
bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (!cancel && !handled) {
rv = DeleteSelectionWithTransaction(aDirection, aStripWrappers);
}
if (!cancel) {
// post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
}
return rv;
}
nsresult
TextEditor::DeleteSelectionWithTransaction(EDirection aDirection,
EStripWrappers aStripWrappers)
{
@@ -739,17 +744,19 @@ TextEditor::DeleteSelectionWithTransacti
&deleteCharLength);
if (NS_WARN_IF(!deleteSelectionTransaction)) {
return NS_ERROR_FAILURE;
}
}
RefPtr<CharacterData> deleteCharData =
CharacterData::FromNodeOrNull(deleteNode);
- AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aDirection);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::deleteSelection,
+ aDirection);
if (mRules && mRules->AsHTMLEditRules()) {
if (!deleteNode) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
htmlEditRules->WillDeleteSelection(*selection);
} else if (!deleteCharData) {
RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
htmlEditRules->WillDeleteNode(*selection, *deleteNode);
@@ -936,51 +943,53 @@ TextEditor::InsertTextAsAction(const nsA
{
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- EditAction opID = EditAction::insertText;
+ EditSubAction editSubAction = EditSubAction::insertText;
if (ShouldHandleIMEComposition()) {
- opID = EditAction::insertIMEText;
+ editSubAction = EditSubAction::insertIMEText;
}
AutoPlaceholderBatch batch(this, nullptr);
- AutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, editSubAction, nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
nsAutoString resultString;
- // XXX can we trust instring to outlive ruleInfo,
- // XXX and ruleInfo not to refer to instring in its dtor?
+ // XXX can we trust instring to outlive subActionInfo,
+ // XXX and subActionInfo not to refer to instring in its dtor?
//nsAutoString instring(aStringToInsert);
- RulesInfo ruleInfo(opID);
- ruleInfo.inString = &aStringToInsert;
- ruleInfo.outString = &resultString;
- ruleInfo.maxLength = mMaxTextLength;
+ EditSubActionInfo subActionInfo(editSubAction);
+ subActionInfo.inString = &aStringToInsert;
+ subActionInfo.outString = &resultString;
+ subActionInfo.maxLength = mMaxTextLength;
bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!cancel && !handled) {
// we rely on rules code for now - no default implementation
}
if (cancel) {
return NS_OK;
}
// post-process
- return rules->DidDoAction(selection, &ruleInfo, NS_OK);
+ return rules->DidDoAction(selection, subActionInfo, NS_OK);
}
NS_IMETHODIMP
TextEditor::InsertLineBreak()
{
return InsertParagraphSeparatorAsAction();
}
@@ -990,27 +999,29 @@ TextEditor::InsertParagraphSeparatorAsAc
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertBreak, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertBreak,
+ nsIEditor::eNext);
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
- RulesInfo ruleInfo(EditAction::insertBreak);
- ruleInfo.maxLength = mMaxTextLength;
+ EditSubActionInfo subActionInfo(EditSubAction::insertBreak);
+ subActionInfo.maxLength = mMaxTextLength;
bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (NS_WARN_IF(NS_FAILED(rv))) {
// XXX DidDoAction() won't be called when WillDoAction() returns error.
// Perhaps, we should move the code between WillDoAction() and
// DidDoAction() to a new method and guarantee that DidDoAction() is
// always called after WillDoAction().
return rv;
}
@@ -1067,47 +1078,50 @@ TextEditor::InsertParagraphSeparatorAsAc
selection->SetInterlinePosition(true, IgnoreErrors());
}
}
}
}
if (!cancel) {
// post-process, always called if WillInsertBreak didn't return cancel==true
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
}
return rv;
}
nsresult
TextEditor::SetText(const nsAString& aString)
{
if (NS_WARN_IF(!mRules)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
// delete placeholder txns merge.
AutoPlaceholderBatch batch(this, nullptr);
- AutoRules beginRulesSniffing(this, EditAction::setText, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::setText,
+ nsIEditor::eNext);
// pre-process
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_NULL_POINTER;
}
- RulesInfo ruleInfo(EditAction::setText);
- ruleInfo.inString = &aString;
- ruleInfo.maxLength = mMaxTextLength;
+ EditSubActionInfo subActionInfo(EditSubAction::setText);
+ subActionInfo.inString = &aString;
+ subActionInfo.maxLength = mMaxTextLength;
bool cancel;
bool handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (cancel) {
return NS_OK;
}
if (!handled) {
// We want to select trailing BR node to remove all nodes to replace all,
@@ -1129,17 +1143,17 @@ TextEditor::SetText(const nsAString& aSt
NS_WARNING_ASSERTION(NS_FAILED(rv), "Failed to remove all text");
} else {
rv = InsertTextAsAction(aString);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the new text");
}
}
}
// post-process
- return rules->DidDoAction(selection, &ruleInfo, rv);
+ return rules->DidDoAction(selection, subActionInfo, rv);
}
bool
TextEditor::EnsureComposition(WidgetCompositionEvent& aCompositionEvent)
{
if (mComposition) {
return true;
}
@@ -1210,17 +1224,17 @@ TextEditor::OnCompositionChange(WidgetCo
compositionChangeEventHandlingMarker(mComposition, &aCompsitionChangeEvent);
RefPtr<nsCaret> caretP = presShell->GetCaret();
nsresult rv;
{
AutoPlaceholderBatch batch(this, nsGkAtoms::IMETxnName);
- MOZ_ASSERT(mIsInEditAction,
+ MOZ_ASSERT(mIsInEditSubAction,
"AutoPlaceholderBatch should've notified the observes of before-edit");
rv = InsertTextAsAction(aCompsitionChangeEvent.mData);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to insert new composition string");
if (caretP) {
caretP->SetSelection(selection);
}
@@ -1481,32 +1495,34 @@ TextEditor::Undo(uint32_t aCount)
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
if (NS_WARN_IF(!CanUndo()) || NS_WARN_IF(Destroyed())) {
return NS_ERROR_FAILURE;
}
nsresult rv;
{
- AutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::undo,
+ nsIEditor::eNone);
- RulesInfo ruleInfo(EditAction::undo);
+ EditSubActionInfo subActionInfo(EditSubAction::undo);
RefPtr<Selection> selection = GetSelection();
bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(rv)) {
RefPtr<TransactionManager> transactionManager(mTransactionManager);
for (uint32_t i = 0; i < aCount; ++i) {
rv = transactionManager->Undo();
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
DoAfterUndoTransaction();
}
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
}
}
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
return rv;
}
NS_IMETHODIMP
@@ -1534,32 +1550,34 @@ TextEditor::Redo(uint32_t aCount)
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
if (NS_WARN_IF(!CanRedo()) || NS_WARN_IF(Destroyed())) {
return NS_ERROR_FAILURE;
}
nsresult rv;
{
- AutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::redo,
+ nsIEditor::eNone);
- RulesInfo ruleInfo(EditAction::redo);
+ EditSubActionInfo subActionInfo(EditSubAction::redo);
RefPtr<Selection> selection = GetSelection();
bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(rv)) {
RefPtr<TransactionManager> transactionManager(mTransactionManager);
for (uint32_t i = 0; i < aCount; ++i) {
nsresult rv = transactionManager->Redo();
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
DoAfterRedoTransaction();
}
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
+ rv = rules->DidDoAction(selection, subActionInfo, rv);
}
}
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
return rv;
}
bool
@@ -1731,26 +1749,27 @@ TextEditor::GetAndInitDocEncoder(const n
NS_IMETHODIMP
TextEditor::OutputToString(const nsAString& aFormatType,
uint32_t aFlags,
nsAString& aOutputString)
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- RulesInfo ruleInfo(EditAction::outputText);
- ruleInfo.outString = &aOutputString;
- ruleInfo.flags = aFlags;
- ruleInfo.outputFormat = &aFormatType;
+ EditSubActionInfo subActionInfo(EditSubAction::outputText);
+ subActionInfo.outString = &aOutputString;
+ subActionInfo.flags = aFlags;
+ subActionInfo.outputFormat = &aFormatType;
Selection* selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return NS_ERROR_FAILURE;
}
bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
+ nsresult rv =
+ rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) {
return rv;
}
if (handled) {
// This case will get triggered by password fields or single text node only.
return rv;
}
@@ -1761,16 +1780,17 @@ TextEditor::OutputToString(const nsAStri
}
nsCOMPtr<nsIDocumentEncoder> encoder =
GetAndInitDocEncoder(aFormatType, aFlags, charsetStr);
if (NS_WARN_IF(!encoder)) {
return NS_ERROR_FAILURE;
}
+ // XXX Why don't we call TextEditRules::DidDoAction() here?
return encoder->EncodeToString(aOutputString);
}
NS_IMETHODIMP
TextEditor::InsertTextWithQuotations(const nsAString& aStringToInsert)
{
nsresult rv = InsertTextAsAction(aStringToInsert);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1839,35 +1859,40 @@ TextEditor::InsertAsQuotation(const nsAS
quotedStuff.Append(char16_t('\n'));
}
// get selection
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
AutoPlaceholderBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertText, nsIEditor::eNext);
+ AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
+ *this, EditSubAction::insertText,
+ nsIEditor::eNext);
// give rules a chance to handle or cancel
- RulesInfo ruleInfo(EditAction::insertElement);
+ EditSubActionInfo subActionInfo(EditSubAction::insertElement);
bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
+ rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
if (cancel) {
return NS_OK; // Rules canceled the operation.
}
if (!handled) {
rv = InsertTextAsAction(quotedStuff);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert quoted text");
// XXX Should set *aNodeInserted to the first node inserted
if (aNodeInserted && NS_SUCCEEDED(rv)) {
*aNodeInserted = nullptr;
}
}
+ // XXX Why don't we call TextEditRules::DidDoAction()?
return rv;
}
NS_IMETHODIMP
TextEditor::PasteAsCitedQuotation(const nsAString& aCitation,
int32_t aSelectionType)
{
return NS_ERROR_NOT_IMPLEMENTED;
@@ -1963,48 +1988,51 @@ TextEditor::GetEmbeddedObjects(nsIArray*
if (NS_WARN_IF(!aNodeList)) {
return NS_ERROR_INVALID_ARG;
}
*aNodeList = nullptr;
return NS_OK;
}
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-nsresult
-TextEditor::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
+void
+TextEditor::OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aEditSubAction,
+ nsIEditor::EDirection aDirection)
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
- EditorBase::StartOperation(opID, aDirection); // will set mAction, mDirection
- if (rules) {
- return rules->BeforeEdit(mAction, mDirection);
+ EditorBase::OnStartToHandleTopLevelEditSubAction(aEditSubAction, aDirection);
+ if (!rules) {
+ return;
}
- return NS_OK;
+
+ MOZ_ASSERT(mTopLevelEditSubAction == aEditSubAction);
+ MOZ_ASSERT(mDirection == aDirection);
+ DebugOnly<nsresult> rv =
+ rules->BeforeEdit(mTopLevelEditSubAction, mDirection);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "TextEditRules::BeforeEdit() failed to handle something");
}
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-nsresult
-TextEditor::EndOperation()
+void
+TextEditor::OnEndHandlingTopLevelEditSubAction()
{
// Protect the edit rules object from dying
RefPtr<TextEditRules> rules(mRules);
// post processing
- nsresult rv = rules ? rules->AfterEdit(mAction, mDirection) : NS_OK;
- EditorBase::EndOperation(); // will clear mAction, mDirection
- return rv;
+ DebugOnly<nsresult> rv =
+ rules ? rules->AfterEdit(mTopLevelEditSubAction, mDirection) : NS_OK;
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "TextEditRules::AfterEdit() failed to handle something");
+ EditorBase::OnEndHandlingTopLevelEditSubAction();
+ MOZ_ASSERT(!mTopLevelEditSubAction);
+ MOZ_ASSERT(mDirection == eNone);
}
nsresult
TextEditor::SelectEntireDocument(Selection* aSelection)
{
if (!aSelection || !mRules) {
return NS_ERROR_NULL_POINTER;
}
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -18,17 +18,17 @@
class nsIContent;
class nsIDocumentEncoder;
class nsIOutputStream;
class nsISelectionController;
class nsITransferable;
namespace mozilla {
class AutoEditInitRulesTrigger;
-enum class EditAction : int32_t;
+enum class EditSubAction : int32_t;
namespace dom {
class DragEvent;
class Selection;
} // namespace dom
/**
* The text editor implementation.
@@ -238,28 +238,21 @@ protected: // May be called by friends.
*/
nsresult ExtendSelectionForDelete(Selection* aSelection,
nsIEditor::EDirection* aAction);
static void GetDefaultEditorPrefs(int32_t& aNewLineHandling,
int32_t& aCaretStyle);
protected: // Called by helper classes.
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- virtual nsresult StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection) override;
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- virtual nsresult EndOperation() override;
+ virtual void
+ OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
+ virtual void OnEndHandlingTopLevelEditSubAction() override;
void BeginEditorInit();
nsresult EndEditorInit();
protected: // Shouldn't be used by friend classes
virtual ~TextEditor();
/**
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -106,34 +106,34 @@ mozInlineSpellStatus::mozInlineSpellStat
//
// This is the most complicated case. For changes, we need to compute the
// range of stuff that changed based on the old and new caret positions,
// as well as use a range possibly provided by the editor (start and end,
// which are usually nullptr) to get a range with the union of these.
nsresult
mozInlineSpellStatus::InitForEditorChange(
- EditAction aAction,
+ EditSubAction aEditSubAction,
nsINode* aAnchorNode, uint32_t aAnchorOffset,
nsINode* aPreviousNode, uint32_t aPreviousOffset,
nsINode* aStartNode, uint32_t aStartOffset,
nsINode* aEndNode, uint32_t aEndOffset)
{
if (NS_WARN_IF(!aAnchorNode) || NS_WARN_IF(!aPreviousNode)) {
return NS_ERROR_FAILURE;
}
// save the anchor point as a range so we can find the current word later
mAnchorRange = PositionToCollapsedRange(aAnchorNode, aAnchorOffset);
if (NS_WARN_IF(!mAnchorRange)) {
return NS_ERROR_FAILURE;
}
- bool deleted = aAction == EditAction::deleteSelection;
- if (aAction == EditAction::insertIMEText) {
+ bool deleted = aEditSubAction == EditSubAction::deleteSelection;
+ if (aEditSubAction == EditSubAction::insertIMEText) {
// IME may remove the previous node if it cancels composition when
// there is no text around the composition.
deleted = !aPreviousNode->IsInComposedDoc();
}
if (deleted) {
// Deletes are easy, the range is just the current anchor. We set the range
// to check to be empty, FinishInitOnEvent will fill in the range to be
@@ -169,17 +169,17 @@ mozInlineSpellStatus::InitForEditorChang
aPreviousNode, aPreviousOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// On insert save this range: DoSpellCheck optimizes things in this range.
// Otherwise, just leave this nullptr.
- if (aAction == EditAction::insertText)
+ if (aEditSubAction == EditSubAction::insertText)
mCreatedRange = mRange;
// if we were given a range, we need to expand our range to encompass it
if (aStartNode && aEndNode) {
cmpResult = mRange->ComparePoint(*aStartNode, aStartOffset, errorResult);
if (NS_WARN_IF(errorResult.Failed())) {
return errorResult.StealNSResult();
}
@@ -549,17 +549,17 @@ mozInlineSpellChecker::SpellCheckingStat
mozInlineSpellChecker::mozInlineSpellChecker() :
mNumWordsInSpellSelection(0),
mMaxNumWordsInSpellSelection(250),
mNumPendingSpellChecks(0),
mNumPendingUpdateCurrentDictionary(0),
mDisabledAsyncToken(0),
mNeedsCheckAfterNavigation(false),
mFullSpellCheckScheduled(false),
- mIsListeningToEditActions(false)
+ mIsListeningToEditSubActions(false)
{
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs)
prefs->GetIntPref(kMaxSpellCheckSelectionSize, &mMaxNumWordsInSpellSelection);
mMaxMisspellingsPerCheck = mMaxNumWordsInSpellSelection * 3 / 4;
}
mozInlineSpellChecker::~mozInlineSpellChecker()
@@ -700,17 +700,17 @@ mozInlineSpellChecker::UpdateCanEnableIn
nsresult
mozInlineSpellChecker::RegisterEventListeners()
{
if (NS_WARN_IF(!mTextEditor)) {
return NS_ERROR_FAILURE;
}
- StartToListenToEditActions();
+ StartToListenToEditSubActions();
nsCOMPtr<nsIDocument> doc = mTextEditor->GetDocument();
if (NS_WARN_IF(!doc)) {
return NS_ERROR_FAILURE;
}
doc->AddEventListener(NS_LITERAL_STRING("blur"), this, true, false);
doc->AddEventListener(NS_LITERAL_STRING("click"), this, false, false);
doc->AddEventListener(NS_LITERAL_STRING("keypress"), this, false, false);
@@ -721,17 +721,17 @@ mozInlineSpellChecker::RegisterEventList
nsresult
mozInlineSpellChecker::UnregisterEventListeners()
{
if (NS_WARN_IF(!mTextEditor)) {
return NS_ERROR_FAILURE;
}
- EndListeningToEditActions();
+ EndListeningToEditSubActions();
nsCOMPtr<nsIDocument> doc = mTextEditor->GetDocument();
if (NS_WARN_IF(!doc)) {
return NS_ERROR_FAILURE;
}
doc->RemoveEventListener(NS_LITERAL_STRING("blur"), this, true);
doc->RemoveEventListener(NS_LITERAL_STRING("click"), this, false);
doc->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, false);
@@ -856,32 +856,32 @@ mozInlineSpellChecker::NotifyObservers(c
//
// The start and end positions specify a range for the thing that happened,
// but these are usually nullptr, even when you'd think they would be useful
// because you want the range (for example, pasting). We ignore them in
// this case.
nsresult
mozInlineSpellChecker::SpellCheckAfterEditorChange(
- EditAction aAction, Selection& aSelection,
+ EditSubAction aEditSubAction, Selection& aSelection,
nsINode *aPreviousSelectedNode, uint32_t aPreviousSelectedOffset,
nsINode *aStartNode, uint32_t aStartOffset,
nsINode *aEndNode, uint32_t aEndOffset)
{
nsresult rv;
if (!mSpellCheck)
return NS_OK; // disabling spell checking is not an error
// this means something has changed, and we never check the current word,
// therefore, we should spellcheck for subsequent caret navigations
mNeedsCheckAfterNavigation = true;
// the anchor node is the position of the caret
auto status = MakeUnique<mozInlineSpellStatus>(this);
- rv = status->InitForEditorChange(aAction,
+ rv = status->InitForEditorChange(aEditSubAction,
aSelection.GetAnchorNode(),
aSelection.AnchorOffset(),
aPreviousSelectedNode,
aPreviousSelectedOffset,
aStartNode, aStartOffset,
aEndNode, aEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
rv = ScheduleSpellCheck(Move(status));
@@ -1031,27 +1031,27 @@ mozInlineSpellChecker::IgnoreWords(const
NS_ENSURE_SUCCESS(rv, rv);
return ScheduleSpellCheck(Move(status));
}
void
mozInlineSpellChecker::DidSplitNode(nsINode* aExistingRightNode,
nsINode* aNewLeftNode)
{
- if (!mIsListeningToEditActions) {
+ if (!mIsListeningToEditSubActions) {
return;
}
SpellCheckBetweenNodes(aNewLeftNode, 0, aNewLeftNode, 0);
}
void
mozInlineSpellChecker::DidJoinNodes(nsINode& aLeftNode,
nsINode& aRightNode)
{
- if (!mIsListeningToEditActions) {
+ if (!mIsListeningToEditSubActions) {
return;
}
SpellCheckBetweenNodes(&aRightNode, 0, &aRightNode, 0);
}
// mozInlineSpellChecker::MakeSpellCheckRange
//
// Given begin and end positions, this function constructs a range as
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -18,29 +18,29 @@ class mozInlineSpellWordUtil;
class mozInlineSpellChecker;
class mozISpellI18NUtil;
class mozInlineSpellResume;
class UpdateCurrentDictionaryCallback;
namespace mozilla {
class EditorSpellCheck;
class TextEditor;
-enum class EditAction : int32_t;
+enum class EditSubAction : int32_t;
namespace dom {
class Event;
} // namespace dom
} // namespace mozilla
class mozInlineSpellStatus
{
public:
explicit mozInlineSpellStatus(mozInlineSpellChecker* aSpellChecker);
- nsresult InitForEditorChange(mozilla::EditAction aAction,
+ nsresult InitForEditorChange(mozilla::EditSubAction aEditSubAction,
nsINode* aAnchorNode, uint32_t aAnchorOffset,
nsINode* aPreviousNode, uint32_t aPreviousOffset,
nsINode* aStartNode, uint32_t aStartOffset,
nsINode* aEndNode, uint32_t aEndOffset);
nsresult InitForNavigation(bool aForceCheck, int32_t aNewPositionOffset,
nsINode* aOldAnchorNode, uint32_t aOldAnchorOffset,
nsINode* aNewAnchorNode, uint32_t aNewAnchorOffset,
bool* aContinue);
@@ -175,17 +175,17 @@ private:
bool mNeedsCheckAfterNavigation;
// Set when we have a pending mozInlineSpellResume which will check
// the whole document.
bool mFullSpellCheckScheduled;
// Set to true when this instance needs to listen to edit actions of
// the editor.
- bool mIsListeningToEditActions;
+ bool mIsListeningToEditSubActions;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIINLINESPELLCHECKER
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozInlineSpellChecker, nsIDOMEventListener)
@@ -252,17 +252,17 @@ public:
nsresult ResumeCheck(mozilla::UniquePtr<mozInlineSpellStatus>&& aStatus);
// Those methods are called when mTextEditor splits a node or joins the
// given nodes.
void DidSplitNode(nsINode* aExistingRightNode, nsINode* aNewLeftNode);
void DidJoinNodes(nsINode& aRightNode, nsINode& aLeftNode);
- nsresult SpellCheckAfterEditorChange(mozilla::EditAction aAction,
+ nsresult SpellCheckAfterEditorChange(mozilla::EditSubAction aEditSubAction,
mozilla::dom::Selection& aSelection,
nsINode* aPreviousSelectedNode,
uint32_t aPreviousSelectedOffset,
nsINode* aStartNode,
uint32_t aStartOffset,
nsINode* aEndNode,
uint32_t aEndOffset);
@@ -274,13 +274,13 @@ protected:
nsresult CurrentDictionaryUpdated();
// track the number of pending spell checks and async operations that may lead
// to spell checks, notifying observers accordingly
void ChangeNumPendingSpellChecks(int32_t aDelta,
mozilla::TextEditor* aTextEditor = nullptr);
void NotifyObservers(const char* aTopic, mozilla::TextEditor* aTextEditor);
- void StartToListenToEditActions() { mIsListeningToEditActions = true; }
- void EndListeningToEditActions() { mIsListeningToEditActions = false; }
+ void StartToListenToEditSubActions() { mIsListeningToEditSubActions = true; }
+ void EndListeningToEditSubActions() { mIsListeningToEditSubActions = false; }
};
#endif // #ifndef mozilla_mozInlineSpellChecker_h