Line data Source code
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/. */
5 :
6 : #ifndef mozilla_HTMLEditor_h
7 : #define mozilla_HTMLEditor_h
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "mozilla/CSSEditUtils.h"
11 : #include "mozilla/StyleSheet.h"
12 : #include "mozilla/TextEditor.h"
13 : #include "mozilla/UniquePtr.h"
14 : #include "mozilla/dom/Element.h"
15 : #include "mozilla/dom/File.h"
16 :
17 : #include "nsAttrName.h"
18 : #include "nsCOMPtr.h"
19 : #include "nsIContentFilter.h"
20 : #include "nsICSSLoaderObserver.h"
21 : #include "nsIDocumentObserver.h"
22 : #include "nsIDOMElement.h"
23 : #include "nsIDOMEventListener.h"
24 : #include "nsIEditorMailSupport.h"
25 : #include "nsIEditorStyleSheets.h"
26 : #include "nsIEditorUtils.h"
27 : #include "nsIEditRules.h"
28 : #include "nsIHTMLAbsPosEditor.h"
29 : #include "nsIHTMLEditor.h"
30 : #include "nsIHTMLInlineTableEditor.h"
31 : #include "nsIHTMLObjectResizer.h"
32 : #include "nsISelectionListener.h"
33 : #include "nsITableEditor.h"
34 : #include "nsPoint.h"
35 : #include "nsStubMutationObserver.h"
36 : #include "nsTArray.h"
37 :
38 : class nsDocumentFragment;
39 : class nsITransferable;
40 : class nsIClipboard;
41 : class nsIDOMMouseEvent;
42 : class nsILinkHandler;
43 : class nsTableWrapperFrame;
44 : class nsIDOMRange;
45 : class nsRange;
46 :
47 : namespace mozilla {
48 :
49 : class HTMLEditorEventListener;
50 : class HTMLEditRules;
51 : class TextEditRules;
52 : class TypeInState;
53 : class WSRunObject;
54 : struct PropItem;
55 : template<class T> class OwningNonNull;
56 : namespace dom {
57 : class DocumentFragment;
58 : } // namespace dom
59 : namespace widget {
60 : struct IMEState;
61 : } // namespace widget
62 :
63 : enum class ParagraphSeparator { div, p, br };
64 :
65 : /**
66 : * The HTML editor implementation.<br>
67 : * Use to edit HTML document represented as a DOM tree.
68 : */
69 : class HTMLEditor final : public TextEditor
70 : , public nsIHTMLEditor
71 : , public nsIHTMLObjectResizer
72 : , public nsIHTMLAbsPosEditor
73 : , public nsITableEditor
74 : , public nsIHTMLInlineTableEditor
75 : , public nsIEditorStyleSheets
76 : , public nsICSSLoaderObserver
77 : , public nsStubMutationObserver
78 : {
79 : private:
80 : enum BlockTransformationType
81 : {
82 : eNoOp,
83 : eReplaceParent = 1,
84 : eInsertParent = 2
85 : };
86 :
87 : const char16_t kNBSP = 160;
88 :
89 : public:
90 : enum ResizingRequestID
91 : {
92 : kX = 0,
93 : kY = 1,
94 : kWidth = 2,
95 : kHeight = 3
96 : };
97 :
98 : NS_DECL_ISUPPORTS_INHERITED
99 0 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
100 :
101 : HTMLEditor();
102 :
103 0 : virtual HTMLEditor* AsHTMLEditor() override { return this; }
104 0 : virtual const HTMLEditor* AsHTMLEditor() const override { return this; }
105 :
106 : bool GetReturnInParagraphCreatesNewParagraph();
107 : Element* GetSelectionContainer();
108 :
109 : // nsIEditor overrides
110 : NS_IMETHOD GetPreferredIMEState(widget::IMEState* aState) override;
111 :
112 : // TextEditor overrides
113 : NS_IMETHOD BeginningOfDocument() override;
114 : virtual nsresult HandleKeyPressEvent(
115 : WidgetKeyboardEvent* aKeyboardEvent) override;
116 : virtual already_AddRefed<nsIContent> GetFocusedContent() override;
117 : virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
118 : virtual bool IsActiveInDOMWindow() override;
119 : virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() override;
120 : virtual Element* GetEditorRoot() override;
121 : virtual already_AddRefed<nsIContent> FindSelectionRoot(
122 : nsINode *aNode) override;
123 : virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
124 : virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
125 : virtual bool IsEditable(nsINode* aNode) override;
126 : using EditorBase::IsEditable;
127 : virtual nsresult RemoveAttributeOrEquivalent(
128 : Element* aElement,
129 : nsIAtom* aAttribute,
130 : bool aSuppressTransaction) override;
131 : virtual nsresult SetAttributeOrEquivalent(Element* aElement,
132 : nsIAtom* aAttribute,
133 : const nsAString& aValue,
134 : bool aSuppressTransaction) override;
135 : using EditorBase::RemoveAttributeOrEquivalent;
136 : using EditorBase::SetAttributeOrEquivalent;
137 :
138 : nsresult MouseMove(nsIDOMMouseEvent* aMouseEvent);
139 :
140 : // nsStubMutationObserver overrides
141 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
142 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
143 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
144 :
145 : // nsIHTMLEditor methods
146 : NS_DECL_NSIHTMLEDITOR
147 :
148 : // nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp)
149 : NS_DECL_NSIHTMLOBJECTRESIZER
150 :
151 : // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
152 : NS_DECL_NSIHTMLABSPOSEDITOR
153 :
154 : // nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
155 : NS_DECL_NSIHTMLINLINETABLEEDITOR
156 :
157 : // XXX Following methods are not overriding but defined here...
158 : nsresult CopyLastEditableChildStyles(nsIDOMNode* aPreviousBlock,
159 : nsIDOMNode* aNewBlock,
160 : Element** aOutBrNode);
161 :
162 : nsresult LoadHTML(const nsAString& aInputString);
163 :
164 : nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
165 : bool aBlockLevel);
166 : NS_IMETHOD GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
167 :
168 : // nsIEditorStyleSheets methods
169 : NS_DECL_NSIEDITORSTYLESHEETS
170 :
171 : // nsIEditorMailSupport methods
172 : NS_DECL_NSIEDITORMAILSUPPORT
173 :
174 : // nsITableEditor methods
175 : NS_DECL_NSITABLEEDITOR
176 :
177 : nsresult GetLastCellInRow(nsIDOMNode* aRowNode,
178 : nsIDOMNode** aCellNode);
179 :
180 : nsresult GetCellFromRange(nsRange* aRange, nsIDOMElement** aCell);
181 :
182 : // Miscellaneous
183 :
184 : /**
185 : * This sets background on the appropriate container element (table, cell,)
186 : * or calls into nsTextEditor to set the page background.
187 : */
188 : nsresult SetCSSBackgroundColor(const nsAString& aColor);
189 : nsresult SetHTMLBackgroundColor(const nsAString& aColor);
190 :
191 : // Block methods moved from EditorBase
192 : static Element* GetBlockNodeParent(nsINode* aNode);
193 : static nsIDOMNode* GetBlockNodeParent(nsIDOMNode* aNode);
194 : static Element* GetBlock(nsINode& aNode);
195 :
196 : void IsNextCharInNodeWhitespace(nsIContent* aContent,
197 : int32_t aOffset,
198 : bool* outIsSpace,
199 : bool* outIsNBSP,
200 : nsIContent** outNode = nullptr,
201 : int32_t* outOffset = 0);
202 : void IsPrevCharInNodeWhitespace(nsIContent* aContent,
203 : int32_t aOffset,
204 : bool* outIsSpace,
205 : bool* outIsNBSP,
206 : nsIContent** outNode = nullptr,
207 : int32_t* outOffset = 0);
208 :
209 : // Overrides of EditorBase interface methods
210 : virtual nsresult EndUpdateViewBatch() override;
211 :
212 : NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
213 : nsISelectionController* aSelCon, uint32_t aFlags,
214 : const nsAString& aValue) override;
215 : NS_IMETHOD PreDestroy(bool aDestroyingFrames) override;
216 :
217 : /**
218 : * @param aElement Must not be null.
219 : */
220 : static bool NodeIsBlockStatic(const nsINode* aElement);
221 : static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock);
222 :
223 : protected:
224 : virtual ~HTMLEditor();
225 :
226 : using EditorBase::IsBlockNode;
227 : virtual bool IsBlockNode(nsINode *aNode) override;
228 :
229 : public:
230 : // XXX Why don't we move following methods above for grouping by the origins?
231 : NS_IMETHOD SetFlags(uint32_t aFlags) override;
232 :
233 : NS_IMETHOD Paste(int32_t aSelectionType) override;
234 : NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
235 :
236 : NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
237 : NS_IMETHOD CanPasteTransferable(nsITransferable* aTransferable,
238 : bool* aCanPaste) override;
239 :
240 : NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
241 : int32_t* outNumTestsFailed) override;
242 :
243 : /**
244 : * All editor operations which alter the doc should be prefaced
245 : * with a call to StartOperation, naming the action and direction.
246 : */
247 : NS_IMETHOD StartOperation(EditAction opID,
248 : nsIEditor::EDirection aDirection) override;
249 :
250 : /**
251 : * All editor operations which alter the doc should be followed
252 : * with a call to EndOperation.
253 : */
254 : NS_IMETHOD EndOperation() override;
255 :
256 : /**
257 : * returns true if aParentTag can contain a child of type aChildTag.
258 : */
259 : virtual bool TagCanContainTag(nsIAtom& aParentTag,
260 : nsIAtom& aChildTag) override;
261 :
262 : /**
263 : * Returns true if aNode is a container.
264 : */
265 : virtual bool IsContainer(nsINode* aNode) override;
266 : virtual bool IsContainer(nsIDOMNode* aNode) override;
267 :
268 : /**
269 : * Make the given selection span the entire document.
270 : */
271 : virtual nsresult SelectEntireDocument(Selection* aSelection) override;
272 :
273 : /**
274 : * Join together any adjacent editable text nodes in the range.
275 : */
276 : nsresult CollapseAdjacentTextNodes(nsRange* aRange);
277 :
278 : virtual bool AreNodesSameType(nsIContent* aNode1,
279 : nsIContent* aNode2) override;
280 :
281 : NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
282 : EStripWrappers aStripWrappers) override;
283 : nsresult DeleteNode(nsINode* aNode);
284 : NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
285 : nsresult DeleteText(nsGenericDOMDataNode& aTextNode, uint32_t aOffset,
286 : uint32_t aLength);
287 : virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
288 : nsCOMPtr<nsINode>* aInOutNode,
289 : int32_t* aInOutOffset,
290 : nsIDocument* aDoc) override;
291 : NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode* aNode) override;
292 : virtual bool IsModifiableNode(nsINode* aNode) override;
293 :
294 : NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable) override;
295 :
296 : NS_IMETHOD SelectAll() override;
297 :
298 : NS_IMETHOD GetRootElement(nsIDOMElement** aRootElement) override;
299 :
300 : // nsICSSLoaderObserver
301 : NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
302 : bool aWasAlternate, nsresult aStatus) override;
303 :
304 : // Utility Routines, not part of public API
305 : NS_IMETHOD TypedText(const nsAString& aString,
306 : ETypingAction aAction) override;
307 : nsresult InsertNodeAtPoint(nsIDOMNode* aNode,
308 : nsCOMPtr<nsIDOMNode>* ioParent,
309 : int32_t* ioOffset,
310 : bool aNoEmptyNodes);
311 :
312 : /**
313 : * Use this to assure that selection is set after attribute nodes when
314 : * trying to collapse selection at begining of a block node
315 : * e.g., when setting at beginning of a table cell
316 : * This will stop at a table, however, since we don't want to
317 : * "drill down" into nested tables.
318 : * @param aSelection Optional. If null, we get current selection.
319 : */
320 : void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
321 : nsINode* aNode);
322 :
323 : /**
324 : * aNode must be a non-null text node.
325 : * outIsEmptyNode must be non-null.
326 : */
327 : nsresult IsVisTextNode(nsIContent* aNode,
328 : bool* outIsEmptyNode,
329 : bool aSafeToAskFrames);
330 : nsresult IsEmptyNode(nsIDOMNode* aNode, bool* outIsEmptyBlock,
331 : bool aMozBRDoesntCount = false,
332 : bool aListOrCellNotEmpty = false,
333 : bool aSafeToAskFrames = false);
334 : nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
335 : bool aMozBRDoesntCount = false,
336 : bool aListOrCellNotEmpty = false,
337 : bool aSafeToAskFrames = false);
338 : nsresult IsEmptyNodeImpl(nsINode* aNode,
339 : bool* outIsEmptyBlock,
340 : bool aMozBRDoesntCount,
341 : bool aListOrCellNotEmpty,
342 : bool aSafeToAskFrames,
343 : bool* aSeenBR);
344 :
345 : /**
346 : * Returns TRUE if sheet was loaded, false if it wasn't.
347 : */
348 : bool EnableExistingStyleSheet(const nsAString& aURL);
349 :
350 : /**
351 : * Dealing with the internal style sheet lists.
352 : */
353 : StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
354 : void GetURLForStyleSheet(StyleSheet* aStyleSheet,
355 : nsAString& aURL);
356 :
357 : /**
358 : * Add a url + known style sheet to the internal lists.
359 : */
360 : nsresult AddNewStyleSheetToList(const nsAString &aURL,
361 : StyleSheet* aStyleSheet);
362 : nsresult RemoveStyleSheetFromList(const nsAString &aURL);
363 :
364 0 : bool IsCSSEnabled()
365 : {
366 : // TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
367 0 : return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
368 : }
369 :
370 0 : static bool HasAttributes(Element* aElement)
371 : {
372 0 : MOZ_ASSERT(aElement);
373 0 : uint32_t attrCount = aElement->GetAttrCount();
374 0 : return attrCount > 1 ||
375 0 : (1 == attrCount &&
376 0 : !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
377 : }
378 :
379 0 : ParagraphSeparator GetDefaultParagraphSeparator() const
380 : {
381 0 : return mDefaultParagraphSeparator;
382 : }
383 0 : void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
384 : {
385 0 : mDefaultParagraphSeparator = aSep;
386 0 : }
387 :
388 : protected:
389 : class BlobReader final : public nsIEditorBlobListener
390 : {
391 : public:
392 : BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
393 : bool aIsSafe, nsIDOMDocument* aSourceDoc,
394 : nsIDOMNode* aDestinationNode, int32_t aDestOffset,
395 : bool aDoDeleteSelection);
396 :
397 : NS_DECL_ISUPPORTS
398 : NS_DECL_NSIEDITORBLOBLISTENER
399 :
400 : private:
401 0 : ~BlobReader()
402 0 : {
403 0 : }
404 :
405 : RefPtr<dom::BlobImpl> mBlob;
406 : RefPtr<HTMLEditor> mHTMLEditor;
407 : bool mIsSafe;
408 : nsCOMPtr<nsIDOMDocument> mSourceDoc;
409 : nsCOMPtr<nsIDOMNode> mDestinationNode;
410 : int32_t mDestOffset;
411 : bool mDoDeleteSelection;
412 : };
413 :
414 : NS_IMETHOD InitRules() override;
415 :
416 : virtual void CreateEventListeners() override;
417 : virtual nsresult InstallEventListeners() override;
418 : virtual void RemoveEventListeners() override;
419 :
420 : bool ShouldReplaceRootElement();
421 : void ResetRootElementAndEventTarget();
422 : nsresult GetBodyElement(nsIDOMHTMLElement** aBody);
423 :
424 : /**
425 : * Get the focused node of this editor.
426 : * @return If the editor has focus, this returns the focused node.
427 : * Otherwise, returns null.
428 : */
429 : already_AddRefed<nsINode> GetFocusedNode();
430 :
431 : /**
432 : * Return TRUE if aElement is a table-related elemet and caret was set.
433 : */
434 : bool SetCaretInTableCell(nsIDOMElement* aElement);
435 :
436 : NS_IMETHOD TabInTable(bool inIsShift, bool* outHandled);
437 : already_AddRefed<Element> CreateBR(nsINode* aNode, int32_t aOffset,
438 : EDirection aSelect = eNone);
439 : NS_IMETHOD CreateBR(
440 : nsIDOMNode* aNode, int32_t aOffset,
441 : nsCOMPtr<nsIDOMNode>* outBRNode,
442 : nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
443 :
444 : nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
445 :
446 : // Table Editing (implemented in nsTableEditor.cpp)
447 :
448 : /**
449 : * Insert a new cell after or before supplied aCell.
450 : * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
451 : * of course)
452 : * This doesn't change or use the current selection.
453 : */
454 : NS_IMETHOD InsertCell(nsIDOMElement* aCell, int32_t aRowSpan,
455 : int32_t aColSpan, bool aAfter, bool aIsHeader,
456 : nsIDOMElement** aNewCell);
457 :
458 : /**
459 : * Helpers that don't touch the selection or do batch transactions.
460 : */
461 : NS_IMETHOD DeleteRow(nsIDOMElement* aTable, int32_t aRowIndex);
462 : NS_IMETHOD DeleteColumn(nsIDOMElement* aTable, int32_t aColIndex);
463 : NS_IMETHOD DeleteCellContents(nsIDOMElement* aCell);
464 :
465 : /**
466 : * Move all contents from aCellToMerge into aTargetCell (append at end).
467 : */
468 : NS_IMETHOD MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
469 : nsCOMPtr<nsIDOMElement> aCellToMerge,
470 : bool aDeleteCellToMerge);
471 :
472 : nsresult DeleteTable2(nsIDOMElement* aTable, Selection* aSelection);
473 : NS_IMETHOD SetColSpan(nsIDOMElement* aCell, int32_t aColSpan);
474 : NS_IMETHOD SetRowSpan(nsIDOMElement* aCell, int32_t aRowSpan);
475 :
476 : /**
477 : * Helper used to get nsTableWrapperFrame for a table.
478 : */
479 : nsTableWrapperFrame* GetTableFrame(nsIDOMElement* aTable);
480 :
481 : /**
482 : * Needed to do appropriate deleting when last cell or row is about to be
483 : * deleted. This doesn't count cells that don't start in the given row (are
484 : * spanning from row above).
485 : */
486 : int32_t GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex);
487 :
488 : /**
489 : * Test if all cells in row or column at given index are selected.
490 : */
491 : bool AllCellsInRowSelected(nsIDOMElement* aTable, int32_t aRowIndex,
492 : int32_t aNumberOfColumns);
493 : bool AllCellsInColumnSelected(nsIDOMElement* aTable, int32_t aColIndex,
494 : int32_t aNumberOfRows);
495 :
496 : bool IsEmptyCell(Element* aCell);
497 :
498 : /**
499 : * Most insert methods need to get the same basic context data.
500 : * Any of the pointers may be null if you don't need that datum (for more
501 : * efficiency).
502 : * Input: *aCell is a known cell,
503 : * if null, cell is obtained from the anchor node of the selection.
504 : * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
505 : * null.
506 : */
507 : nsresult GetCellContext(Selection** aSelection, nsIDOMElement** aTable,
508 : nsIDOMElement** aCell, nsIDOMNode** aCellParent,
509 : int32_t* aCellOffset, int32_t* aRowIndex,
510 : int32_t* aColIndex);
511 :
512 : NS_IMETHOD GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex,
513 : int32_t aColIndex, int32_t& aActualRowSpan,
514 : int32_t& aActualColSpan);
515 :
516 : NS_IMETHOD SplitCellIntoColumns(nsIDOMElement* aTable, int32_t aRowIndex,
517 : int32_t aColIndex, int32_t aColSpanLeft,
518 : int32_t aColSpanRight,
519 : nsIDOMElement** aNewCell);
520 :
521 : NS_IMETHOD SplitCellIntoRows(nsIDOMElement* aTable, int32_t aRowIndex,
522 : int32_t aColIndex, int32_t aRowSpanAbove,
523 : int32_t aRowSpanBelow, nsIDOMElement** aNewCell);
524 :
525 : nsresult CopyCellBackgroundColor(nsIDOMElement* destCell,
526 : nsIDOMElement* sourceCell);
527 :
528 : /**
529 : * Reduce rowspan/colspan when cells span into nonexistent rows/columns.
530 : */
531 : NS_IMETHOD FixBadRowSpan(nsIDOMElement* aTable, int32_t aRowIndex,
532 : int32_t& aNewRowCount);
533 : NS_IMETHOD FixBadColSpan(nsIDOMElement* aTable, int32_t aColIndex,
534 : int32_t& aNewColCount);
535 :
536 : /**
537 : * Fallback method: Call this after using ClearSelection() and you
538 : * failed to set selection to some other content in the document.
539 : */
540 : nsresult SetSelectionAtDocumentStart(Selection* aSelection);
541 :
542 : // End of Table Editing utilities
543 :
544 : static Element* GetEnclosingTable(nsINode* aNode);
545 : static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
546 :
547 : /**
548 : * Content-based query returns true if <aProperty aAttribute=aValue> effects
549 : * aNode. If <aProperty aAttribute=aValue> contains aNode, but
550 : * <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
551 : * more deeply nested than the first, then the first does not effect aNode.
552 : *
553 : * @param aNode The target of the query
554 : * @param aProperty The property that we are querying for
555 : * @param aAttribute The attribute of aProperty, example: color in
556 : * <FONT color="blue"> May be null.
557 : * @param aValue The value of aAttribute, example: blue in
558 : * <FONT color="blue"> May be null. Ignored if aAttribute
559 : * is null.
560 : * @param aIsSet [OUT] true if <aProperty aAttribute=aValue> effects
561 : * aNode.
562 : * @param outValue [OUT] the value of the attribute, if aIsSet is true
563 : *
564 : * The nsIContent variant returns aIsSet instead of using an out parameter.
565 : */
566 : bool IsTextPropertySetByContent(nsINode* aNode,
567 : nsIAtom* aProperty,
568 : const nsAString* aAttribute,
569 : const nsAString* aValue,
570 : nsAString* outValue = nullptr);
571 :
572 : void IsTextPropertySetByContent(nsIDOMNode* aNode,
573 : nsIAtom* aProperty,
574 : const nsAString* aAttribute,
575 : const nsAString* aValue,
576 : bool& aIsSet,
577 : nsAString* outValue = nullptr);
578 :
579 : // Methods for handling plaintext quotations
580 : NS_IMETHOD PasteAsPlaintextQuotation(int32_t aSelectionType);
581 :
582 : /**
583 : * Insert a string as quoted text, replacing the selected text (if any).
584 : * @param aQuotedText The string to insert.
585 : * @param aAddCites Whether to prepend extra ">" to each line
586 : * (usually true, unless those characters
587 : * have already been added.)
588 : * @return aNodeInserted The node spanning the insertion, if applicable.
589 : * If aAddCites is false, this will be null.
590 : */
591 : NS_IMETHOD InsertAsPlaintextQuotation(const nsAString& aQuotedText,
592 : bool aAddCites,
593 : nsIDOMNode** aNodeInserted);
594 :
595 : nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
596 : bool aIsSafe,
597 : nsIDOMDocument* aSourceDoc,
598 : nsIDOMNode* aDestinationNode,
599 : int32_t aDestOffset,
600 : bool aDoDeleteSelection);
601 :
602 : // factored methods for handling insertion of data from transferables
603 : // (drag&drop or clipboard)
604 : NS_IMETHOD PrepareTransferable(nsITransferable** transferable) override;
605 : nsresult PrepareHTMLTransferable(nsITransferable** transferable);
606 : nsresult InsertFromTransferable(nsITransferable* transferable,
607 : nsIDOMDocument* aSourceDoc,
608 : const nsAString& aContextStr,
609 : const nsAString& aInfoStr,
610 : bool havePrivateHTMLFlavor,
611 : nsIDOMNode *aDestinationNode,
612 : int32_t aDestinationOffset,
613 : bool aDoDeleteSelection);
614 : virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
615 : int32_t aIndex,
616 : nsIDOMDocument* aSourceDoc,
617 : nsIDOMNode* aDestinationNode,
618 : int32_t aDestOffset,
619 : bool aDoDeleteSelection) override;
620 : bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
621 : nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
622 : char16_t** aCfcontext);
623 : nsresult DoContentFilterCallback(const nsAString& aFlavor,
624 : nsIDOMDocument* aSourceDoc,
625 : bool aWillDeleteSelection,
626 : nsIDOMNode** aFragmentAsNode,
627 : nsIDOMNode** aFragStartNode,
628 : int32_t* aFragStartOffset,
629 : nsIDOMNode** aFragEndNode,
630 : int32_t* aFragEndOffset,
631 : nsIDOMNode** aTargetNode,
632 : int32_t* aTargetOffset,
633 : bool* aDoContinue);
634 :
635 : bool IsInLink(nsIDOMNode* aNode, nsCOMPtr<nsIDOMNode>* outLink = nullptr);
636 : nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
637 : nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
638 : const nsAString& aContextStr,
639 : const nsAString& aInfoStr,
640 : nsCOMPtr<nsIDOMNode>* outFragNode,
641 : nsCOMPtr<nsIDOMNode>* outStartNode,
642 : nsCOMPtr<nsIDOMNode>* outEndNode,
643 : int32_t* outStartOffset,
644 : int32_t* outEndOffset,
645 : bool aTrustedInput);
646 : nsresult ParseFragment(const nsAString& aStr, nsIAtom* aContextLocalName,
647 : nsIDocument* aTargetDoc,
648 : dom::DocumentFragment** aFragment, bool aTrustedInput);
649 : void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
650 : nsTArray<OwningNonNull<nsINode>>& outNodeList,
651 : nsINode* aStartContainer,
652 : int32_t aStartOffset,
653 : nsINode* aEndContainer,
654 : int32_t aEndOffset);
655 : nsresult CreateTagStack(nsTArray<nsString>& aTagStack,
656 : nsIDOMNode* aNode);
657 : enum class StartOrEnd { start, end };
658 : void GetListAndTableParents(StartOrEnd aStartOrEnd,
659 : nsTArray<OwningNonNull<nsINode>>& aNodeList,
660 : nsTArray<OwningNonNull<Element>>& outArray);
661 : int32_t DiscoverPartialListsAndTables(
662 : nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
663 : nsTArray<OwningNonNull<Element>>& aListsAndTables);
664 : nsINode* ScanForListAndTableStructure(
665 : StartOrEnd aStartOrEnd,
666 : nsTArray<OwningNonNull<nsINode>>& aNodes,
667 : Element& aListOrTable);
668 : void ReplaceOrphanedStructure(
669 : StartOrEnd aStartOrEnd,
670 : nsTArray<OwningNonNull<nsINode>>& aNodeArray,
671 : nsTArray<OwningNonNull<Element>>& aListAndTableArray,
672 : int32_t aHighWaterMark);
673 :
674 : /**
675 : * Small utility routine to test if a break node is visible to user.
676 : */
677 : bool IsVisBreak(nsINode* aNode);
678 :
679 : /**
680 : * Utility routine to possibly adjust the insertion position when
681 : * inserting a block level element.
682 : */
683 : void NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
684 : nsCOMPtr<nsIDOMNode>* insertParentNode,
685 : int32_t* insertOffset);
686 :
687 : /**
688 : * Helpers for block transformations.
689 : */
690 : nsresult MakeDefinitionItem(const nsAString& aItemType);
691 : nsresult InsertBasicBlock(const nsAString& aBlockType);
692 :
693 : /**
694 : * Increase/decrease the font size of selection.
695 : */
696 : enum class FontSize { incr, decr };
697 : nsresult RelativeFontChange(FontSize aDir);
698 :
699 : /**
700 : * Helper routines for font size changing.
701 : */
702 : nsresult RelativeFontChangeOnTextNode(FontSize aDir,
703 : Text& aTextNode,
704 : int32_t aStartOffset,
705 : int32_t aEndOffset);
706 : nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
707 : nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
708 :
709 : /**
710 : * Helper routines for inline style.
711 : */
712 : nsresult SetInlinePropertyOnTextNode(Text& aData,
713 : int32_t aStartOffset,
714 : int32_t aEndOffset,
715 : nsIAtom& aProperty,
716 : const nsAString* aAttribute,
717 : const nsAString& aValue);
718 : nsresult SetInlinePropertyOnNode(nsIContent& aNode,
719 : nsIAtom& aProperty,
720 : const nsAString* aAttribute,
721 : const nsAString& aValue);
722 :
723 : nsresult PromoteInlineRange(nsRange& aRange);
724 : nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
725 : nsresult SplitStyleAboveRange(nsRange* aRange,
726 : nsIAtom* aProperty,
727 : const nsAString* aAttribute);
728 : nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
729 : nsIAtom* aProperty,
730 : const nsAString* aAttribute,
731 : nsIContent** aOutLeftNode = nullptr,
732 : nsIContent** aOutRightNode = nullptr);
733 : nsresult ApplyDefaultProperties();
734 : nsresult RemoveStyleInside(nsIContent& aNode,
735 : nsIAtom* aProperty,
736 : const nsAString* aAttribute,
737 : const bool aChildrenOnly = false);
738 : nsresult RemoveInlinePropertyImpl(nsIAtom* aProperty,
739 : const nsAString* aAttribute);
740 :
741 : bool NodeIsProperty(nsINode& aNode);
742 : bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
743 : bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
744 : bool IsOnlyAttribute(const nsIContent* aElement, const nsAString& aAttribute);
745 :
746 : nsresult RemoveBlockContainer(nsIContent& aNode);
747 :
748 : nsIContent* GetPriorHTMLSibling(nsINode* aNode);
749 : nsresult GetPriorHTMLSibling(nsIDOMNode*inNode,
750 : nsCOMPtr<nsIDOMNode>* outNode);
751 : nsIContent* GetPriorHTMLSibling(nsINode* aParent, int32_t aOffset);
752 : nsresult GetPriorHTMLSibling(nsIDOMNode* inParent, int32_t inOffset,
753 : nsCOMPtr<nsIDOMNode>* outNode);
754 :
755 : nsIContent* GetNextHTMLSibling(nsINode* aNode);
756 : nsresult GetNextHTMLSibling(nsIDOMNode* inNode,
757 : nsCOMPtr<nsIDOMNode>* outNode);
758 : nsIContent* GetNextHTMLSibling(nsINode* aParent, int32_t aOffset);
759 : nsresult GetNextHTMLSibling(nsIDOMNode* inParent, int32_t inOffset,
760 : nsCOMPtr<nsIDOMNode>* outNode);
761 :
762 : nsIContent* GetPriorHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
763 : nsresult GetPriorHTMLNode(nsIDOMNode* inNode, nsCOMPtr<nsIDOMNode>* outNode,
764 : bool bNoBlockCrossing = false);
765 : nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset,
766 : bool aNoBlockCrossing = false);
767 : nsresult GetPriorHTMLNode(nsIDOMNode* inParent, int32_t inOffset,
768 : nsCOMPtr<nsIDOMNode>* outNode,
769 : bool bNoBlockCrossing = false);
770 :
771 : nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
772 : nsresult GetNextHTMLNode(nsIDOMNode* inNode, nsCOMPtr<nsIDOMNode>* outNode,
773 : bool bNoBlockCrossing = false);
774 : nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset,
775 : bool aNoBlockCrossing = false);
776 : nsresult GetNextHTMLNode(nsIDOMNode* inParent, int32_t inOffset,
777 : nsCOMPtr<nsIDOMNode>* outNode,
778 : bool bNoBlockCrossing = false);
779 :
780 : bool IsFirstEditableChild(nsINode* aNode);
781 : bool IsLastEditableChild(nsINode* aNode);
782 : nsIContent* GetFirstEditableChild(nsINode& aNode);
783 : nsIContent* GetLastEditableChild(nsINode& aNode);
784 :
785 : nsIContent* GetFirstEditableLeaf(nsINode& aNode);
786 : nsIContent* GetLastEditableLeaf(nsINode& aNode);
787 :
788 : nsresult GetInlinePropertyBase(nsIAtom& aProperty,
789 : const nsAString* aAttribute,
790 : const nsAString* aValue,
791 : bool* aFirst,
792 : bool* aAny,
793 : bool* aAll,
794 : nsAString* outValue,
795 : bool aCheckDefaults = true);
796 : bool HasStyleOrIdOrClass(Element* aElement);
797 : nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
798 :
799 : /**
800 : * Whether the outer window of the DOM event target has focus or not.
801 : */
802 : bool OurWindowHasFocus();
803 :
804 : /**
805 : * This function is used to insert a string of HTML input optionally with some
806 : * context information into the editable field. The HTML input either comes
807 : * from a transferable object created as part of a drop/paste operation, or
808 : * from the InsertHTML method. We may want the HTML input to be sanitized
809 : * (for example, if it's coming from a transferable object), in which case
810 : * aTrustedInput should be set to false, otherwise, the caller should set it
811 : * to true, which means that the HTML will be inserted in the DOM verbatim.
812 : *
813 : * aClearStyle should be set to false if you want the paste to be affected by
814 : * local style (e.g., for the insertHTML command).
815 : */
816 : nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
817 : const nsAString& aContextStr,
818 : const nsAString& aInfoStr,
819 : const nsAString& aFlavor,
820 : nsIDOMDocument* aSourceDoc,
821 : nsIDOMNode* aDestNode,
822 : int32_t aDestOffset,
823 : bool aDeleteSelection,
824 : bool aTrustedInput,
825 : bool aClearStyle = true);
826 :
827 : nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
828 : nsIAtom* aProperty, const nsAString* aAttribute);
829 :
830 : void SetElementPosition(Element& aElement, int32_t aX, int32_t aY);
831 :
832 : protected:
833 : nsTArray<OwningNonNull<nsIContentFilter>> mContentFilters;
834 :
835 : RefPtr<TypeInState> mTypeInState;
836 :
837 : bool mCRInParagraphCreatesParagraph;
838 :
839 : bool mCSSAware;
840 : UniquePtr<CSSEditUtils> mCSSEditUtils;
841 :
842 : // Used by GetFirstSelectedCell and GetNextSelectedCell
843 : int32_t mSelectedCellIndex;
844 :
845 : nsString mLastStyleSheetURL;
846 : nsString mLastOverrideStyleSheetURL;
847 :
848 : // Maintain a list of associated style sheets and their urls.
849 : nsTArray<nsString> mStyleSheetURLs;
850 : nsTArray<RefPtr<StyleSheet>> mStyleSheets;
851 :
852 : // an array for holding default style settings
853 : nsTArray<PropItem*> mDefaultStyles;
854 :
855 : protected:
856 : // ANONYMOUS UTILS
857 : void RemoveListenerAndDeleteRef(const nsAString& aEvent,
858 : nsIDOMEventListener* aListener,
859 : bool aUseCapture,
860 : Element* aElement,
861 : nsIPresShell* aShell);
862 : void DeleteRefToAnonymousNode(nsIContent* aContent,
863 : nsIPresShell* aShell);
864 :
865 : nsresult ShowResizersInner(nsIDOMElement *aResizedElement);
866 :
867 : /**
868 : * Returns the offset of an element's frame to its absolute containing block.
869 : */
870 : nsresult GetElementOrigin(nsIDOMElement* aElement,
871 : int32_t& aX, int32_t& aY);
872 : nsresult GetPositionAndDimensions(nsIDOMElement* aElement,
873 : int32_t& aX, int32_t& aY,
874 : int32_t& aW, int32_t& aH,
875 : int32_t& aBorderLeft,
876 : int32_t& aBorderTop,
877 : int32_t& aMarginLeft,
878 : int32_t& aMarginTop);
879 :
880 : bool IsInObservedSubtree(nsIDocument* aDocument,
881 : nsIContent* aContainer,
882 : nsIContent* aChild);
883 :
884 : // resizing
885 : bool mIsObjectResizingEnabled;
886 : bool mIsResizing;
887 : bool mPreserveRatio;
888 : bool mResizedObjectIsAnImage;
889 :
890 : // absolute positioning
891 : bool mIsAbsolutelyPositioningEnabled;
892 : bool mResizedObjectIsAbsolutelyPositioned;
893 :
894 : bool mGrabberClicked;
895 : bool mIsMoving;
896 :
897 : bool mSnapToGridEnabled;
898 :
899 : // inline table editing
900 : bool mIsInlineTableEditingEnabled;
901 :
902 : // resizing
903 : nsCOMPtr<Element> mTopLeftHandle;
904 : nsCOMPtr<Element> mTopHandle;
905 : nsCOMPtr<Element> mTopRightHandle;
906 : nsCOMPtr<Element> mLeftHandle;
907 : nsCOMPtr<Element> mRightHandle;
908 : nsCOMPtr<Element> mBottomLeftHandle;
909 : nsCOMPtr<Element> mBottomHandle;
910 : nsCOMPtr<Element> mBottomRightHandle;
911 :
912 : nsCOMPtr<Element> mActivatedHandle;
913 :
914 : nsCOMPtr<Element> mResizingShadow;
915 : nsCOMPtr<Element> mResizingInfo;
916 :
917 : nsCOMPtr<Element> mResizedObject;
918 :
919 : nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
920 : nsCOMPtr<nsISelectionListener> mSelectionListenerP;
921 : nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
922 :
923 : int32_t mOriginalX;
924 : int32_t mOriginalY;
925 :
926 : int32_t mResizedObjectX;
927 : int32_t mResizedObjectY;
928 : int32_t mResizedObjectWidth;
929 : int32_t mResizedObjectHeight;
930 :
931 : int32_t mResizedObjectMarginLeft;
932 : int32_t mResizedObjectMarginTop;
933 : int32_t mResizedObjectBorderLeft;
934 : int32_t mResizedObjectBorderTop;
935 :
936 : int32_t mXIncrementFactor;
937 : int32_t mYIncrementFactor;
938 : int32_t mWidthIncrementFactor;
939 : int32_t mHeightIncrementFactor;
940 :
941 : int8_t mInfoXIncrement;
942 : int8_t mInfoYIncrement;
943 :
944 : nsresult SetAllResizersPosition();
945 :
946 : already_AddRefed<Element> CreateResizer(int16_t aLocation,
947 : nsIDOMNode* aParentNode);
948 : void SetAnonymousElementPosition(int32_t aX, int32_t aY,
949 : Element* aResizer);
950 :
951 : already_AddRefed<Element> CreateShadow(nsIDOMNode* aParentNode,
952 : nsIDOMElement* aOriginalObject);
953 : nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
954 : int32_t aOriginalObjectX,
955 : int32_t aOriginalObjectY);
956 :
957 : already_AddRefed<Element> CreateResizingInfo(nsIDOMNode* aParentNode);
958 : nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
959 : int32_t aW, int32_t aH);
960 :
961 : int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
962 : nsresult StartResizing(nsIDOMElement* aHandle);
963 : int32_t GetNewResizingX(int32_t aX, int32_t aY);
964 : int32_t GetNewResizingY(int32_t aX, int32_t aY);
965 : int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
966 : int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
967 : void HideShadowAndInfo();
968 : void SetFinalSize(int32_t aX, int32_t aY);
969 : void DeleteRefToAnonymousNode(nsIDOMNode* aNode);
970 : void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
971 : bool aPreserveRatio);
972 : void HideAnonymousEditingUIs();
973 :
974 : // absolute positioning
975 : int32_t mPositionedObjectX;
976 : int32_t mPositionedObjectY;
977 : int32_t mPositionedObjectWidth;
978 : int32_t mPositionedObjectHeight;
979 :
980 : int32_t mPositionedObjectMarginLeft;
981 : int32_t mPositionedObjectMarginTop;
982 : int32_t mPositionedObjectBorderLeft;
983 : int32_t mPositionedObjectBorderTop;
984 :
985 : nsCOMPtr<Element> mAbsolutelyPositionedObject;
986 : nsCOMPtr<Element> mGrabber;
987 : nsCOMPtr<Element> mPositioningShadow;
988 :
989 : int32_t mGridSize;
990 :
991 : already_AddRefed<Element> CreateGrabber(nsINode* aParentNode);
992 : nsresult StartMoving(nsIDOMElement* aHandle);
993 : nsresult SetFinalPosition(int32_t aX, int32_t aY);
994 : void AddPositioningOffset(int32_t& aX, int32_t& aY);
995 : void SnapToGrid(int32_t& newX, int32_t& newY);
996 : nsresult GrabberClicked();
997 : nsresult EndMoving();
998 : nsresult CheckPositionedElementBGandFG(nsIDOMElement* aElement,
999 : nsAString& aReturn);
1000 :
1001 : // inline table editing
1002 : nsCOMPtr<nsIDOMElement> mInlineEditedCell;
1003 :
1004 : RefPtr<Element> mAddColumnBeforeButton;
1005 : RefPtr<Element> mRemoveColumnButton;
1006 : RefPtr<Element> mAddColumnAfterButton;
1007 :
1008 : RefPtr<Element> mAddRowBeforeButton;
1009 : RefPtr<Element> mRemoveRowButton;
1010 : RefPtr<Element> mAddRowAfterButton;
1011 :
1012 : void AddMouseClickListener(Element* aElement);
1013 : void RemoveMouseClickListener(Element* aElement);
1014 :
1015 : nsCOMPtr<nsILinkHandler> mLinkHandler;
1016 :
1017 : ParagraphSeparator mDefaultParagraphSeparator;
1018 :
1019 : public:
1020 : friend class HTMLEditorEventListener;
1021 : friend class HTMLEditRules;
1022 : friend class TextEditRules;
1023 : friend class WSRunObject;
1024 :
1025 : private:
1026 : bool IsSimpleModifiableNode(nsIContent* aContent,
1027 : nsIAtom* aProperty,
1028 : const nsAString* aAttribute,
1029 : const nsAString* aValue);
1030 : nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
1031 : nsIAtom& aProperty,
1032 : const nsAString* aAttribute,
1033 : const nsAString& aValue);
1034 : typedef enum { eInserted, eAppended } InsertedOrAppended;
1035 : void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
1036 : nsIContent* aChild, int32_t aIndexInContainer,
1037 : InsertedOrAppended aInsertedOrAppended);
1038 : already_AddRefed<Element> GetElementOrParentByTagName(
1039 : const nsAString& aTagName, nsINode* aNode);
1040 : already_AddRefed<Element> CreateElementWithDefaults(
1041 : const nsAString& aTagName);
1042 : /**
1043 : * Returns an anonymous Element of type aTag,
1044 : * child of aParentNode. If aIsCreatedHidden is true, the class
1045 : * "hidden" is added to the created element. If aAnonClass is not
1046 : * the empty string, it becomes the value of the attribute "_moz_anonclass"
1047 : * @return a Element
1048 : * @param aTag [IN] desired type of the element to create
1049 : * @param aParentNode [IN] the parent node of the created anonymous
1050 : * element
1051 : * @param aAnonClass [IN] contents of the _moz_anonclass attribute
1052 : * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
1053 : * is to be added to the created anonymous
1054 : * element
1055 : */
1056 : already_AddRefed<Element> CreateAnonymousElement(
1057 : nsIAtom* aTag,
1058 : nsIDOMNode* aParentNode,
1059 : const nsAString& aAnonClass,
1060 : bool aIsCreatedHidden);
1061 : };
1062 :
1063 : } // namespace mozilla
1064 :
1065 : #endif // #ifndef mozilla_HTMLEditor_h
|