michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsHTMLEditRules_h__ michael@0: #define nsHTMLEditRules_h__ michael@0: michael@0: #include "TypeInState.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsEditor.h" michael@0: #include "nsIEditActionListener.h" michael@0: #include "nsIEditor.h" michael@0: #include "nsIHTMLEditor.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsSelectionState.h" michael@0: #include "nsTArray.h" michael@0: #include "nsTextEditRules.h" michael@0: #include "nscore.h" michael@0: michael@0: class nsHTMLEditor; michael@0: class nsIAtom; michael@0: class nsIDOMCharacterData; michael@0: class nsIDOMDocument; michael@0: class nsIDOMElement; michael@0: class nsIDOMNode; michael@0: class nsIDOMRange; michael@0: class nsIEditor; michael@0: class nsINode; michael@0: class nsISelection; michael@0: class nsPlaintextEditor; michael@0: class nsRange; michael@0: class nsRulesInfo; michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class Element; michael@0: class Selection; michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: struct DOMPoint; michael@0: template class nsCOMArray; michael@0: michael@0: struct StyleCache : public PropItem michael@0: { michael@0: bool mPresent; michael@0: michael@0: StyleCache() : PropItem(), mPresent(false) { michael@0: MOZ_COUNT_CTOR(StyleCache); michael@0: } michael@0: michael@0: StyleCache(nsIAtom *aTag, const nsAString &aAttr, const nsAString &aValue) : michael@0: PropItem(aTag, aAttr, aValue), mPresent(false) { michael@0: MOZ_COUNT_CTOR(StyleCache); michael@0: } michael@0: michael@0: ~StyleCache() { michael@0: MOZ_COUNT_DTOR(StyleCache); michael@0: } michael@0: }; michael@0: michael@0: michael@0: #define SIZE_STYLE_TABLE 19 michael@0: michael@0: class nsHTMLEditRules : public nsTextEditRules, public nsIEditActionListener michael@0: { michael@0: public: michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: nsHTMLEditRules(); michael@0: virtual ~nsHTMLEditRules(); michael@0: michael@0: michael@0: // nsIEditRules methods michael@0: NS_IMETHOD Init(nsPlaintextEditor *aEditor); michael@0: NS_IMETHOD DetachEditor(); michael@0: NS_IMETHOD BeforeEdit(EditAction action, michael@0: nsIEditor::EDirection aDirection); michael@0: NS_IMETHOD AfterEdit(EditAction action, michael@0: nsIEditor::EDirection aDirection); michael@0: NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection, nsRulesInfo* aInfo, michael@0: bool* aCancel, bool* aHandled); michael@0: NS_IMETHOD DidDoAction(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); michael@0: NS_IMETHOD DocumentModified(); michael@0: michael@0: nsresult GetListState(bool *aMixed, bool *aOL, bool *aUL, bool *aDL); michael@0: nsresult GetListItemState(bool *aMixed, bool *aLI, bool *aDT, bool *aDD); michael@0: nsresult GetIndentState(bool *aCanIndent, bool *aCanOutdent); michael@0: nsresult GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign); michael@0: nsresult GetParagraphState(bool *aMixed, nsAString &outFormat); michael@0: nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode); michael@0: michael@0: // nsIEditActionListener methods michael@0: michael@0: NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, int32_t aPosition); michael@0: NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aPosition, nsresult aResult); michael@0: NS_IMETHOD WillInsertNode(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aPosition); michael@0: NS_IMETHOD DidInsertNode(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aPosition, nsresult aResult); michael@0: NS_IMETHOD WillDeleteNode(nsIDOMNode *aChild); michael@0: NS_IMETHOD DidDeleteNode(nsIDOMNode *aChild, nsresult aResult); michael@0: NS_IMETHOD WillSplitNode(nsIDOMNode *aExistingRightNode, int32_t aOffset); michael@0: NS_IMETHOD DidSplitNode(nsIDOMNode *aExistingRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode, nsresult aResult); michael@0: NS_IMETHOD WillJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMNode *aParent); michael@0: NS_IMETHOD DidJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMNode *aParent, nsresult aResult); michael@0: NS_IMETHOD WillInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString); michael@0: NS_IMETHOD DidInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString, nsresult aResult); michael@0: NS_IMETHOD WillDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength); michael@0: NS_IMETHOD DidDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength, nsresult aResult); michael@0: NS_IMETHOD WillDeleteSelection(nsISelection *aSelection); michael@0: NS_IMETHOD DidDeleteSelection(nsISelection *aSelection); michael@0: michael@0: protected: michael@0: michael@0: enum RulesEndpoint michael@0: { michael@0: kStart, michael@0: kEnd michael@0: }; michael@0: michael@0: enum BRLocation michael@0: { michael@0: kBeforeBlock, michael@0: kBlockEnd michael@0: }; michael@0: michael@0: void InitFields(); michael@0: michael@0: // nsHTMLEditRules implementation methods michael@0: nsresult WillInsert(nsISelection *aSelection, bool *aCancel); michael@0: nsresult WillInsertText( EditAction aAction, michael@0: mozilla::dom::Selection* aSelection, michael@0: bool *aCancel, michael@0: bool *aHandled, michael@0: const nsAString *inString, michael@0: nsAString *outString, michael@0: int32_t aMaxLength); michael@0: nsresult WillLoadHTML(nsISelection *aSelection, bool *aCancel); michael@0: nsresult WillInsertBreak(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult StandardBreakImpl(nsIDOMNode *aNode, int32_t aOffset, nsISelection *aSelection); michael@0: nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); michael@0: nsresult SplitMailCites(nsISelection *aSelection, bool aPlaintext, bool *aHandled); michael@0: nsresult WillDeleteSelection(mozilla::dom::Selection* aSelection, michael@0: nsIEditor::EDirection aAction, michael@0: nsIEditor::EStripWrappers aStripWrappers, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult DidDeleteSelection(nsISelection *aSelection, michael@0: nsIEditor::EDirection aDir, michael@0: nsresult aResult); michael@0: nsresult InsertBRIfNeeded(nsISelection *aSelection); michael@0: nsresult GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection aAction, michael@0: nsCOMPtr *outSelNode, int32_t *outSelOffset); michael@0: nsresult JoinBlocks(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, bool *aCanceled); michael@0: nsresult MoveBlock(nsIDOMNode *aLeft, nsIDOMNode *aRight, int32_t aLeftOffset, int32_t aRightOffset); michael@0: nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset); michael@0: nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, int32_t *aOffset); michael@0: nsresult DeleteNonTableElements(nsINode* aNode); michael@0: nsresult WillMakeList(mozilla::dom::Selection* aSelection, michael@0: const nsAString* aListType, michael@0: bool aEntireList, michael@0: const nsAString* aBulletType, michael@0: bool* aCancel, bool* aHandled, michael@0: const nsAString* aItemType = nullptr); michael@0: nsresult WillRemoveList(mozilla::dom::Selection* aSelection, michael@0: bool aOrdered, bool* aCancel, bool* aHandled); michael@0: nsresult WillIndent(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillCSSIndent(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillHTMLIndent(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillOutdent(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillAlign(mozilla::dom::Selection* aSelection, michael@0: const nsAString* alignType, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillAbsolutePosition(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillRemoveAbsolutePosition(mozilla::dom::Selection* aSelection, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillRelativeChangeZIndex(mozilla::dom::Selection* aSelection, michael@0: int32_t aChange, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillMakeDefListItem(mozilla::dom::Selection* aSelection, michael@0: const nsAString* aBlockType, bool aEntireList, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult WillMakeBasicBlock(mozilla::dom::Selection* aSelection, michael@0: const nsAString* aBlockType, michael@0: bool* aCancel, bool* aHandled); michael@0: nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); michael@0: nsresult DidAbsolutePosition(); michael@0: nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType); michael@0: nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType); michael@0: nsresult AppendInnerFormatNodes(nsCOMArray& aArray, michael@0: nsINode* aNode); michael@0: nsresult AppendInnerFormatNodes(nsCOMArray& aArray, michael@0: nsIDOMNode *aNode); michael@0: nsresult GetFormatString(nsIDOMNode *aNode, nsAString &outFormat); michael@0: nsresult GetInnerContent(nsIDOMNode *aNode, nsCOMArray& outArrayOfNodes, int32_t *aIndex, bool aList = true, bool aTble = true); michael@0: already_AddRefed IsInListItem(nsIDOMNode* aNode); michael@0: nsINode* IsInListItem(nsINode* aNode); michael@0: nsresult ReturnInHeader(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, int32_t aOffset); michael@0: nsresult ReturnInParagraph(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, int32_t aOffset, bool *aCancel, bool *aHandled); michael@0: nsresult SplitParagraph(nsIDOMNode *aPara, michael@0: nsIDOMNode *aBRNode, michael@0: nsISelection *aSelection, michael@0: nsCOMPtr *aSelNode, michael@0: int32_t *aOffset); michael@0: nsresult ReturnInListItem(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, int32_t aOffset); michael@0: nsresult AfterEditInner(EditAction action, michael@0: nsIEditor::EDirection aDirection); michael@0: nsresult RemovePartOfBlock(nsIDOMNode *aBlock, michael@0: nsIDOMNode *aStartChild, michael@0: nsIDOMNode *aEndChild, michael@0: nsCOMPtr *aLeftNode = 0, michael@0: nsCOMPtr *aRightNode = 0); michael@0: nsresult SplitBlock(nsIDOMNode *aBlock, michael@0: nsIDOMNode *aStartChild, michael@0: nsIDOMNode *aEndChild, michael@0: nsCOMPtr *aLeftNode = 0, michael@0: nsCOMPtr *aRightNode = 0, michael@0: nsCOMPtr *aMiddleNode = 0); michael@0: nsresult OutdentPartOfBlock(nsIDOMNode *aBlock, michael@0: nsIDOMNode *aStartChild, michael@0: nsIDOMNode *aEndChild, michael@0: bool aIsBlockIndentedWithCSS, michael@0: nsCOMPtr *aLeftNode = 0, michael@0: nsCOMPtr *aRightNode = 0); michael@0: michael@0: nsresult ConvertListType(nsIDOMNode* aList, michael@0: nsCOMPtr* outList, michael@0: nsIAtom* aListType, michael@0: nsIAtom* aItemType); michael@0: nsresult ConvertListType(nsINode* aList, michael@0: mozilla::dom::Element** aOutList, michael@0: nsIAtom* aListType, michael@0: nsIAtom* aItemType); michael@0: michael@0: nsresult CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocument *aDoc); michael@0: nsresult IsEmptyBlock(nsIDOMNode *aNode, michael@0: bool *outIsEmptyBlock, michael@0: bool aMozBRDoesntCount = false, michael@0: bool aListItemsNotEmpty = false); michael@0: nsresult CheckForEmptyBlock(nsIDOMNode *aStartNode, michael@0: nsIDOMNode *aBodyNode, michael@0: nsISelection *aSelection, michael@0: bool *aHandled); michael@0: nsresult CheckForInvisibleBR(nsIDOMNode *aBlock, nsHTMLEditRules::BRLocation aWhere, michael@0: nsCOMPtr *outBRNode, int32_t aOffset=0); michael@0: nsresult ExpandSelectionForDeletion(nsISelection *aSelection); michael@0: bool IsFirstNode(nsIDOMNode *aNode); michael@0: bool IsLastNode(nsIDOMNode *aNode); michael@0: nsresult NormalizeSelection(nsISelection *inSelection); michael@0: void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode, michael@0: int32_t aOffset, EditAction actionID, michael@0: nsCOMPtr* outNode, int32_t* outOffset); michael@0: nsresult GetPromotedRanges(nsISelection *inSelection, michael@0: nsCOMArray &outArrayOfRanges, michael@0: EditAction inOperationType); michael@0: nsresult PromoteRange(nsIDOMRange *inRange, michael@0: EditAction inOperationType); michael@0: nsresult GetNodesForOperation(nsCOMArray& inArrayOfRanges, michael@0: nsCOMArray& outArrayOfNodes, michael@0: EditAction inOperationType, michael@0: bool aDontTouchContent=false); michael@0: nsresult GetChildNodesForOperation(nsIDOMNode *inNode, michael@0: nsCOMArray& outArrayOfNodes); michael@0: nsresult GetNodesFromPoint(DOMPoint point, michael@0: EditAction operation, michael@0: nsCOMArray& arrayOfNodes, michael@0: bool dontTouchContent); michael@0: nsresult GetNodesFromSelection(nsISelection *selection, michael@0: EditAction operation, michael@0: nsCOMArray& arrayOfNodes, michael@0: bool aDontTouchContent=false); michael@0: nsresult GetListActionNodes(nsCOMArray &outArrayOfNodes, bool aEntireList, bool aDontTouchContent=false); michael@0: void GetDefinitionListItemTypes(mozilla::dom::Element* aElement, bool* aDT, bool* aDD); michael@0: nsresult GetParagraphFormatNodes(nsCOMArray& outArrayOfNodes, bool aDontTouchContent=false); michael@0: nsresult LookInsideDivBQandList(nsCOMArray& aNodeArray); michael@0: nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange); michael@0: nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode, michael@0: nsCOMArray& outArrayOfNodes); michael@0: nsCOMPtr GetHighestInlineParent(nsIDOMNode* aNode); michael@0: nsresult MakeTransitionList(nsCOMArray& inArrayOfNodes, michael@0: nsTArray &inTransitionArray); michael@0: nsresult RemoveBlockStyle(nsCOMArray& arrayOfNodes); michael@0: nsresult ApplyBlockStyle(nsCOMArray& arrayOfNodes, const nsAString *aBlockTag); michael@0: nsresult MakeBlockquote(nsCOMArray& arrayOfNodes); michael@0: nsresult SplitAsNeeded(const nsAString *aTag, nsCOMPtr *inOutParent, int32_t *inOutOffset); michael@0: nsresult AddTerminatingBR(nsIDOMNode *aBlock); michael@0: nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft, michael@0: nsIDOMNode *aNodeRight, michael@0: nsCOMPtr *aOutMergeParent, michael@0: int32_t *aOutMergeOffset); michael@0: nsresult GetTopEnclosingMailCite(nsIDOMNode *aNode, nsCOMPtr *aOutCiteNode, bool aPlaintext); michael@0: nsresult PopListItem(nsIDOMNode *aListItem, bool *aOutOfList); michael@0: nsresult RemoveListStructure(nsIDOMNode *aList); michael@0: nsresult CacheInlineStyles(nsIDOMNode *aNode); michael@0: nsresult ReapplyCachedStyles(); michael@0: void ClearCachedStyles(); michael@0: nsresult AdjustSpecialBreaks(bool aSafeToAskFrames = false); michael@0: nsresult AdjustWhitespace(nsISelection *aSelection); michael@0: nsresult PinSelectionToNewBlock(nsISelection *aSelection); michael@0: nsresult CheckInterlinePosition(nsISelection *aSelection); michael@0: nsresult AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction); michael@0: nsresult FindNearSelectableNode(nsIDOMNode *aSelNode, michael@0: int32_t aSelOffset, michael@0: nsIEditor::EDirection &aDirection, michael@0: nsCOMPtr *outSelectableNode); michael@0: /** michael@0: * Returns true if aNode1 or aNode2 or both is the descendant of some type of michael@0: * table element, but their nearest table element ancestors differ. "Table michael@0: * element" here includes not just but also , , etc. michael@0: * The nodes count as being their own descendants for this purpose, so a michael@0: * table element is its own nearest table element ancestor. michael@0: */ michael@0: bool InDifferentTableElements(nsIDOMNode* aNode1, nsIDOMNode* aNode2); michael@0: bool InDifferentTableElements(nsINode* aNode1, nsINode* aNode2); michael@0: nsresult RemoveEmptyNodes(); michael@0: nsresult SelectionEndpointInNode(nsINode *aNode, bool *aResult); michael@0: nsresult UpdateDocChangeRange(nsIDOMRange *aRange); michael@0: nsresult ConfirmSelectionInBody(); michael@0: nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode); michael@0: bool IsEmptyInline(nsIDOMNode *aNode); michael@0: bool ListIsEmptyLine(nsCOMArray &arrayOfNodes); michael@0: nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly); michael@0: nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts); michael@0: nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly); michael@0: nsresult RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_t aRelativeChange); michael@0: void DocumentModifiedWorker(); michael@0: michael@0: // data members michael@0: protected: michael@0: nsHTMLEditor *mHTMLEditor; michael@0: nsRefPtr mDocChangeRange; michael@0: bool mListenerEnabled; michael@0: bool mReturnInEmptyLIKillsList; michael@0: bool mDidDeleteSelection; michael@0: bool mDidRangedDelete; michael@0: bool mRestoreContentEditableCount; michael@0: nsRefPtr mUtilRange; michael@0: uint32_t mJoinOffset; // need to remember an int across willJoin/didJoin... michael@0: nsCOMPtr mNewBlock; michael@0: nsRefPtr mRangeItem; michael@0: StyleCache mCachedStyles[SIZE_STYLE_TABLE]; michael@0: }; michael@0: michael@0: #endif //nsHTMLEditRules_h__ michael@0:
,