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__
10 #include "nsPlaintextEditor.h"
11 #include "nsIEditor.h"
12 #include "nsIHTMLEditor.h"
13 #include "nsITableEditor.h"
14 #include "nsIEditorMailSupport.h"
15 #include "nsIEditorStyleSheets.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"
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
;
46 class nsITransferable
;
49 class nsIContentFilter
;
51 class nsTableOuterFrame
;
57 template<class T
> class OwningNonNull
;
59 class DocumentFragment
;
64 } // namespace mozilla
67 * The HTML editor implementation.<br>
68 * Use to edit HTML document represented as a DOM tree.
70 class nsHTMLEditor final
: public nsPlaintextEditor
,
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
;
84 enum ResizingRequestID
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
)
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
,
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
;
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
,
243 nsIContent
** outNode
= nullptr,
244 int32_t* outOffset
= 0);
245 void IsPrevCharInNodeWhitespace(nsIContent
* aContent
,
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
);
267 virtual ~nsHTMLEditor();
269 using nsEditor::IsBlockNode
;
270 virtual bool IsBlockNode(nsINode
*aNode
) override
;
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
)
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
)
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
,
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
,
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
,
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
,
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
);
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
));
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
);
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)
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">
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
,
520 const nsAString
* aAttribute
,
521 const nsAString
* aValue
,
522 nsAString
* outValue
= nullptr);
524 void IsTextPropertySetByContent(nsIDOMNode
* aNode
,
526 const nsAString
* aAttribute
,
527 const nsAString
* aValue
,
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
,
545 nsIDOMNode
**aNodeInserted
);
547 nsresult
InsertObject(const char* aType
, nsISupports
* aObject
, bool aIsSafe
,
548 nsIDOMDocument
*aSourceDoc
,
549 nsIDOMNode
*aDestinationNode
,
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
,
566 nsIDOMDocument
*aSourceDoc
,
567 nsIDOMNode
*aDestinationNode
,
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
,
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
,
595 nsresult
ParseFragment(const nsAString
& aStr
, nsIAtom
* aContextLocalName
,
596 nsIDocument
* aTargetDoc
,
597 mozilla::dom::DocumentFragment
** aFragment
,
599 void CreateListOfNodesToPaste(mozilla::dom::DocumentFragment
& aFragment
,
600 nsTArray
<mozilla::OwningNonNull
<nsINode
>>& outNodeList
,
602 int32_t aStartOffset
,
605 nsresult
CreateTagStack(nsTArray
<nsString
> &aTagStack
,
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 */
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
,
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
,
655 const nsAString
* aAttribute
,
656 const nsAString
& aValue
);
657 nsresult
SetInlinePropertyOnNode(nsIContent
& aNode
,
659 const nsAString
* aAttribute
,
660 const nsAString
& aValue
);
662 nsresult
PromoteInlineRange(nsRange
* aRange
);
663 nsresult
PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange
* aRange
);
664 nsresult
SplitStyleAboveRange(nsRange
* aRange
,
666 const nsAString
*aAttribute
);
667 nsresult
SplitStyleAbovePoint(nsCOMPtr
<nsIDOMNode
> *aNode
,
670 const nsAString
*aAttribute
,
671 nsCOMPtr
<nsIDOMNode
> *outLeftNode
= nullptr,
672 nsCOMPtr
<nsIDOMNode
> *outRightNode
= nullptr);
673 nsresult
ApplyDefaultProperties();
674 nsresult
RemoveStyleInside(nsIDOMNode
*aNode
,
676 const nsAString
*aAttribute
,
677 const bool aChildrenOnly
= false);
678 nsresult
RemoveStyleInside(nsIContent
& aNode
,
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
,
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
,
755 bool aDeleteSelection
,
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
);
768 nsTArray
<mozilla::OwningNonNull
<nsIContentFilter
>> mContentFilters
;
770 RefPtr
<TypeInState
> mTypeInState
;
772 bool mCRInParagraphCreatesParagraph
;
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
;
792 /* ANONYMOUS UTILS */
793 void RemoveListenerAndDeleteRef(const nsAString
& aEvent
,
794 nsIDOMEventListener
* aListener
,
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 */
819 bool mIsObjectResizingEnabled
;
822 bool mResizedObjectIsAnImage
;
824 // absolute positioning
825 bool mIsAbsolutelyPositioningEnabled
;
826 bool mResizedObjectIsAbsolutelyPositioned
;
828 bool mGrabberClicked
;
831 bool mSnapToGridEnabled
;
833 // inline table editing
834 bool mIsInlineTableEditingEnabled
;
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
;
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
;
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
;
958 friend class nsHTMLEditRules
;
959 friend class nsTextEditRules
;
960 friend class nsWSRunObject
;
961 friend class nsHTMLEditorEventListener
;
965 bool IsSimpleModifiableNode(nsIContent
* aContent
,
967 const nsAString
* aAttribute
,
968 const nsAString
* aValue
);
969 nsresult
SetInlinePropertyOnNodeImpl(nsIContent
& aNode
,
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__