summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/HTMLEditRules.h
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor/HTMLEditRules.h')
-rw-r--r--editor/libeditor/HTMLEditRules.h377
1 files changed, 377 insertions, 0 deletions
diff --git a/editor/libeditor/HTMLEditRules.h b/editor/libeditor/HTMLEditRules.h
new file mode 100644
index 000000000..40c5e2afd
--- /dev/null
+++ b/editor/libeditor/HTMLEditRules.h
@@ -0,0 +1,377 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef HTMLEditRules_h
+#define HTMLEditRules_h
+
+#include "TypeInState.h"
+#include "mozilla/SelectionState.h"
+#include "mozilla/TextEditRules.h"
+#include "nsCOMPtr.h"
+#include "nsIEditActionListener.h"
+#include "nsIEditor.h"
+#include "nsIHTMLEditor.h"
+#include "nsISupportsImpl.h"
+#include "nsTArray.h"
+#include "nscore.h"
+
+class nsIAtom;
+class nsIDOMCharacterData;
+class nsIDOMDocument;
+class nsIDOMElement;
+class nsIDOMNode;
+class nsIEditor;
+class nsINode;
+class nsRange;
+
+namespace mozilla {
+
+class HTMLEditor;
+class RulesInfo;
+class TextEditor;
+struct EditorDOMPoint;
+namespace dom {
+class Element;
+class Selection;
+} // namespace dom
+
+struct StyleCache final : public PropItem
+{
+ bool mPresent;
+
+ StyleCache()
+ : PropItem()
+ , mPresent(false)
+ {
+ MOZ_COUNT_CTOR(StyleCache);
+ }
+
+ StyleCache(nsIAtom* aTag,
+ const nsAString& aAttr,
+ const nsAString& aValue)
+ : PropItem(aTag, aAttr, aValue)
+ , mPresent(false)
+ {
+ MOZ_COUNT_CTOR(StyleCache);
+ }
+
+ ~StyleCache()
+ {
+ MOZ_COUNT_DTOR(StyleCache);
+ }
+};
+
+#define SIZE_STYLE_TABLE 19
+
+class HTMLEditRules : public TextEditRules
+ , public nsIEditActionListener
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditRules, TextEditRules)
+
+ HTMLEditRules();
+
+ // nsIEditRules methods
+ NS_IMETHOD Init(TextEditor* aTextEditor) override;
+ NS_IMETHOD DetachEditor() override;
+ NS_IMETHOD BeforeEdit(EditAction action,
+ nsIEditor::EDirection aDirection) override;
+ NS_IMETHOD AfterEdit(EditAction action,
+ nsIEditor::EDirection aDirection) override;
+ NS_IMETHOD WillDoAction(Selection* aSelection, RulesInfo* aInfo,
+ bool* aCancel, bool* aHandled) override;
+ NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
+ nsresult aResult) override;
+ NS_IMETHOD 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);
+ nsresult GetParagraphState(bool* aMixed, nsAString& outFormat);
+ nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode);
+
+ // nsIEditActionListener methods
+
+ NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode* aParent,
+ int32_t aPosition) override;
+ NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode* aNode,
+ nsIDOMNode* aParent, int32_t aPosition,
+ nsresult aResult) override;
+ NS_IMETHOD WillInsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent,
+ int32_t aPosition) override;
+ NS_IMETHOD DidInsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent,
+ int32_t aPosition, nsresult aResult) override;
+ NS_IMETHOD WillDeleteNode(nsIDOMNode* aChild) override;
+ NS_IMETHOD DidDeleteNode(nsIDOMNode* aChild, nsresult aResult) override;
+ NS_IMETHOD WillSplitNode(nsIDOMNode* aExistingRightNode,
+ int32_t aOffset) override;
+ NS_IMETHOD DidSplitNode(nsIDOMNode* aExistingRightNode, int32_t aOffset,
+ nsIDOMNode* aNewLeftNode, nsresult aResult) override;
+ NS_IMETHOD WillJoinNodes(nsIDOMNode* aLeftNode, nsIDOMNode* aRightNode,
+ nsIDOMNode* aParent) override;
+ NS_IMETHOD DidJoinNodes(nsIDOMNode* aLeftNode, nsIDOMNode* aRightNode,
+ nsIDOMNode* aParent, nsresult aResult) override;
+ NS_IMETHOD WillInsertText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
+ const nsAString &aString) override;
+ NS_IMETHOD DidInsertText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
+ const nsAString &aString, nsresult aResult) override;
+ NS_IMETHOD WillDeleteText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
+ int32_t aLength) override;
+ NS_IMETHOD DidDeleteText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
+ int32_t aLength, nsresult aResult) override;
+ NS_IMETHOD WillDeleteSelection(nsISelection* aSelection) override;
+ NS_IMETHOD DidDeleteSelection(nsISelection* aSelection) override;
+ void DeleteNodeIfCollapsedText(nsINode& aNode);
+
+protected:
+ virtual ~HTMLEditRules();
+
+ enum RulesEndpoint
+ {
+ kStart,
+ kEnd
+ };
+
+ void InitFields();
+
+ void WillInsert(Selection& aSelection, bool* aCancel);
+ nsresult WillInsertText(EditAction aAction,
+ Selection* aSelection,
+ bool* aCancel,
+ bool* aHandled,
+ const nsAString* inString,
+ nsAString* outString,
+ int32_t aMaxLength);
+ nsresult WillLoadHTML(Selection* aSelection, bool* aCancel);
+ nsresult WillInsertBreak(Selection& aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult StandardBreakImpl(nsINode& aNode, int32_t aOffset,
+ Selection& aSelection);
+ nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
+ nsresult SplitMailCites(Selection* aSelection, bool* aHandled);
+ nsresult WillDeleteSelection(Selection* aSelection,
+ nsIEditor::EDirection aAction,
+ nsIEditor::EStripWrappers aStripWrappers,
+ bool* aCancel, bool* aHandled);
+ nsresult DidDeleteSelection(Selection* aSelection,
+ nsIEditor::EDirection aDir,
+ nsresult aResult);
+ nsresult InsertBRIfNeeded(Selection* aSelection);
+ mozilla::EditorDOMPoint GetGoodSelPointForNode(nsINode& aNode,
+ nsIEditor::EDirection aAction);
+ nsresult JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
+ bool* aCanceled);
+ nsresult MoveBlock(Element& aLeftBlock, Element& aRightBlock,
+ int32_t aLeftOffset, int32_t aRightOffset);
+ nsresult MoveNodeSmart(nsIContent& aNode, Element& aDestElement,
+ int32_t* aOffset);
+ nsresult MoveContents(Element& aElement, Element& aDestElement,
+ int32_t* aOffset);
+ nsresult DeleteNonTableElements(nsINode* aNode);
+ nsresult WillMakeList(Selection* aSelection,
+ const nsAString* aListType,
+ bool aEntireList,
+ const nsAString* aBulletType,
+ bool* aCancel, bool* aHandled,
+ const nsAString* aItemType = nullptr);
+ nsresult WillRemoveList(Selection* aSelection, bool aOrdered, bool* aCancel,
+ bool* aHandled);
+ nsresult WillIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
+ nsresult WillCSSIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
+ nsresult WillHTMLIndent(Selection* aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult WillOutdent(Selection& aSelection, bool* aCancel, bool* aHandled);
+ nsresult WillAlign(Selection& aSelection, const nsAString& aAlignType,
+ bool* aCancel, bool* aHandled);
+ nsresult WillAbsolutePosition(Selection& aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult WillRemoveAbsolutePosition(Selection* aSelection, bool* aCancel,
+ bool* aHandled);
+ nsresult WillRelativeChangeZIndex(Selection* aSelection, int32_t aChange,
+ bool* aCancel, bool* aHandled);
+ nsresult WillMakeDefListItem(Selection* aSelection,
+ const nsAString* aBlockType, bool aEntireList,
+ bool* aCancel, bool* aHandled);
+ nsresult WillMakeBasicBlock(Selection& aSelection,
+ const nsAString& aBlockType,
+ bool* aCancel, bool* aHandled);
+ nsresult DidMakeBasicBlock(Selection* aSelection, RulesInfo* aInfo,
+ nsresult aResult);
+ nsresult DidAbsolutePosition();
+ nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType);
+ nsresult AlignBlockContents(nsIDOMNode* aNode, const nsAString* alignType);
+ nsresult AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
+ nsINode* aNode);
+ nsresult GetFormatString(nsIDOMNode* aNode, nsAString &outFormat);
+ enum class Lists { no, yes };
+ enum class Tables { no, yes };
+ void GetInnerContent(nsINode& aNode,
+ nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
+ int32_t* aIndex, Lists aLists = Lists::yes,
+ Tables aTables = Tables::yes);
+ Element* IsInListItem(nsINode* aNode);
+ nsresult ReturnInHeader(Selection& aSelection, Element& aHeader,
+ nsINode& aNode, int32_t aOffset);
+ nsresult ReturnInParagraph(Selection* aSelection, nsIDOMNode* aHeader,
+ nsIDOMNode* aTextNode, int32_t aOffset,
+ bool* aCancel, bool* aHandled);
+ nsresult SplitParagraph(nsIDOMNode* aPara,
+ nsIContent* aBRNode,
+ Selection* aSelection,
+ nsCOMPtr<nsIDOMNode>* aSelNode,
+ int32_t* aOffset);
+ nsresult ReturnInListItem(Selection& aSelection, Element& aHeader,
+ nsINode& aNode, int32_t aOffset);
+ nsresult AfterEditInner(EditAction action,
+ nsIEditor::EDirection aDirection);
+ nsresult RemovePartOfBlock(Element& aBlock, nsIContent& aStartChild,
+ nsIContent& aEndChild);
+ void SplitBlock(Element& aBlock,
+ nsIContent& aStartChild,
+ nsIContent& aEndChild,
+ nsIContent** aOutLeftNode = nullptr,
+ nsIContent** aOutRightNode = nullptr,
+ nsIContent** aOutMiddleNode = nullptr);
+ nsresult OutdentPartOfBlock(Element& aBlock,
+ nsIContent& aStartChild,
+ nsIContent& aEndChild,
+ bool aIsBlockIndentedWithCSS,
+ nsIContent** aOutLeftNode,
+ nsIContent** aOutRightNode);
+
+ nsresult ConvertListType(Element* aList, Element** aOutList,
+ nsIAtom* aListType, nsIAtom* aItemType);
+
+ nsresult CreateStyleForInsertText(Selection& aSelection, nsIDocument& aDoc);
+ enum class MozBRCounts { yes, no };
+ nsresult IsEmptyBlock(Element& aNode, bool* aOutIsEmptyBlock,
+ MozBRCounts aMozBRCounts = MozBRCounts::yes);
+ nsresult CheckForEmptyBlock(nsINode* aStartNode, Element* aBodyNode,
+ Selection* aSelection,
+ nsIEditor::EDirection aAction, bool* aHandled);
+ enum class BRLocation { beforeBlock, blockEnd };
+ Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
+ int32_t aOffset = 0);
+ nsresult ExpandSelectionForDeletion(Selection& aSelection);
+ bool IsFirstNode(nsIDOMNode* aNode);
+ bool IsLastNode(nsIDOMNode* aNode);
+ nsresult NormalizeSelection(Selection* aSelection);
+ void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
+ int32_t aOffset, EditAction actionID,
+ nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
+ void GetPromotedRanges(Selection& aSelection,
+ nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
+ EditAction inOperationType);
+ void PromoteRange(nsRange& aRange, EditAction inOperationType);
+ enum class TouchContent { no, yes };
+ nsresult GetNodesForOperation(
+ nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
+ nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
+ EditAction aOperationType,
+ TouchContent aTouchContent = TouchContent::yes);
+ void GetChildNodesForOperation(
+ nsINode& aNode,
+ nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
+ nsresult GetNodesFromPoint(EditorDOMPoint aPoint,
+ EditAction aOperation,
+ nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
+ TouchContent aTouchContent);
+ nsresult GetNodesFromSelection(
+ Selection& aSelection,
+ EditAction aOperation,
+ nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
+ TouchContent aTouchContent = TouchContent::yes);
+ enum class EntireList { no, yes };
+ nsresult GetListActionNodes(
+ nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
+ EntireList aEntireList,
+ TouchContent aTouchContent = TouchContent::yes);
+ void GetDefinitionListItemTypes(Element* aElement, bool* aDT, bool* aDD);
+ nsresult GetParagraphFormatNodes(
+ nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
+ TouchContent aTouchContent = TouchContent::yes);
+ void LookInsideDivBQandList(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
+ nsresult BustUpInlinesAtRangeEndpoints(RangeItem& inRange);
+ nsresult BustUpInlinesAtBRs(
+ nsIContent& aNode,
+ nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
+ nsIContent* GetHighestInlineParent(nsINode& aNode);
+ void MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
+ nsTArray<bool>& aTransitionArray);
+ nsresult RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
+ nsresult ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
+ nsIAtom& aBlockTag);
+ nsresult MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
+ nsresult SplitAsNeeded(nsIAtom& aTag, OwningNonNull<nsINode>& inOutParent,
+ int32_t& inOutOffset);
+ nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
+ int32_t& inOutOffset);
+ nsresult AddTerminatingBR(nsIDOMNode *aBlock);
+ EditorDOMPoint JoinNodesSmart(nsIContent& aNodeLeft,
+ nsIContent& aNodeRight);
+ Element* GetTopEnclosingMailCite(nsINode& aNode);
+ nsresult PopListItem(nsIDOMNode* aListItem, bool* aOutOfList);
+ nsresult RemoveListStructure(Element& aList);
+ nsresult CacheInlineStyles(nsIDOMNode* aNode);
+ nsresult ReapplyCachedStyles();
+ void ClearCachedStyles();
+ void AdjustSpecialBreaks();
+ nsresult AdjustWhitespace(Selection* aSelection);
+ nsresult PinSelectionToNewBlock(Selection* aSelection);
+ void CheckInterlinePosition(Selection& aSelection);
+ nsresult AdjustSelection(Selection* aSelection,
+ nsIEditor::EDirection aAction);
+ nsresult FindNearSelectableNode(nsIDOMNode* aSelNode,
+ int32_t aSelOffset,
+ nsIEditor::EDirection& aDirection,
+ nsCOMPtr<nsIDOMNode>* outSelectableNode);
+ /**
+ * Returns true if aNode1 or aNode2 or both is the descendant of some type of
+ * table element, but their nearest table element ancestors differ. "Table
+ * element" here includes not just <table> but also <td>, <tbody>, <tr>, etc.
+ * The nodes count as being their own descendants for this purpose, so a
+ * table element is its own nearest table element ancestor.
+ */
+ bool InDifferentTableElements(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
+ bool InDifferentTableElements(nsINode* aNode1, nsINode* aNode2);
+ nsresult RemoveEmptyNodes();
+ nsresult SelectionEndpointInNode(nsINode* aNode, bool* aResult);
+ nsresult UpdateDocChangeRange(nsRange* aRange);
+ nsresult ConfirmSelectionInBody();
+ nsresult InsertMozBRIfNeeded(nsINode& aNode);
+ bool IsEmptyInline(nsINode& aNode);
+ bool ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& arrayOfNodes);
+ nsresult RemoveAlignment(nsIDOMNode* aNode, const nsAString& aAlignType,
+ bool aChildrenOnly);
+ nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode, bool aStarts);
+ enum class ContentsOnly { no, yes };
+ nsresult AlignBlock(Element& aElement,
+ const nsAString& aAlignType, ContentsOnly aContentsOnly);
+ enum class Change { minus, plus };
+ nsresult ChangeIndentation(Element& aElement, Change aChange);
+ void DocumentModifiedWorker();
+
+protected:
+ HTMLEditor* mHTMLEditor;
+ RefPtr<nsRange> mDocChangeRange;
+ bool mListenerEnabled;
+ bool mReturnInEmptyLIKillsList;
+ bool mDidDeleteSelection;
+ bool mDidRangedDelete;
+ bool mRestoreContentEditableCount;
+ RefPtr<nsRange> mUtilRange;
+ // Need to remember an int across willJoin/didJoin...
+ uint32_t mJoinOffset;
+ nsCOMPtr<Element> mNewBlock;
+ RefPtr<RangeItem> mRangeItem;
+ StyleCache mCachedStyles[SIZE_STYLE_TABLE];
+};
+
+} // namespace mozilla
+
+#endif // #ifndef HTMLEditRules_h
+