Bug 1247796. Use keyboardFocusIndicatorColor for ActiveBorder system color keyword...
[gecko.git] / editor / libeditor / nsHTMLEditor.h
blob754a3b66c08265649e02894458505efe25949f36
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsHTMLEditor_h__
7 #define nsHTMLEditor_h__
9 #include "nsCOMPtr.h"
10 #include "nsPlaintextEditor.h"
11 #include "nsIEditor.h"
12 #include "nsIHTMLEditor.h"
13 #include "nsITableEditor.h"
14 #include "nsIEditorMailSupport.h"
15 #include "nsIEditorStyleSheets.h"
17 #include "nsEditor.h"
18 #include "nsIDOMElement.h"
19 #include "nsIDOMEventListener.h"
20 #include "nsICSSLoaderObserver.h"
22 #include "nsEditRules.h"
24 #include "nsHTMLCSSUtils.h"
26 #include "nsHTMLObjectResizer.h"
27 #include "nsIHTMLAbsPosEditor.h"
28 #include "nsIHTMLInlineTableEditor.h"
29 #include "nsIHTMLObjectResizeListener.h"
30 #include "nsIHTMLObjectResizer.h"
32 #include "nsIDocumentObserver.h"
34 #include "nsPoint.h"
35 #include "nsTArray.h"
36 #include "nsAutoPtr.h"
37 #include "nsAttrName.h"
38 #include "nsStubMutationObserver.h"
40 #include "mozilla/Attributes.h"
41 #include "mozilla/dom/Element.h"
42 #include "mozilla/StyleSheetHandle.h"
44 class nsDocumentFragment;
45 class nsIDOMKeyEvent;
46 class nsITransferable;
47 class nsIClipboard;
48 class TypeInState;
49 class nsIContentFilter;
50 class nsILinkHandler;
51 class nsTableOuterFrame;
52 class nsIDOMRange;
53 class nsRange;
54 struct PropItem;
56 namespace mozilla {
57 template<class T> class OwningNonNull;
58 namespace dom {
59 class DocumentFragment;
60 } // namespace dom
61 namespace widget {
62 struct IMEState;
63 } // namespace widget
64 } // namespace mozilla
66 /**
67 * The HTML editor implementation.<br>
68 * Use to edit HTML document represented as a DOM tree.
70 class nsHTMLEditor final : public nsPlaintextEditor,
71 public nsIHTMLEditor,
72 public nsIHTMLObjectResizer,
73 public nsIHTMLAbsPosEditor,
74 public nsITableEditor,
75 public nsIHTMLInlineTableEditor,
76 public nsIEditorStyleSheets,
77 public nsICSSLoaderObserver,
78 public nsStubMutationObserver
80 typedef enum {eNoOp, eReplaceParent=1, eInsertParent=2} BlockTransformationType;
82 public:
84 enum ResizingRequestID
86 kX = 0,
87 kY = 1,
88 kWidth = 2,
89 kHeight = 3
92 // see nsIHTMLEditor for documentation
94 //Interfaces for addref and release and queryinterface
95 //NOTE macro used is for classes that inherit from
96 // another class. Only the base class should use NS_DECL_ISUPPORTS
97 NS_DECL_ISUPPORTS_INHERITED
98 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLEditor, nsPlaintextEditor)
101 nsHTMLEditor();
103 bool GetReturnInParagraphCreatesNewParagraph();
105 /* ------------ nsPlaintextEditor overrides -------------- */
106 NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable) override;
107 NS_IMETHOD BeginningOfDocument() override;
108 virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) override;
109 virtual already_AddRefed<nsIContent> GetFocusedContent() override;
110 virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
111 virtual bool IsActiveInDOMWindow() override;
112 virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() override;
113 virtual mozilla::dom::Element* GetEditorRoot() override;
114 virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode) override;
115 virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent) override;
116 virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
117 virtual bool IsEditable(nsINode* aNode) override;
118 using nsEditor::IsEditable;
120 /* ------------ nsStubMutationObserver overrides --------- */
121 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
122 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
123 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
125 /* ------------ nsIEditorIMESupport overrides ------------ */
126 NS_IMETHOD GetPreferredIMEState(mozilla::widget::IMEState *aState) override;
128 /* ------------ nsIHTMLEditor methods -------------- */
130 NS_DECL_NSIHTMLEDITOR
132 /* ------------ nsIHTMLObjectResizer methods -------------- */
133 /* -------- Implemented in nsHTMLObjectResizer.cpp -------- */
134 NS_DECL_NSIHTMLOBJECTRESIZER
136 /* ------------ nsIHTMLAbsPosEditor methods -------------- */
137 /* -------- Implemented in nsHTMLAbsPosition.cpp --------- */
138 NS_DECL_NSIHTMLABSPOSEDITOR
140 /* ------------ nsIHTMLInlineTableEditor methods -------------- */
141 /* ------- Implemented in nsHTMLInlineTableEditor.cpp --------- */
142 NS_DECL_NSIHTMLINLINETABLEEDITOR
144 /* ------------ nsIHTMLEditor methods -------------- */
145 nsresult CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock,
146 nsIDOMNode **aOutBrNode);
148 nsresult LoadHTML(const nsAString &aInputString);
150 nsresult GetCSSBackgroundColorState(bool *aMixed, nsAString &aOutColor,
151 bool aBlockLevel);
152 NS_IMETHOD GetHTMLBackgroundColorState(bool *aMixed, nsAString &outColor);
154 /* ------------ nsIEditorStyleSheets methods -------------- */
156 NS_IMETHOD AddStyleSheet(const nsAString & aURL) override;
157 NS_IMETHOD ReplaceStyleSheet(const nsAString& aURL) override;
158 NS_IMETHOD RemoveStyleSheet(const nsAString &aURL) override;
160 NS_IMETHOD AddOverrideStyleSheet(const nsAString & aURL) override;
161 NS_IMETHOD ReplaceOverrideStyleSheet(const nsAString& aURL) override;
162 NS_IMETHOD RemoveOverrideStyleSheet(const nsAString &aURL) override;
164 NS_IMETHOD EnableStyleSheet(const nsAString& aURL, bool aEnable) override;
166 /* ------------ nsIEditorMailSupport methods -------------- */
168 NS_DECL_NSIEDITORMAILSUPPORT
170 /* ------------ nsITableEditor methods -------------- */
172 NS_IMETHOD InsertTableCell(int32_t aNumber, bool aAfter) override;
173 NS_IMETHOD InsertTableColumn(int32_t aNumber, bool aAfter) override;
174 NS_IMETHOD InsertTableRow(int32_t aNumber, bool aAfter) override;
175 NS_IMETHOD DeleteTable() override;
176 NS_IMETHOD DeleteTableCell(int32_t aNumber) override;
177 NS_IMETHOD DeleteTableCellContents() override;
178 NS_IMETHOD DeleteTableColumn(int32_t aNumber) override;
179 NS_IMETHOD DeleteTableRow(int32_t aNumber) override;
180 NS_IMETHOD SelectTableCell() override;
181 NS_IMETHOD SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndCell) override;
182 NS_IMETHOD SelectTableRow() override;
183 NS_IMETHOD SelectTableColumn() override;
184 NS_IMETHOD SelectTable() override;
185 NS_IMETHOD SelectAllTableCells() override;
186 NS_IMETHOD SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElement **aNewCell) override;
187 NS_IMETHOD JoinTableCells(bool aMergeNonContiguousContents) override;
188 NS_IMETHOD SplitTableCell() override;
189 NS_IMETHOD NormalizeTable(nsIDOMElement *aTable) override;
190 NS_IMETHOD GetCellIndexes(nsIDOMElement *aCell,
191 int32_t* aRowIndex, int32_t* aColIndex) override;
192 NS_IMETHOD GetTableSize(nsIDOMElement *aTable,
193 int32_t* aRowCount, int32_t* aColCount) override;
194 NS_IMETHOD GetCellAt(nsIDOMElement* aTable, int32_t aRowIndex, int32_t aColIndex, nsIDOMElement **aCell) override;
195 NS_IMETHOD GetCellDataAt(nsIDOMElement* aTable,
196 int32_t aRowIndex, int32_t aColIndex,
197 nsIDOMElement **aCell,
198 int32_t* aStartRowIndex, int32_t* aStartColIndex,
199 int32_t* aRowSpan, int32_t* aColSpan,
200 int32_t* aActualRowSpan, int32_t* aActualColSpan,
201 bool* aIsSelected) override;
202 NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode) override;
203 NS_IMETHOD GetNextRow(nsIDOMNode* aCurrentRowNode, nsIDOMNode** aRowNode) override;
204 nsresult GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode);
206 NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow, int32_t aCol,
207 int32_t aDirection, bool aSelected) override;
208 NS_IMETHOD GetSelectedOrParentTableElement(nsAString& aTagName,
209 int32_t *aSelectedCount,
210 nsIDOMElement** aTableElement) override;
211 NS_IMETHOD GetSelectedCellsType(nsIDOMElement *aElement, uint32_t *aSelectionType) override;
213 nsresult GetCellFromRange(nsRange* aRange, nsIDOMElement** aCell);
215 // Finds the first selected cell in first range of selection
216 // This is in the *order of selection*, not order in the table
217 // (i.e., each cell added to selection is added in another range
218 // in the selection's rangelist, independent of location in table)
219 // aRange is optional: returns the range around the cell
220 NS_IMETHOD GetFirstSelectedCell(nsIDOMRange **aRange, nsIDOMElement **aCell) override;
221 // Get next cell until no more are found. Always use GetFirstSelected cell first
222 // aRange is optional: returns the range around the cell
223 NS_IMETHOD GetNextSelectedCell(nsIDOMRange **aRange, nsIDOMElement **aCell) override;
225 // Upper-left-most selected cell in table
226 NS_IMETHOD GetFirstSelectedCellInTable(int32_t *aRowIndex, int32_t *aColIndex, nsIDOMElement **aCell) override;
228 /* miscellaneous */
229 // This sets background on the appropriate container element (table, cell,)
230 // or calls into nsTextEditor to set the page background
231 nsresult SetCSSBackgroundColor(const nsAString& aColor);
232 nsresult SetHTMLBackgroundColor(const nsAString& aColor);
234 /* ------------ Block methods moved from nsEditor -------------- */
235 static mozilla::dom::Element* GetBlockNodeParent(nsINode* aNode);
236 static nsIDOMNode* GetBlockNodeParent(nsIDOMNode* aNode);
237 static mozilla::dom::Element* GetBlock(nsINode& aNode);
239 void IsNextCharInNodeWhitespace(nsIContent* aContent,
240 int32_t aOffset,
241 bool* outIsSpace,
242 bool* outIsNBSP,
243 nsIContent** outNode = nullptr,
244 int32_t* outOffset = 0);
245 void IsPrevCharInNodeWhitespace(nsIContent* aContent,
246 int32_t aOffset,
247 bool* outIsSpace,
248 bool* outIsNBSP,
249 nsIContent** outNode = nullptr,
250 int32_t* outOffset = 0);
252 /* ------------ Overrides of nsEditor interface methods -------------- */
254 nsresult EndUpdateViewBatch() override;
256 /** prepare the editor for use */
257 NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot,
258 nsISelectionController *aSelCon, uint32_t aFlags,
259 const nsAString& aValue) override;
260 NS_IMETHOD PreDestroy(bool aDestroyingFrames) override;
262 /** Internal, static version */
263 // aElement must not be null.
264 static bool NodeIsBlockStatic(const nsINode* aElement);
265 static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock);
266 protected:
267 virtual ~nsHTMLEditor();
269 using nsEditor::IsBlockNode;
270 virtual bool IsBlockNode(nsINode *aNode) override;
272 public:
273 NS_IMETHOD SetFlags(uint32_t aFlags) override;
275 NS_IMETHOD Paste(int32_t aSelectionType) override;
276 NS_IMETHOD CanPaste(int32_t aSelectionType, bool *aCanPaste) override;
278 NS_IMETHOD PasteTransferable(nsITransferable *aTransferable) override;
279 NS_IMETHOD CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste) override;
281 NS_IMETHOD DebugUnitTests(int32_t *outNumTests, int32_t *outNumTestsFailed) override;
283 /** All editor operations which alter the doc should be prefaced
284 * with a call to StartOperation, naming the action and direction */
285 NS_IMETHOD StartOperation(EditAction opID,
286 nsIEditor::EDirection aDirection) override;
288 /** All editor operations which alter the doc should be followed
289 * with a call to EndOperation */
290 NS_IMETHOD EndOperation() override;
292 /** returns true if aParentTag can contain a child of type aChildTag */
293 virtual bool TagCanContainTag(nsIAtom& aParentTag, nsIAtom& aChildTag)
294 override;
296 /** returns true if aNode is a container */
297 virtual bool IsContainer(nsINode* aNode) override;
298 virtual bool IsContainer(nsIDOMNode* aNode) override;
300 /** make the given selection span the entire document */
301 virtual nsresult SelectEntireDocument(mozilla::dom::Selection* aSelection) override;
303 NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement * aElement,
304 const nsAString & aAttribute,
305 const nsAString & aValue,
306 bool aSuppressTransaction) override;
307 NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement * aElement,
308 const nsAString & aAttribute,
309 bool aSuppressTransaction) override;
311 /** join together any adjacent editable text nodes in the range */
312 nsresult CollapseAdjacentTextNodes(nsRange* aRange);
314 virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2)
315 override;
317 NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
318 EStripWrappers aStripWrappers) override;
319 nsresult DeleteNode(nsINode* aNode);
320 NS_IMETHOD DeleteNode(nsIDOMNode * aNode) override;
321 nsresult DeleteText(nsGenericDOMDataNode& aTextNode, uint32_t aOffset,
322 uint32_t aLength);
323 virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
324 nsCOMPtr<nsINode>* aInOutNode,
325 int32_t* aInOutOffset,
326 nsIDocument* aDoc) override;
327 NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode *aNode) override;
328 virtual bool IsModifiableNode(nsINode *aNode) override;
330 NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable) override;
332 NS_IMETHOD SelectAll() override;
334 NS_IMETHOD GetRootElement(nsIDOMElement **aRootElement) override;
336 /* ------------ nsICSSLoaderObserver -------------- */
337 NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
338 bool aWasAlternate, nsresult aStatus) override;
340 /* ------------ Utility Routines, not part of public API -------------- */
341 NS_IMETHOD TypedText(const nsAString& aString, ETypingAction aAction) override;
342 nsresult InsertNodeAtPoint( nsIDOMNode *aNode,
343 nsCOMPtr<nsIDOMNode> *ioParent,
344 int32_t *ioOffset,
345 bool aNoEmptyNodes);
347 // Use this to assure that selection is set after attribute nodes when
348 // trying to collapse selection at begining of a block node
349 // e.g., when setting at beginning of a table cell
350 // This will stop at a table, however, since we don't want to
351 // "drill down" into nested tables.
352 // aSelection is optional -- if null, we get current seletion
353 void CollapseSelectionToDeepestNonTableFirstChild(
354 mozilla::dom::Selection* aSelection, nsINode* aNode);
357 * aNode must be a non-null text node.
358 * outIsEmptyNode must be non-null.
360 nsresult IsVisTextNode(nsIContent* aNode,
361 bool* outIsEmptyNode,
362 bool aSafeToAskFrames);
363 nsresult IsEmptyNode(nsIDOMNode *aNode, bool *outIsEmptyBlock,
364 bool aMozBRDoesntCount = false,
365 bool aListOrCellNotEmpty = false,
366 bool aSafeToAskFrames = false);
367 nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
368 bool aMozBRDoesntCount = false,
369 bool aListOrCellNotEmpty = false,
370 bool aSafeToAskFrames = false);
371 nsresult IsEmptyNodeImpl(nsINode* aNode,
372 bool *outIsEmptyBlock,
373 bool aMozBRDoesntCount,
374 bool aListOrCellNotEmpty,
375 bool aSafeToAskFrames,
376 bool *aSeenBR);
378 // Returns TRUE if sheet was loaded, false if it wasn't
379 bool EnableExistingStyleSheet(const nsAString& aURL);
381 // Dealing with the internal style sheet lists:
382 mozilla::StyleSheetHandle GetStyleSheetForURL(const nsAString& aURL);
383 void GetURLForStyleSheet(mozilla::StyleSheetHandle aStyleSheet,
384 nsAString& aURL);
386 // Add a url + known style sheet to the internal lists:
387 nsresult AddNewStyleSheetToList(const nsAString &aURL,
388 mozilla::StyleSheetHandle aStyleSheet);
390 nsresult RemoveStyleSheetFromList(const nsAString &aURL);
392 bool IsCSSEnabled()
394 // TODO: removal of mCSSAware and use only the presence of mHTMLCSSUtils
395 return mCSSAware && mHTMLCSSUtils && mHTMLCSSUtils->IsCSSPrefChecked();
398 static bool HasAttributes(mozilla::dom::Element* aElement)
400 MOZ_ASSERT(aElement);
401 uint32_t attrCount = aElement->GetAttrCount();
402 return attrCount > 1 ||
403 (1 == attrCount && !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
406 protected:
408 NS_IMETHOD InitRules() override;
410 // Create the event listeners for the editor to install
411 virtual void CreateEventListeners() override;
413 virtual nsresult InstallEventListeners() override;
414 virtual void RemoveEventListeners() override;
416 bool ShouldReplaceRootElement();
417 void ResetRootElementAndEventTarget();
418 nsresult GetBodyElement(nsIDOMHTMLElement** aBody);
419 // Get the focused node of this editor.
420 // @return If the editor has focus, this returns the focused node.
421 // Otherwise, returns null.
422 already_AddRefed<nsINode> GetFocusedNode();
424 // Return TRUE if aElement is a table-related elemet and caret was set
425 bool SetCaretInTableCell(nsIDOMElement* aElement);
427 // key event helpers
428 NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled);
429 already_AddRefed<mozilla::dom::Element> CreateBR(nsINode* aNode,
430 int32_t aOffset, EDirection aSelect = eNone);
431 NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset,
432 nsCOMPtr<nsIDOMNode> *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
434 // Table Editing (implemented in nsTableEditor.cpp)
436 // Table utilities
438 // Insert a new cell after or before supplied aCell.
439 // Optional: If aNewCell supplied, returns the newly-created cell (addref'd, of course)
440 // This doesn't change or use the current selection
441 NS_IMETHOD InsertCell(nsIDOMElement *aCell, int32_t aRowSpan, int32_t aColSpan,
442 bool aAfter, bool aIsHeader, nsIDOMElement **aNewCell);
444 // Helpers that don't touch the selection or do batch transactions
445 NS_IMETHOD DeleteRow(nsIDOMElement *aTable, int32_t aRowIndex);
446 NS_IMETHOD DeleteColumn(nsIDOMElement *aTable, int32_t aColIndex);
447 NS_IMETHOD DeleteCellContents(nsIDOMElement *aCell);
449 // Move all contents from aCellToMerge into aTargetCell (append at end)
450 NS_IMETHOD MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell, nsCOMPtr<nsIDOMElement> aCellToMerge, bool aDeleteCellToMerge);
452 nsresult DeleteTable2(nsIDOMElement* aTable,
453 mozilla::dom::Selection* aSelection);
454 NS_IMETHOD SetColSpan(nsIDOMElement *aCell, int32_t aColSpan);
455 NS_IMETHOD SetRowSpan(nsIDOMElement *aCell, int32_t aRowSpan);
457 // Helper used to get nsTableOuterFrame for a table.
458 nsTableOuterFrame* GetTableFrame(nsIDOMElement* aTable);
459 // Needed to do appropriate deleting when last cell or row is about to be deleted
460 // This doesn't count cells that don't start in the given row (are spanning from row above)
461 int32_t GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex);
462 // Test if all cells in row or column at given index are selected
463 bool AllCellsInRowSelected(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aNumberOfColumns);
464 bool AllCellsInColumnSelected(nsIDOMElement *aTable, int32_t aColIndex, int32_t aNumberOfRows);
466 bool IsEmptyCell(mozilla::dom::Element* aCell);
468 // Most insert methods need to get the same basic context data
469 // Any of the pointers may be null if you don't need that datum (for more efficiency)
470 // Input: *aCell is a known cell,
471 // if null, cell is obtained from the anchor node of the selection
472 // Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is null
473 nsresult GetCellContext(mozilla::dom::Selection** aSelection,
474 nsIDOMElement** aTable, nsIDOMElement** aCell,
475 nsIDOMNode** aCellParent, int32_t* aCellOffset,
476 int32_t* aRowIndex, int32_t* aColIndex);
478 NS_IMETHOD GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex, int32_t aColIndex,
479 int32_t& aActualRowSpan, int32_t& aActualColSpan);
481 NS_IMETHOD SplitCellIntoColumns(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex,
482 int32_t aColSpanLeft, int32_t aColSpanRight, nsIDOMElement **aNewCell);
484 NS_IMETHOD SplitCellIntoRows(nsIDOMElement *aTable, int32_t aRowIndex, int32_t aColIndex,
485 int32_t aRowSpanAbove, int32_t aRowSpanBelow, nsIDOMElement **aNewCell);
487 nsresult CopyCellBackgroundColor(nsIDOMElement *destCell, nsIDOMElement *sourceCell);
489 // Reduce rowspan/colspan when cells span into nonexistent rows/columns
490 NS_IMETHOD FixBadRowSpan(nsIDOMElement *aTable, int32_t aRowIndex, int32_t& aNewRowCount);
491 NS_IMETHOD FixBadColSpan(nsIDOMElement *aTable, int32_t aColIndex, int32_t& aNewColCount);
493 // Fallback method: Call this after using ClearSelection() and you
494 // failed to set selection to some other content in the document
495 nsresult SetSelectionAtDocumentStart(mozilla::dom::Selection* aSelection);
497 // End of Table Editing utilities
499 static mozilla::dom::Element* GetEnclosingTable(nsINode* aNode);
500 static nsIDOMNode* GetEnclosingTable(nsIDOMNode *aNode);
502 /** content-based query returns true if <aProperty aAttribute=aValue> effects aNode
503 * If <aProperty aAttribute=aValue> contains aNode,
504 * but <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
505 * more deeply nested than the first, then the first does not effect aNode.
507 * @param aNode The target of the query
508 * @param aProperty The property that we are querying for
509 * @param aAttribute The attribute of aProperty, example: color in <FONT color="blue">
510 * May be null.
511 * @param aValue The value of aAttribute, example: blue in <FONT color="blue">
512 * May be null. Ignored if aAttribute is null.
513 * @param aIsSet [OUT] true if <aProperty aAttribute=aValue> effects aNode.
514 * @param outValue [OUT] the value of the attribute, if aIsSet is true
516 * The nsIContent variant returns aIsSet instead of using an out parameter.
518 bool IsTextPropertySetByContent(nsINode* aNode,
519 nsIAtom* aProperty,
520 const nsAString* aAttribute,
521 const nsAString* aValue,
522 nsAString* outValue = nullptr);
524 void IsTextPropertySetByContent(nsIDOMNode* aNode,
525 nsIAtom* aProperty,
526 const nsAString* aAttribute,
527 const nsAString* aValue,
528 bool& aIsSet,
529 nsAString* outValue = nullptr);
531 // Methods for handling plaintext quotations
532 NS_IMETHOD PasteAsPlaintextQuotation(int32_t aSelectionType);
534 /** Insert a string as quoted text,
535 * replacing the selected text (if any).
536 * @param aQuotedText The string to insert.
537 * @param aAddCites Whether to prepend extra ">" to each line
538 * (usually true, unless those characters
539 * have already been added.)
540 * @return aNodeInserted The node spanning the insertion, if applicable.
541 * If aAddCites is false, this will be null.
543 NS_IMETHOD InsertAsPlaintextQuotation(const nsAString & aQuotedText,
544 bool aAddCites,
545 nsIDOMNode **aNodeInserted);
547 nsresult InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
548 nsIDOMDocument *aSourceDoc,
549 nsIDOMNode *aDestinationNode,
550 int32_t aDestOffset,
551 bool aDoDeleteSelection);
553 // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
554 NS_IMETHOD PrepareTransferable(nsITransferable **transferable) override;
555 nsresult PrepareHTMLTransferable(nsITransferable **transferable);
556 nsresult InsertFromTransferable(nsITransferable *transferable,
557 nsIDOMDocument *aSourceDoc,
558 const nsAString & aContextStr,
559 const nsAString & aInfoStr,
560 bool havePrivateHTMLFlavor,
561 nsIDOMNode *aDestinationNode,
562 int32_t aDestinationOffset,
563 bool aDoDeleteSelection);
564 nsresult InsertFromDataTransfer(mozilla::dom::DataTransfer *aDataTransfer,
565 int32_t aIndex,
566 nsIDOMDocument *aSourceDoc,
567 nsIDOMNode *aDestinationNode,
568 int32_t aDestOffset,
569 bool aDoDeleteSelection) override;
570 bool HavePrivateHTMLFlavor( nsIClipboard *clipboard );
571 nsresult ParseCFHTML(nsCString & aCfhtml, char16_t **aStuffToPaste, char16_t **aCfcontext);
572 nsresult DoContentFilterCallback(const nsAString &aFlavor,
573 nsIDOMDocument *aSourceDoc,
574 bool aWillDeleteSelection,
575 nsIDOMNode **aFragmentAsNode,
576 nsIDOMNode **aFragStartNode,
577 int32_t *aFragStartOffset,
578 nsIDOMNode **aFragEndNode,
579 int32_t *aFragEndOffset,
580 nsIDOMNode **aTargetNode,
581 int32_t *aTargetOffset,
582 bool *aDoContinue);
584 bool IsInLink(nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *outLink = nullptr);
585 nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
586 nsresult CreateDOMFragmentFromPaste(const nsAString & aInputString,
587 const nsAString & aContextStr,
588 const nsAString & aInfoStr,
589 nsCOMPtr<nsIDOMNode> *outFragNode,
590 nsCOMPtr<nsIDOMNode> *outStartNode,
591 nsCOMPtr<nsIDOMNode> *outEndNode,
592 int32_t *outStartOffset,
593 int32_t *outEndOffset,
594 bool aTrustedInput);
595 nsresult ParseFragment(const nsAString & aStr, nsIAtom* aContextLocalName,
596 nsIDocument* aTargetDoc,
597 mozilla::dom::DocumentFragment** aFragment,
598 bool aTrustedInput);
599 void CreateListOfNodesToPaste(mozilla::dom::DocumentFragment& aFragment,
600 nsTArray<mozilla::OwningNonNull<nsINode>>& outNodeList,
601 nsINode* aStartNode,
602 int32_t aStartOffset,
603 nsINode* aEndNode,
604 int32_t aEndOffset);
605 nsresult CreateTagStack(nsTArray<nsString> &aTagStack,
606 nsIDOMNode *aNode);
607 enum class StartOrEnd { start, end };
608 void GetListAndTableParents(StartOrEnd aStartOrEnd,
609 nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeList,
610 nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& outArray);
611 int32_t DiscoverPartialListsAndTables(nsTArray<mozilla::OwningNonNull<nsINode>>& aPasteNodes,
612 nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& aListsAndTables);
613 nsINode* ScanForListAndTableStructure(StartOrEnd aStartOrEnd,
614 nsTArray<mozilla::OwningNonNull<nsINode>>& aNodes,
615 mozilla::dom::Element& aListOrTable);
616 void ReplaceOrphanedStructure(StartOrEnd aStartOrEnd,
617 nsTArray<mozilla::OwningNonNull<nsINode>>& aNodeArray,
618 nsTArray<mozilla::OwningNonNull<mozilla::dom::Element>>& aListAndTableArray,
619 int32_t aHighWaterMark);
621 /* small utility routine to test if a break node is visible to user */
622 bool IsVisBreak(nsINode* aNode);
623 bool IsVisBreak(nsIDOMNode *aNode);
625 /* utility routine to possibly adjust the insertion position when
626 inserting a block level element */
627 void NormalizeEOLInsertPosition(nsIDOMNode *firstNodeToInsert,
628 nsCOMPtr<nsIDOMNode> *insertParentNode,
629 int32_t *insertOffset);
631 /* small utility routine to test the eEditorReadonly bit */
632 bool IsModifiable();
634 /* helpers for block transformations */
635 nsresult MakeDefinitionItem(const nsAString & aItemType);
636 nsresult InsertBasicBlock(const nsAString & aBlockType);
638 /* increase/decrease the font size of selection */
639 enum class FontSize { incr, decr };
640 nsresult RelativeFontChange(FontSize aDir);
642 /* helper routines for font size changing */
643 nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange,
644 nsIDOMCharacterData *aTextNode,
645 int32_t aStartOffset,
646 int32_t aEndOffset);
647 nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
648 nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
650 /* helper routines for inline style */
651 nsresult SetInlinePropertyOnTextNode(mozilla::dom::Text& aData,
652 int32_t aStartOffset,
653 int32_t aEndOffset,
654 nsIAtom& aProperty,
655 const nsAString* aAttribute,
656 const nsAString& aValue);
657 nsresult SetInlinePropertyOnNode(nsIContent& aNode,
658 nsIAtom& aProperty,
659 const nsAString* aAttribute,
660 const nsAString& aValue);
662 nsresult PromoteInlineRange(nsRange* aRange);
663 nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange* aRange);
664 nsresult SplitStyleAboveRange(nsRange* aRange,
665 nsIAtom *aProperty,
666 const nsAString *aAttribute);
667 nsresult SplitStyleAbovePoint(nsCOMPtr<nsIDOMNode> *aNode,
668 int32_t *aOffset,
669 nsIAtom *aProperty,
670 const nsAString *aAttribute,
671 nsCOMPtr<nsIDOMNode> *outLeftNode = nullptr,
672 nsCOMPtr<nsIDOMNode> *outRightNode = nullptr);
673 nsresult ApplyDefaultProperties();
674 nsresult RemoveStyleInside(nsIDOMNode *aNode,
675 nsIAtom *aProperty,
676 const nsAString *aAttribute,
677 const bool aChildrenOnly = false);
678 nsresult RemoveStyleInside(nsIContent& aNode,
679 nsIAtom* aProperty,
680 const nsAString* aAttribute,
681 const bool aChildrenOnly = false);
682 nsresult RemoveInlinePropertyImpl(nsIAtom* aProperty,
683 const nsAString* aAttribute);
685 bool NodeIsProperty(nsIDOMNode *aNode);
686 bool HasAttr(nsIDOMNode *aNode, const nsAString *aAttribute);
687 bool IsAtFrontOfNode(nsIDOMNode *aNode, int32_t aOffset);
688 bool IsAtEndOfNode(nsIDOMNode *aNode, int32_t aOffset);
689 bool IsOnlyAttribute(nsIDOMNode *aElement, const nsAString *aAttribute);
690 bool IsOnlyAttribute(const nsIContent* aElement, const nsAString& aAttribute);
692 nsresult RemoveBlockContainer(nsIDOMNode *inNode);
694 nsIContent* GetPriorHTMLSibling(nsINode* aNode);
695 nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
696 nsIContent* GetPriorHTMLSibling(nsINode* aParent, int32_t aOffset);
697 nsresult GetPriorHTMLSibling(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr<nsIDOMNode> *outNode);
699 nsIContent* GetNextHTMLSibling(nsINode* aNode);
700 nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
701 nsIContent* GetNextHTMLSibling(nsINode* aParent, int32_t aOffset);
702 nsresult GetNextHTMLSibling(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr<nsIDOMNode> *outNode);
704 nsIContent* GetPriorHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
705 nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing = false);
706 nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset,
707 bool aNoBlockCrossing = false);
708 nsresult GetPriorHTMLNode(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing = false);
710 nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
711 nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing = false);
712 nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset,
713 bool aNoBlockCrossing = false);
714 nsresult GetNextHTMLNode(nsIDOMNode *inParent, int32_t inOffset, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing = false);
716 nsresult IsFirstEditableChild( nsIDOMNode *aNode, bool *aOutIsFirst);
717 nsresult IsLastEditableChild( nsIDOMNode *aNode, bool *aOutIsLast);
718 nsIContent* GetFirstEditableChild(nsINode& aNode);
719 nsIContent* GetLastEditableChild(nsINode& aNode);
721 nsIContent* GetFirstEditableLeaf(nsINode& aNode);
722 nsIContent* GetLastEditableLeaf(nsINode& aNode);
724 nsresult GetInlinePropertyBase(nsIAtom& aProperty,
725 const nsAString* aAttribute,
726 const nsAString* aValue,
727 bool* aFirst,
728 bool* aAny,
729 bool* aAll,
730 nsAString* outValue,
731 bool aCheckDefaults = true);
732 bool HasStyleOrIdOrClass(mozilla::dom::Element* aElement);
733 nsresult RemoveElementIfNoStyleOrIdOrClass(mozilla::dom::Element& aElement);
735 // Whether the outer window of the DOM event target has focus or not.
736 bool OurWindowHasFocus();
738 // This function is used to insert a string of HTML input optionally with some
739 // context information into the editable field. The HTML input either comes
740 // from a transferable object created as part of a drop/paste operation, or from
741 // the InsertHTML method. We may want the HTML input to be sanitized (for example,
742 // if it's coming from a transferable object), in which case aTrustedInput should
743 // be set to false, otherwise, the caller should set it to true, which means that
744 // the HTML will be inserted in the DOM verbatim.
746 // aClearStyle should be set to false if you want the paste to be affected by
747 // local style (e.g., for the insertHTML command).
748 nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
749 const nsAString& aContextStr,
750 const nsAString& aInfoStr,
751 const nsAString& aFlavor,
752 nsIDOMDocument* aSourceDoc,
753 nsIDOMNode* aDestNode,
754 int32_t aDestOffset,
755 bool aDeleteSelection,
756 bool aTrustedInput,
757 bool aClearStyle = true);
759 nsresult ClearStyle(nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset,
760 nsIAtom* aProperty, const nsAString* aAttribute);
762 void SetElementPosition(mozilla::dom::Element& aElement,
763 int32_t aX, int32_t aY);
765 // Data members
766 protected:
768 nsTArray<mozilla::OwningNonNull<nsIContentFilter>> mContentFilters;
770 RefPtr<TypeInState> mTypeInState;
772 bool mCRInParagraphCreatesParagraph;
774 bool mCSSAware;
775 nsAutoPtr<nsHTMLCSSUtils> mHTMLCSSUtils;
777 // Used by GetFirstSelectedCell and GetNextSelectedCell
778 int32_t mSelectedCellIndex;
780 nsString mLastStyleSheetURL;
781 nsString mLastOverrideStyleSheetURL;
783 // Maintain a list of associated style sheets and their urls.
784 nsTArray<nsString> mStyleSheetURLs;
785 nsTArray<mozilla::StyleSheetHandle::RefPtr> mStyleSheets;
787 // an array for holding default style settings
788 nsTArray<PropItem*> mDefaultStyles;
790 protected:
792 /* ANONYMOUS UTILS */
793 void RemoveListenerAndDeleteRef(const nsAString& aEvent,
794 nsIDOMEventListener* aListener,
795 bool aUseCapture,
796 mozilla::dom::Element* aElement,
797 nsIContent* aParentContent,
798 nsIPresShell* aShell);
799 void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
800 nsIContent * aParentContent,
801 nsIPresShell* aShell);
803 nsresult ShowResizersInner(nsIDOMElement *aResizedElement);
805 // Returns the offset of an element's frame to its absolute containing block.
806 nsresult GetElementOrigin(nsIDOMElement * aElement, int32_t & aX, int32_t & aY);
807 nsresult GetPositionAndDimensions(nsIDOMElement * aElement,
808 int32_t & aX, int32_t & aY,
809 int32_t & aW, int32_t & aH,
810 int32_t & aBorderLeft,
811 int32_t & aBorderTop,
812 int32_t & aMarginLeft,
813 int32_t & aMarginTop);
815 /* PACKED BOOLEANS FOR RESIZING, ABSOLUTE POSITIONING AND */
816 /* INLINE TABLE EDITING */
818 // resizing
819 bool mIsObjectResizingEnabled;
820 bool mIsResizing;
821 bool mPreserveRatio;
822 bool mResizedObjectIsAnImage;
824 // absolute positioning
825 bool mIsAbsolutelyPositioningEnabled;
826 bool mResizedObjectIsAbsolutelyPositioned;
828 bool mGrabberClicked;
829 bool mIsMoving;
831 bool mSnapToGridEnabled;
833 // inline table editing
834 bool mIsInlineTableEditingEnabled;
836 /* RESIZING */
838 nsCOMPtr<mozilla::dom::Element> mTopLeftHandle;
839 nsCOMPtr<mozilla::dom::Element> mTopHandle;
840 nsCOMPtr<mozilla::dom::Element> mTopRightHandle;
841 nsCOMPtr<mozilla::dom::Element> mLeftHandle;
842 nsCOMPtr<mozilla::dom::Element> mRightHandle;
843 nsCOMPtr<mozilla::dom::Element> mBottomLeftHandle;
844 nsCOMPtr<mozilla::dom::Element> mBottomHandle;
845 nsCOMPtr<mozilla::dom::Element> mBottomRightHandle;
847 nsCOMPtr<mozilla::dom::Element> mActivatedHandle;
849 nsCOMPtr<mozilla::dom::Element> mResizingShadow;
850 nsCOMPtr<mozilla::dom::Element> mResizingInfo;
852 nsCOMPtr<mozilla::dom::Element> mResizedObject;
854 nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
855 nsCOMPtr<nsISelectionListener> mSelectionListenerP;
856 nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
858 nsTArray<mozilla::OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners;
860 int32_t mOriginalX;
861 int32_t mOriginalY;
863 int32_t mResizedObjectX;
864 int32_t mResizedObjectY;
865 int32_t mResizedObjectWidth;
866 int32_t mResizedObjectHeight;
868 int32_t mResizedObjectMarginLeft;
869 int32_t mResizedObjectMarginTop;
870 int32_t mResizedObjectBorderLeft;
871 int32_t mResizedObjectBorderTop;
873 int32_t mXIncrementFactor;
874 int32_t mYIncrementFactor;
875 int32_t mWidthIncrementFactor;
876 int32_t mHeightIncrementFactor;
878 int8_t mInfoXIncrement;
879 int8_t mInfoYIncrement;
881 nsresult SetAllResizersPosition();
883 already_AddRefed<mozilla::dom::Element>
884 CreateResizer(int16_t aLocation, nsIDOMNode* aParentNode);
885 void SetAnonymousElementPosition(int32_t aX, int32_t aY, nsIDOMElement *aResizer);
887 already_AddRefed<mozilla::dom::Element>
888 CreateShadow(nsIDOMNode* aParentNode, nsIDOMElement* aOriginalObject);
889 nsresult SetShadowPosition(mozilla::dom::Element* aShadow,
890 mozilla::dom::Element* aOriginalObject,
891 int32_t aOriginalObjectX,
892 int32_t aOriginalObjectY);
894 already_AddRefed<mozilla::dom::Element> CreateResizingInfo(nsIDOMNode* aParentNode);
895 nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
896 int32_t aW, int32_t aH);
898 int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
899 nsresult StartResizing(nsIDOMElement * aHandle);
900 int32_t GetNewResizingX(int32_t aX, int32_t aY);
901 int32_t GetNewResizingY(int32_t aX, int32_t aY);
902 int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
903 int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
904 void HideShadowAndInfo();
905 void SetFinalSize(int32_t aX, int32_t aY);
906 void DeleteRefToAnonymousNode(nsIDOMNode * aNode);
907 void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH, bool aPreserveRatio);
908 void HideAnonymousEditingUIs();
910 /* ABSOLUTE POSITIONING */
912 int32_t mPositionedObjectX;
913 int32_t mPositionedObjectY;
914 int32_t mPositionedObjectWidth;
915 int32_t mPositionedObjectHeight;
917 int32_t mPositionedObjectMarginLeft;
918 int32_t mPositionedObjectMarginTop;
919 int32_t mPositionedObjectBorderLeft;
920 int32_t mPositionedObjectBorderTop;
922 nsCOMPtr<mozilla::dom::Element> mAbsolutelyPositionedObject;
923 nsCOMPtr<mozilla::dom::Element> mGrabber;
924 nsCOMPtr<mozilla::dom::Element> mPositioningShadow;
926 int32_t mGridSize;
928 already_AddRefed<mozilla::dom::Element> CreateGrabber(nsINode* aParentNode);
929 nsresult StartMoving(nsIDOMElement * aHandle);
930 nsresult SetFinalPosition(int32_t aX, int32_t aY);
931 void AddPositioningOffset(int32_t & aX, int32_t & aY);
932 void SnapToGrid(int32_t & newX, int32_t & newY);
933 nsresult GrabberClicked();
934 nsresult EndMoving();
935 nsresult CheckPositionedElementBGandFG(nsIDOMElement * aElement,
936 nsAString & aReturn);
938 /* INLINE TABLE EDITING */
940 nsCOMPtr<nsIDOMElement> mInlineEditedCell;
942 nsCOMPtr<nsIDOMElement> mAddColumnBeforeButton;
943 nsCOMPtr<nsIDOMElement> mRemoveColumnButton;
944 nsCOMPtr<nsIDOMElement> mAddColumnAfterButton;
946 nsCOMPtr<nsIDOMElement> mAddRowBeforeButton;
947 nsCOMPtr<nsIDOMElement> mRemoveRowButton;
948 nsCOMPtr<nsIDOMElement> mAddRowAfterButton;
950 void AddMouseClickListener(nsIDOMElement * aElement);
951 void RemoveMouseClickListener(nsIDOMElement * aElement);
953 nsCOMPtr<nsILinkHandler> mLinkHandler;
955 public:
957 // friends
958 friend class nsHTMLEditRules;
959 friend class nsTextEditRules;
960 friend class nsWSRunObject;
961 friend class nsHTMLEditorEventListener;
963 private:
964 // Helpers
965 bool IsSimpleModifiableNode(nsIContent* aContent,
966 nsIAtom* aProperty,
967 const nsAString* aAttribute,
968 const nsAString* aValue);
969 nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
970 nsIAtom& aProperty,
971 const nsAString* aAttribute,
972 const nsAString& aValue);
973 typedef enum { eInserted, eAppended } InsertedOrAppended;
974 void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
975 nsIContent* aChild, int32_t aIndexInContainer,
976 InsertedOrAppended aInsertedOrAppended);
977 already_AddRefed<mozilla::dom::Element> GetElementOrParentByTagName(
978 const nsAString& aTagName, nsINode* aNode);
979 already_AddRefed<mozilla::dom::Element> CreateElementWithDefaults(
980 const nsAString& aTagName);
982 #endif //nsHTMLEditor_h__