diff -r 000000000000 -r 6474c204b198 editor/libeditor/html/nsHTMLEditor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/editor/libeditor/html/nsHTMLEditor.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,961 @@ +/* -*- 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 nsHTMLEditor_h__ +#define nsHTMLEditor_h__ + +#include "nsCOMPtr.h" +#include "nsCOMArray.h" +#include "nsPlaintextEditor.h" +#include "nsIEditor.h" +#include "nsIHTMLEditor.h" +#include "nsITableEditor.h" +#include "nsIEditorMailSupport.h" +#include "nsIEditorStyleSheets.h" + +#include "nsEditor.h" +#include "nsIDOMElement.h" +#include "nsIDOMEventListener.h" +#include "nsICSSLoaderObserver.h" + +#include "nsEditRules.h" + +#include "nsEditProperty.h" +#include "nsHTMLCSSUtils.h" + +#include "nsHTMLObjectResizer.h" +#include "nsIHTMLAbsPosEditor.h" +#include "nsIHTMLInlineTableEditor.h" +#include "nsIHTMLObjectResizeListener.h" +#include "nsIHTMLObjectResizer.h" + +#include "nsIDocumentObserver.h" + +#include "nsPoint.h" +#include "nsTArray.h" +#include "nsAutoPtr.h" +#include "nsAttrName.h" +#include "nsStubMutationObserver.h" + +#include "mozilla/Attributes.h" +#include "mozilla/dom/Element.h" + +class nsIDOMKeyEvent; +class nsITransferable; +class nsIDocumentEncoder; +class nsIClipboard; +class TypeInState; +class nsIContentFilter; +class nsIURL; +class nsILinkHandler; +class nsTableOuterFrame; +struct PropItem; + +namespace mozilla { +namespace widget { +struct IMEState; +} // namespace widget +} // namespace mozilla + +/** + * The HTML editor implementation.
+ * Use to edit HTML document represented as a DOM tree. + */ +class nsHTMLEditor : public nsPlaintextEditor, + public nsIHTMLEditor, + public nsIHTMLObjectResizer, + public nsIHTMLAbsPosEditor, + public nsITableEditor, + public nsIHTMLInlineTableEditor, + public nsIEditorStyleSheets, + public nsICSSLoaderObserver, + public nsStubMutationObserver +{ + typedef enum {eNoOp, eReplaceParent=1, eInsertParent=2} BlockTransformationType; + +public: + + enum ResizingRequestID + { + kX = 0, + kY = 1, + kWidth = 2, + kHeight = 3 + }; + + // see nsIHTMLEditor for documentation + +//Interfaces for addref and release and queryinterface +//NOTE macro used is for classes that inherit from +// another class. Only the base class should use NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLEditor, nsPlaintextEditor) + + + nsHTMLEditor(); + virtual ~nsHTMLEditor(); + + bool GetReturnInParagraphCreatesNewParagraph(); + + /* ------------ nsPlaintextEditor overrides -------------- */ + NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable); + NS_IMETHOD BeginningOfDocument(); + virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent); + virtual already_AddRefed GetFocusedContent(); + virtual already_AddRefed GetFocusedContentForIME(); + virtual bool IsActiveInDOMWindow(); + virtual already_AddRefed GetDOMEventTarget(); + virtual mozilla::dom::Element* GetEditorRoot() MOZ_OVERRIDE; + virtual already_AddRefed FindSelectionRoot(nsINode *aNode); + virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent); + virtual already_AddRefed GetInputEventTargetContent(); + virtual bool IsEditable(nsIContent *aNode); + using nsEditor::IsEditable; + + /* ------------ nsStubMutationObserver overrides --------- */ + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + + /* ------------ nsIEditorIMESupport overrides ------------ */ + NS_IMETHOD GetPreferredIMEState(mozilla::widget::IMEState *aState); + + /* ------------ nsIHTMLEditor methods -------------- */ + + NS_DECL_NSIHTMLEDITOR + + /* ------------ nsIHTMLObjectResizer methods -------------- */ + /* -------- Implemented in nsHTMLObjectResizer.cpp -------- */ + NS_DECL_NSIHTMLOBJECTRESIZER + + /* ------------ nsIHTMLAbsPosEditor methods -------------- */ + /* -------- Implemented in nsHTMLAbsPosition.cpp --------- */ + NS_DECL_NSIHTMLABSPOSEDITOR + + /* ------------ nsIHTMLInlineTableEditor methods -------------- */ + /* ------- Implemented in nsHTMLInlineTableEditor.cpp --------- */ + NS_DECL_NSIHTMLINLINETABLEEDITOR + + /* ------------ nsIHTMLEditor methods -------------- */ + NS_IMETHOD CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock, + nsIDOMNode **aOutBrNode); + + NS_IMETHOD LoadHTML(const nsAString &aInputString); + + nsresult GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor, + bool aBlockLevel); + NS_IMETHOD GetHTMLBackgroundColorState(bool *aMixed, nsAString &outColor); + + /* ------------ nsIEditorStyleSheets methods -------------- */ + + NS_IMETHOD AddStyleSheet(const nsAString & aURL); + NS_IMETHOD ReplaceStyleSheet(const nsAString& aURL); + NS_IMETHOD RemoveStyleSheet(const nsAString &aURL); + + NS_IMETHOD AddOverrideStyleSheet(const nsAString & aURL); + NS_IMETHOD ReplaceOverrideStyleSheet(const nsAString& aURL); + NS_IMETHOD RemoveOverrideStyleSheet(const nsAString &aURL); + + NS_IMETHOD EnableStyleSheet(const nsAString& aURL, bool aEnable); + + /* ------------ nsIEditorMailSupport methods -------------- */ + + NS_DECL_NSIEDITORMAILSUPPORT + + /* ------------ nsITableEditor methods -------------- */ + + NS_IMETHOD InsertTableCell(int32_t aNumber, bool aAfter); + NS_IMETHOD InsertTableColumn(int32_t aNumber, bool aAfter); + NS_IMETHOD InsertTableRow(int32_t aNumber, bool aAfter); + NS_IMETHOD DeleteTable(); + NS_IMETHOD DeleteTableCell(int32_t aNumber); + NS_IMETHOD DeleteTableCellContents(); + NS_IMETHOD DeleteTableColumn(int32_t aNumber); + NS_IMETHOD DeleteTableRow(int32_t aNumber); + NS_IMETHOD SelectTableCell(); + NS_IMETHOD SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndCell); + NS_IMETHOD SelectTableRow(); + NS_IMETHOD SelectTableColumn(); + NS_IMETHOD SelectTable(); + NS_IMETHOD SelectAllTableCells(); + NS_IMETHOD SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElement **aNewCell); + NS_IMETHOD JoinTableCells(bool aMergeNonContiguousContents); + NS_IMETHOD SplitTableCell(); + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable); + NS_IMETHOD GetCellIndexes(nsIDOMElement *aCell, + int32_t* aRowIndex, int32_t* aColIndex); + NS_IMETHOD GetTableSize(nsIDOMElement *aTable, + int32_t* aRowCount, int32_t* aColCount); + NS_IMETHOD GetCellAt(nsIDOMElement* aTable, int32_t aRowIndex, int32_t aColIndex, nsIDOMElement **aCell); + NS_IMETHOD GetCellDataAt(nsIDOMElement* aTable, + int32_t aRowIndex, int32_t aColIndex, + nsIDOMElement **aCell, + int32_t* aStartRowIndex, int32_t* aStartColIndex, + int32_t* aRowSpan, int32_t* aColSpan, + int32_t* aActualRowSpan, int32_t* aActualColSpan, + bool* aIsSelected); + NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode); + NS_IMETHOD GetNextRow(nsIDOMNode* aCurrentRowNode, nsIDOMNode** aRowNode); + NS_IMETHOD GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode); + + NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, int32_t aCol, + int32_t aDirection, bool aSelected); + NS_IMETHOD GetSelectedOrParentTableElement(nsAString& aTagName, + int32_t *aSelectedCount, + nsIDOMElement** aTableElement); + NS_IMETHOD GetSelectedCellsType(nsIDOMElement *aElement, uint32_t *aSelectionType); + + nsresult GetCellFromRange(nsIDOMRange *aRange, nsIDOMElement **aCell); + + // Finds the first selected cell in first range of selection + // This is in the *order of selection*, not order in the table + // (i.e., each cell added to selection is added in another range + // in the selection's rangelist, independent of location in table) + // aRange is optional: returns the range around the cell + NS_IMETHOD GetFirstSelectedCell(nsIDOMRange **aRange, nsIDOMElement **aCell); + // Get next cell until no more are found. Always use GetFirstSelected cell first + // aRange is optional: returns the range around the cell + NS_IMETHOD GetNextSelectedCell(nsIDOMRange **aRange, nsIDOMElement **aCell); + + // Upper-left-most selected cell in table + NS_IMETHOD GetFirstSelectedCellInTable(int32_t *aRowIndex, int32_t *aColIndex, nsIDOMElement **aCell); + + /* miscellaneous */ + // This sets background on the appropriate container element (table, cell,) + // or calls into nsTextEditor to set the page background + NS_IMETHOD SetCSSBackgroundColor(const nsAString& aColor); + NS_IMETHOD SetHTMLBackgroundColor(const nsAString& aColor); + + /* ------------ Block methods moved from nsEditor -------------- */ + static already_AddRefed GetBlockNodeParent(nsIDOMNode *aNode); + + void IsNextCharInNodeWhitespace(nsIContent* aContent, + int32_t aOffset, + bool* outIsSpace, + bool* outIsNBSP, + nsIContent** outNode = nullptr, + int32_t* outOffset = 0); + void IsPrevCharInNodeWhitespace(nsIContent* aContent, + int32_t aOffset, + bool* outIsSpace, + bool* outIsNBSP, + nsIContent** outNode = nullptr, + int32_t* outOffset = 0); + + /* ------------ Overrides of nsEditor interface methods -------------- */ + + nsresult EndUpdateViewBatch(); + + /** prepare the editor for use */ + NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot, + nsISelectionController *aSelCon, uint32_t aFlags, + const nsAString& aValue); + NS_IMETHOD PreDestroy(bool aDestroyingFrames); + + /** Internal, static version */ + // aElement must not be null. + static bool NodeIsBlockStatic(const mozilla::dom::Element* aElement); + static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock); +protected: + using nsEditor::IsBlockNode; + virtual bool IsBlockNode(nsINode *aNode); + +public: + NS_IMETHOD SetFlags(uint32_t aFlags); + + NS_IMETHOD Paste(int32_t aSelectionType); + NS_IMETHOD CanPaste(int32_t aSelectionType, bool *aCanPaste); + + NS_IMETHOD PasteTransferable(nsITransferable *aTransferable); + NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste); + + NS_IMETHOD DebugUnitTests(int32_t *outNumTests, int32_t *outNumTestsFailed); + + /** All editor operations which alter the doc should be prefaced + * with a call to StartOperation, naming the action and direction */ + NS_IMETHOD StartOperation(EditAction opID, + nsIEditor::EDirection aDirection); + + /** All editor operations which alter the doc should be followed + * with a call to EndOperation */ + NS_IMETHOD EndOperation(); + + /** returns true if aParentTag can contain a child of type aChildTag */ + virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag); + + /** returns true if aNode is a container */ + virtual bool IsContainer(nsIDOMNode *aNode); + + /** make the given selection span the entire document */ + NS_IMETHOD SelectEntireDocument(nsISelection *aSelection); + + NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement * aElement, + const nsAString & aAttribute, + const nsAString & aValue, + bool aSuppressTransaction); + NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement * aElement, + const nsAString & aAttribute, + bool aSuppressTransaction); + + /** join together any adjacent editable text nodes in the range */ + NS_IMETHOD CollapseAdjacentTextNodes(nsIDOMRange *aInRange); + + virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2) + MOZ_OVERRIDE; + + NS_IMETHOD DeleteSelectionImpl(EDirection aAction, + EStripWrappers aStripWrappers); + nsresult DeleteNode(nsINode* aNode); + NS_IMETHODIMP DeleteNode(nsIDOMNode * aNode); + NS_IMETHODIMP DeleteText(nsIDOMCharacterData *aTextNode, + uint32_t aOffset, + uint32_t aLength); + NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, + nsCOMPtr *aInOutNode, + int32_t *aInOutOffset, + nsIDOMDocument *aDoc); + NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode *aNode); + virtual bool IsModifiableNode(nsINode *aNode); + + NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable); + + NS_IMETHOD SelectAll(); + + NS_IMETHOD GetRootElement(nsIDOMElement **aRootElement); + + /* ------------ nsICSSLoaderObserver -------------- */ + NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet*aSheet, bool aWasAlternate, + nsresult aStatus); + + /* ------------ Utility Routines, not part of public API -------------- */ + NS_IMETHOD TypedText(const nsAString& aString, ETypingAction aAction); + nsresult InsertNodeAtPoint( nsIDOMNode *aNode, + nsCOMPtr *ioParent, + int32_t *ioOffset, + bool aNoEmptyNodes); + + // Use this to assure that selection is set after attribute nodes when + // trying to collapse selection at begining of a block node + // e.g., when setting at beginning of a table cell + // This will stop at a table, however, since we don't want to + // "drill down" into nested tables. + // aSelection is optional -- if null, we get current seletion + nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode); + + /** + * aNode must be a non-null text node. + * outIsEmptyNode must be non-null. + */ + nsresult IsVisTextNode(nsIContent* aNode, + bool* outIsEmptyNode, + bool aSafeToAskFrames); + nsresult IsEmptyNode(nsIDOMNode *aNode, bool *outIsEmptyBlock, + bool aMozBRDoesntCount = false, + bool aListOrCellNotEmpty = false, + bool aSafeToAskFrames = false); + nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock, + bool aMozBRDoesntCount = false, + bool aListOrCellNotEmpty = false, + bool aSafeToAskFrames = false); + nsresult IsEmptyNodeImpl(nsINode* aNode, + bool *outIsEmptyBlock, + bool aMozBRDoesntCount, + bool aListOrCellNotEmpty, + bool aSafeToAskFrames, + bool *aSeenBR); + + // Returns TRUE if sheet was loaded, false if it wasn't + bool EnableExistingStyleSheet(const nsAString& aURL); + + // Dealing with the internal style sheet lists: + NS_IMETHOD GetStyleSheetForURL(const nsAString &aURL, + nsCSSStyleSheet **_retval); + NS_IMETHOD GetURLForStyleSheet(nsCSSStyleSheet *aStyleSheet, nsAString &aURL); + + // Add a url + known style sheet to the internal lists: + nsresult AddNewStyleSheetToList(const nsAString &aURL, + nsCSSStyleSheet *aStyleSheet); + + nsresult RemoveStyleSheetFromList(const nsAString &aURL); + + bool IsCSSEnabled() + { + // TODO: removal of mCSSAware and use only the presence of mHTMLCSSUtils + return mCSSAware && mHTMLCSSUtils && mHTMLCSSUtils->IsCSSPrefChecked(); + } + + static bool HasAttributes(mozilla::dom::Element* aElement) + { + MOZ_ASSERT(aElement); + uint32_t attrCount = aElement->GetAttrCount(); + return attrCount > 1 || + (1 == attrCount && !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty)); + } + +protected: + + NS_IMETHOD InitRules(); + + // Create the event listeners for the editor to install + virtual void CreateEventListeners(); + + virtual nsresult InstallEventListeners(); + virtual void RemoveEventListeners(); + + bool ShouldReplaceRootElement(); + void ResetRootElementAndEventTarget(); + nsresult GetBodyElement(nsIDOMHTMLElement** aBody); + // Get the focused node of this editor. + // @return If the editor has focus, this returns the focused node. + // Otherwise, returns null. + already_AddRefed GetFocusedNode(); + + // Return TRUE if aElement is a table-related elemet and caret was set + bool SetCaretInTableCell(nsIDOMElement* aElement); + + // key event helpers + NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled); + NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset, + nsCOMPtr *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone); + +// Table Editing (implemented in nsTableEditor.cpp) + + // Table utilities + + // Insert a new cell after or before supplied aCell. + // Optional: If aNewCell supplied, returns the newly-created cell (addref'd, of course) + // This doesn't change or use the current selection + NS_IMETHOD InsertCell(nsIDOMElement *aCell, int32_t aRowSpan, int32_t aColSpan, + bool aAfter, bool aIsHeader, nsIDOMElement **aNewCell); + + // Helpers that don't touch the selection or do batch transactions + NS_IMETHOD DeleteRow(nsIDOMElement *aTable, int32_t aRowIndex); + NS_IMETHOD DeleteColumn(nsIDOMElement *aTable, int32_t aColIndex); + NS_IMETHOD DeleteCellContents(nsIDOMElement *aCell); + + // Move all contents from aCellToMerge into aTargetCell (append at end) + NS_IMETHOD MergeCells(nsCOMPtr aTargetCell, nsCOMPtr aCellToMerge, bool aDeleteCellToMerge); + + NS_IMETHOD DeleteTable2(nsIDOMElement *aTable, nsISelection *aSelection); + NS_IMETHOD SetColSpan(nsIDOMElement *aCell, int32_t aColSpan); + NS_IMETHOD SetRowSpan(nsIDOMElement *aCell, int32_t aRowSpan); + + // Helper used to get nsTableOuterFrame for a table. + nsTableOuterFrame* GetTableFrame(nsIDOMElement* aTable); + // Needed to do appropriate deleting when last cell or row is about to be deleted + // This doesn't count cells that don't start in the given row (are spanning from row above) + int32_t GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex); + // Test if all cells in row or column at given index are selected + bool AllCellsInRowSelected(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aNumberOfColumns); + bool AllCellsInColumnSelected(nsIDOMElement *aTable, int32_t aColIndex, int32_t aNumberOfRows); + + bool IsEmptyCell(mozilla::dom::Element* aCell); + + // Most insert methods need to get the same basic context data + // Any of the pointers may be null if you don't need that datum (for more efficiency) + // Input: *aCell is a known cell, + // if null, cell is obtained from the anchor node of the selection + // Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is null + NS_IMETHOD GetCellContext(nsISelection **aSelection, + nsIDOMElement **aTable, + nsIDOMElement **aCell, + nsIDOMNode **aCellParent, int32_t *aCellOffset, + int32_t *aRowIndex, int32_t *aColIndex); + + NS_IMETHOD GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex, int32_t aColIndex, + int32_t& aActualRowSpan, int32_t& aActualColSpan); + + NS_IMETHOD SplitCellIntoColumns(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex, + int32_t aColSpanLeft, int32_t aColSpanRight, nsIDOMElement **aNewCell); + + NS_IMETHOD SplitCellIntoRows(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex, + int32_t aRowSpanAbove, int32_t aRowSpanBelow, nsIDOMElement **aNewCell); + + nsresult CopyCellBackgroundColor(nsIDOMElement *destCell, nsIDOMElement *sourceCell); + + // Reduce rowspan/colspan when cells span into nonexistent rows/columns + NS_IMETHOD FixBadRowSpan(nsIDOMElement *aTable, int32_t aRowIndex, int32_t& aNewRowCount); + NS_IMETHOD FixBadColSpan(nsIDOMElement *aTable, int32_t aColIndex, int32_t& aNewColCount); + + // Fallback method: Call this after using ClearSelection() and you + // failed to set selection to some other content in the document + NS_IMETHOD SetSelectionAtDocumentStart(nsISelection *aSelection); + +// End of Table Editing utilities + + static nsCOMPtr GetEnclosingTable(nsIDOMNode *aNode); + + /** content-based query returns true if effects aNode + * If contains aNode, + * but also contains aNode and the second is + * more deeply nested than the first, then the first does not effect aNode. + * + * @param aNode The target of the query + * @param aProperty The property that we are querying for + * @param aAttribute The attribute of aProperty, example: color in + * May be null. + * @param aValue The value of aAttribute, example: blue in + * May be null. Ignored if aAttribute is null. + * @param aIsSet [OUT] true if effects aNode. + * @param outValue [OUT] the value of the attribute, if aIsSet is true + * + * The nsIContent variant returns aIsSet instead of using an out parameter. + */ + bool IsTextPropertySetByContent(nsIContent* aContent, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue, + nsAString* outValue = nullptr); + + void IsTextPropertySetByContent(nsIDOMNode* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool& aIsSet, + nsAString* outValue = nullptr); + + // Methods for handling plaintext quotations + NS_IMETHOD PasteAsPlaintextQuotation(int32_t aSelectionType); + + /** Insert a string as quoted text, + * replacing the selected text (if any). + * @param aQuotedText The string to insert. + * @param aAddCites Whether to prepend extra ">" to each line + * (usually true, unless those characters + * have already been added.) + * @return aNodeInserted The node spanning the insertion, if applicable. + * If aAddCites is false, this will be null. + */ + NS_IMETHOD InsertAsPlaintextQuotation(const nsAString & aQuotedText, + bool aAddCites, + nsIDOMNode **aNodeInserted); + + nsresult InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe, + nsIDOMDocument *aSourceDoc, + nsIDOMNode *aDestinationNode, + int32_t aDestOffset, + bool aDoDeleteSelection); + + // factored methods for handling insertion of data from transferables (drag&drop or clipboard) + NS_IMETHOD PrepareTransferable(nsITransferable **transferable); + NS_IMETHOD PrepareHTMLTransferable(nsITransferable **transferable, bool havePrivFlavor); + NS_IMETHOD InsertFromTransferable(nsITransferable *transferable, + nsIDOMDocument *aSourceDoc, + const nsAString & aContextStr, + const nsAString & aInfoStr, + nsIDOMNode *aDestinationNode, + int32_t aDestinationOffset, + bool aDoDeleteSelection); + nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer, + int32_t aIndex, + nsIDOMDocument *aSourceDoc, + nsIDOMNode *aDestinationNode, + int32_t aDestOffset, + bool aDoDeleteSelection); + bool HavePrivateHTMLFlavor( nsIClipboard *clipboard ); + nsresult ParseCFHTML(nsCString & aCfhtml, char16_t **aStuffToPaste, char16_t **aCfcontext); + nsresult DoContentFilterCallback(const nsAString &aFlavor, + nsIDOMDocument *aSourceDoc, + bool aWillDeleteSelection, + nsIDOMNode **aFragmentAsNode, + nsIDOMNode **aFragStartNode, + int32_t *aFragStartOffset, + nsIDOMNode **aFragEndNode, + int32_t *aFragEndOffset, + nsIDOMNode **aTargetNode, + int32_t *aTargetOffset, + bool *aDoContinue); + + bool IsInLink(nsIDOMNode *aNode, nsCOMPtr *outLink = nullptr); + nsresult StripFormattingNodes(nsIDOMNode *aNode, bool aOnlyList = false); + nsresult CreateDOMFragmentFromPaste(const nsAString & aInputString, + const nsAString & aContextStr, + const nsAString & aInfoStr, + nsCOMPtr *outFragNode, + nsCOMPtr *outStartNode, + nsCOMPtr *outEndNode, + int32_t *outStartOffset, + int32_t *outEndOffset, + bool aTrustedInput); + nsresult ParseFragment(const nsAString & aStr, nsIAtom* aContextLocalName, + nsIDocument* aTargetDoc, + nsCOMPtr *outNode, + bool aTrustedInput); + nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, + nsCOMArray& outNodeList, + nsIDOMNode *aStartNode, + int32_t aStartOffset, + nsIDOMNode *aEndNode, + int32_t aEndOffset); + nsresult CreateTagStack(nsTArray &aTagStack, + nsIDOMNode *aNode); + nsresult GetListAndTableParents( bool aEnd, + nsCOMArray& aListOfNodes, + nsCOMArray& outArray); + nsresult DiscoverPartialListsAndTables(nsCOMArray& aPasteNodes, + nsCOMArray& aListsAndTables, + int32_t *outHighWaterMark); + nsresult ScanForListAndTableStructure(bool aEnd, + nsCOMArray& aNodes, + nsIDOMNode *aListOrTable, + nsCOMPtr *outReplaceNode); + nsresult ReplaceOrphanedStructure( bool aEnd, + nsCOMArray& aNodeArray, + nsCOMArray& aListAndTableArray, + int32_t aHighWaterMark); + nsIDOMNode* GetArrayEndpoint(bool aEnd, nsCOMArray& aNodeArray); + + /* small utility routine to test if a break node is visible to user */ + bool IsVisBreak(nsIDOMNode *aNode); + + /* utility routine to possibly adjust the insertion position when + inserting a block level element */ + void NormalizeEOLInsertPosition(nsIDOMNode *firstNodeToInsert, + nsCOMPtr *insertParentNode, + int32_t *insertOffset); + + /* small utility routine to test the eEditorReadonly bit */ + bool IsModifiable(); + + /* helpers for block transformations */ + nsresult MakeDefinitionItem(const nsAString & aItemType); + nsresult InsertBasicBlock(const nsAString & aBlockType); + + /* increase/decrease the font size of selection */ + nsresult RelativeFontChange( int32_t aSizeChange); + + /* helper routines for font size changing */ + nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange, + nsIDOMCharacterData *aTextNode, + int32_t aStartOffset, + int32_t aEndOffset); + nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsINode* aNode); + nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode); + + /* helper routines for inline style */ + nsresult SetInlinePropertyOnTextNode( nsIDOMCharacterData *aTextNode, + int32_t aStartOffset, + int32_t aEndOffset, + nsIAtom *aProperty, + const nsAString *aAttribute, + const nsAString *aValue); + nsresult SetInlinePropertyOnNode( nsIDOMNode *aNode, + nsIAtom *aProperty, + const nsAString *aAttribute, + const nsAString *aValue); + nsresult SetInlinePropertyOnNode(nsIContent* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue); + + nsresult PromoteInlineRange(nsIDOMRange *inRange); + nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsIDOMRange *inRange); + nsresult SplitStyleAboveRange(nsIDOMRange *aRange, + nsIAtom *aProperty, + const nsAString *aAttribute); + nsresult SplitStyleAbovePoint(nsCOMPtr *aNode, + int32_t *aOffset, + nsIAtom *aProperty, + const nsAString *aAttribute, + nsCOMPtr *outLeftNode = nullptr, + nsCOMPtr *outRightNode = nullptr); + nsresult ApplyDefaultProperties(); + nsresult RemoveStyleInside(nsIDOMNode *aNode, + nsIAtom *aProperty, + const nsAString *aAttribute, + const bool aChildrenOnly = false); + nsresult RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAString *aAttribute); + + bool NodeIsProperty(nsIDOMNode *aNode); + bool HasAttr(nsIDOMNode *aNode, const nsAString *aAttribute); + bool IsAtFrontOfNode(nsIDOMNode *aNode, int32_t aOffset); + bool IsAtEndOfNode(nsIDOMNode *aNode, int32_t aOffset); + bool IsOnlyAttribute(nsIDOMNode *aElement, const nsAString *aAttribute); + bool IsOnlyAttribute(const nsIContent* aElement, const nsAString& aAttribute); + + nsresult RemoveBlockContainer(nsIDOMNode *inNode); + + nsIContent* GetPriorHTMLSibling(nsINode* aNode); + nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr *outNode); + nsIContent* GetPriorHTMLSibling(nsINode* aParent, int32_t aOffset); + nsresult GetPriorHTMLSibling(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr *outNode); + + nsIContent* GetNextHTMLSibling(nsINode* aNode); + nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr *outNode); + nsIContent* GetNextHTMLSibling(nsINode* aParent, int32_t aOffset); + nsresult GetNextHTMLSibling(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr *outNode); + + nsIContent* GetPriorHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false); + nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr *outNode, bool bNoBlockCrossing = false); + nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset, + bool aNoBlockCrossing = false); + nsresult GetPriorHTMLNode(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr *outNode, bool bNoBlockCrossing = false); + + nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false); + nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr *outNode, bool bNoBlockCrossing = false); + nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset, + bool aNoBlockCrossing = false); + nsresult GetNextHTMLNode(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr *outNode, bool bNoBlockCrossing = false); + + nsresult IsFirstEditableChild( nsIDOMNode *aNode, bool *aOutIsFirst); + nsresult IsLastEditableChild( nsIDOMNode *aNode, bool *aOutIsLast); + nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr *aOutFirstChild); + nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr *aOutLastChild); + + nsresult GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOutFirstLeaf); + nsresult GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOutLastLeaf); + + nsresult GetInlinePropertyBase(nsIAtom *aProperty, + const nsAString *aAttribute, + const nsAString *aValue, + bool *aFirst, + bool *aAny, + bool *aAll, + nsAString *outValue, + bool aCheckDefaults = true); + bool HasStyleOrIdOrClass(mozilla::dom::Element* aElement); + nsresult RemoveElementIfNoStyleOrIdOrClass(nsIDOMNode* aElement); + + // Whether the outer window of the DOM event target has focus or not. + bool OurWindowHasFocus(); + + // This function is used to insert a string of HTML input optionally with some + // context information into the editable field. The HTML input either comes + // from a transferable object created as part of a drop/paste operation, or from + // the InsertHTML method. We may want the HTML input to be sanitized (for example, + // if it's coming from a transferable object), in which case aTrustedInput should + // be set to false, otherwise, the caller should set it to true, which means that + // the HTML will be inserted in the DOM verbatim. + // + // aClearStyle should be set to false if you want the paste to be affected by + // local style (e.g., for the insertHTML command). + nsresult DoInsertHTMLWithContext(const nsAString& aInputString, + const nsAString& aContextStr, + const nsAString& aInfoStr, + const nsAString& aFlavor, + nsIDOMDocument* aSourceDoc, + nsIDOMNode* aDestNode, + int32_t aDestOffset, + bool aDeleteSelection, + bool aTrustedInput, + bool aClearStyle = true); + + nsresult ClearStyle(nsCOMPtr* aNode, int32_t* aOffset, + nsIAtom* aProperty, const nsAString* aAttribute); + +// Data members +protected: + + nsCOMArray mContentFilters; + + nsRefPtr mTypeInState; + + bool mCRInParagraphCreatesParagraph; + + bool mCSSAware; + nsAutoPtr mHTMLCSSUtils; + + // Used by GetFirstSelectedCell and GetNextSelectedCell + int32_t mSelectedCellIndex; + + nsString mLastStyleSheetURL; + nsString mLastOverrideStyleSheetURL; + + // Maintain a list of associated style sheets and their urls. + nsTArray mStyleSheetURLs; + nsTArray > mStyleSheets; + + // an array for holding default style settings + nsTArray mDefaultStyles; + +protected: + + /* ANONYMOUS UTILS */ + void RemoveListenerAndDeleteRef(const nsAString& aEvent, + nsIDOMEventListener* aListener, + bool aUseCapture, + nsIDOMElement* aElement, + nsIContent* aParentContent, + nsIPresShell* aShell); + void DeleteRefToAnonymousNode(nsIDOMElement* aElement, + nsIContent * aParentContent, + nsIPresShell* aShell); + + nsresult ShowResizersInner(nsIDOMElement *aResizedElement); + + // Returns the offset of an element's frame to its absolute containing block. + nsresult GetElementOrigin(nsIDOMElement * aElement, int32_t & aX, int32_t & aY); + nsresult GetPositionAndDimensions(nsIDOMElement * aElement, + int32_t & aX, int32_t & aY, + int32_t & aW, int32_t & aH, + int32_t & aBorderLeft, + int32_t & aBorderTop, + int32_t & aMarginLeft, + int32_t & aMarginTop); + + /* PACKED BOOLEANS FOR RESIZING, ABSOLUTE POSITIONING AND */ + /* INLINE TABLE EDITING */ + + // resizing + bool mIsObjectResizingEnabled; + bool mIsResizing; + bool mPreserveRatio; + bool mResizedObjectIsAnImage; + + // absolute positioning + bool mIsAbsolutelyPositioningEnabled; + bool mResizedObjectIsAbsolutelyPositioned; + + bool mGrabberClicked; + bool mIsMoving; + + bool mSnapToGridEnabled; + + // inline table editing + bool mIsInlineTableEditingEnabled; + + /* RESIZING */ + + nsCOMPtr mTopLeftHandle; + nsCOMPtr mTopHandle; + nsCOMPtr mTopRightHandle; + nsCOMPtr mLeftHandle; + nsCOMPtr mRightHandle; + nsCOMPtr mBottomLeftHandle; + nsCOMPtr mBottomHandle; + nsCOMPtr mBottomRightHandle; + + nsCOMPtr mActivatedHandle; + + nsCOMPtr mResizingShadow; + nsCOMPtr mResizingInfo; + + nsCOMPtr mResizedObject; + + nsCOMPtr mMouseMotionListenerP; + nsCOMPtr mSelectionListenerP; + nsCOMPtr mResizeEventListenerP; + + nsCOMArray objectResizeEventListeners; + + int32_t mOriginalX; + int32_t mOriginalY; + + int32_t mResizedObjectX; + int32_t mResizedObjectY; + int32_t mResizedObjectWidth; + int32_t mResizedObjectHeight; + + int32_t mResizedObjectMarginLeft; + int32_t mResizedObjectMarginTop; + int32_t mResizedObjectBorderLeft; + int32_t mResizedObjectBorderTop; + + int32_t mXIncrementFactor; + int32_t mYIncrementFactor; + int32_t mWidthIncrementFactor; + int32_t mHeightIncrementFactor; + + int8_t mInfoXIncrement; + int8_t mInfoYIncrement; + + nsresult SetAllResizersPosition(); + + nsresult CreateResizer(nsIDOMElement ** aReturn, int16_t aLocation, nsIDOMNode * aParentNode); + void SetAnonymousElementPosition(int32_t aX, int32_t aY, nsIDOMElement *aResizer); + + nsresult CreateShadow(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode, + nsIDOMElement * aOriginalObject); + nsresult SetShadowPosition(nsIDOMElement * aShadow, + nsIDOMElement * aOriginalObject, + int32_t aOriginalObjectX, + int32_t aOriginalObjectY); + + nsresult CreateResizingInfo(nsIDOMElement ** aReturn, nsIDOMNode * aParentNode); + nsresult SetResizingInfoPosition(int32_t aX, int32_t aY, + int32_t aW, int32_t aH); + + int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID); + nsresult StartResizing(nsIDOMElement * aHandle); + int32_t GetNewResizingX(int32_t aX, int32_t aY); + int32_t GetNewResizingY(int32_t aX, int32_t aY); + int32_t GetNewResizingWidth(int32_t aX, int32_t aY); + int32_t GetNewResizingHeight(int32_t aX, int32_t aY); + void HideShadowAndInfo(); + void SetFinalSize(int32_t aX, int32_t aY); + void DeleteRefToAnonymousNode(nsIDOMNode * aNode); + void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH, bool aPreserveRatio); + void HideAnonymousEditingUIs(); + + /* ABSOLUTE POSITIONING */ + + int32_t mPositionedObjectX; + int32_t mPositionedObjectY; + int32_t mPositionedObjectWidth; + int32_t mPositionedObjectHeight; + + int32_t mPositionedObjectMarginLeft; + int32_t mPositionedObjectMarginTop; + int32_t mPositionedObjectBorderLeft; + int32_t mPositionedObjectBorderTop; + + nsCOMPtr mAbsolutelyPositionedObject; + nsCOMPtr mGrabber; + nsCOMPtr mPositioningShadow; + + int32_t mGridSize; + + nsresult CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn); + nsresult StartMoving(nsIDOMElement * aHandle); + nsresult SetFinalPosition(int32_t aX, int32_t aY); + void AddPositioningOffset(int32_t & aX, int32_t & aY); + void SnapToGrid(int32_t & newX, int32_t & newY); + nsresult GrabberClicked(); + nsresult EndMoving(); + nsresult CheckPositionedElementBGandFG(nsIDOMElement * aElement, + nsAString & aReturn); + + /* INLINE TABLE EDITING */ + + nsCOMPtr mInlineEditedCell; + + nsCOMPtr mAddColumnBeforeButton; + nsCOMPtr mRemoveColumnButton; + nsCOMPtr mAddColumnAfterButton; + + nsCOMPtr mAddRowBeforeButton; + nsCOMPtr mRemoveRowButton; + nsCOMPtr mAddRowAfterButton; + + void AddMouseClickListener(nsIDOMElement * aElement); + void RemoveMouseClickListener(nsIDOMElement * aElement); + + nsCOMPtr mLinkHandler; + +public: + +// friends +friend class nsHTMLEditRules; +friend class nsTextEditRules; +friend class nsWSRunObject; +friend class nsHTMLEditorEventListener; + +private: + // Helpers + bool IsSimpleModifiableNode(nsIContent* aContent, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue); + nsresult SetInlinePropertyOnNodeImpl(nsIContent* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue); + typedef enum { eInserted, eAppended } InsertedOrAppended; + void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer, + nsIContent* aChild, int32_t aIndexInContainer, + InsertedOrAppended aInsertedOrAppended); +}; +#endif //nsHTMLEditor_h__ +