Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/HTMLEditor.h
Line
Count
Source (jump to first uncovered line)
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/ComposerCommandsUpdater.h"
11
#include "mozilla/CSSEditUtils.h"
12
#include "mozilla/ManualNAC.h"
13
#include "mozilla/StyleSheet.h"
14
#include "mozilla/TextEditor.h"
15
#include "mozilla/UniquePtr.h"
16
#include "mozilla/dom/Element.h"
17
#include "mozilla/dom/File.h"
18
19
#include "nsAttrName.h"
20
#include "nsCOMPtr.h"
21
#include "nsICSSLoaderObserver.h"
22
#include "nsIDocumentObserver.h"
23
#include "nsIDOMEventListener.h"
24
#include "nsIEditorMailSupport.h"
25
#include "nsIEditorStyleSheets.h"
26
#include "nsIHTMLAbsPosEditor.h"
27
#include "nsIHTMLEditor.h"
28
#include "nsIHTMLInlineTableEditor.h"
29
#include "nsIHTMLObjectResizer.h"
30
#include "nsITableEditor.h"
31
#include "nsPoint.h"
32
#include "nsStubMutationObserver.h"
33
#include "nsTArray.h"
34
35
class nsDocumentFragment;
36
class nsHTMLDocument;
37
class nsITransferable;
38
class nsIClipboard;
39
class nsILinkHandler;
40
class nsTableWrapperFrame;
41
class nsRange;
42
43
namespace mozilla {
44
class AutoSelectionSetterAfterTableEdit;
45
class DocumentResizeEventListener;
46
class EmptyEditableFunctor;
47
class ResizerSelectionListener;
48
enum class EditSubAction : int32_t;
49
struct PropItem;
50
template<class T> class OwningNonNull;
51
namespace dom {
52
class Blob;
53
class DocumentFragment;
54
class Event;
55
class MouseEvent;
56
} // namespace dom
57
namespace widget {
58
struct IMEState;
59
} // namespace widget
60
61
enum class ParagraphSeparator { div, p, br };
62
63
/**
64
 * The HTML editor implementation.<br>
65
 * Use to edit HTML document represented as a DOM tree.
66
 */
67
class HTMLEditor final : public TextEditor
68
                       , public nsIHTMLEditor
69
                       , public nsIHTMLObjectResizer
70
                       , public nsIHTMLAbsPosEditor
71
                       , public nsITableEditor
72
                       , public nsIHTMLInlineTableEditor
73
                       , public nsIEditorStyleSheets
74
                       , public nsStubMutationObserver
75
                       , public nsIEditorMailSupport
76
{
77
public:
78
  /****************************************************************************
79
   * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
80
   *       classes under libeditor except EditorEventListener and
81
   *       HTMLEditorEventListener because each public method which may fire
82
   *       eEditorInput event will need to instantiate new stack class for
83
   *       managing input type value of eEditorInput and cache some objects
84
   *       for smarter handling.  In other words, when you add new root
85
   *       method to edit the DOM tree, you can make your new method public.
86
   ****************************************************************************/
87
88
  NS_DECL_ISUPPORTS_INHERITED
89
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
90
91
  // nsStubMutationObserver overrides
92
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
93
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
94
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
95
96
  // nsIHTMLEditor methods
97
  NS_DECL_NSIHTMLEDITOR
98
99
  // nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp)
100
  NS_DECL_NSIHTMLOBJECTRESIZER
101
102
  // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
103
  NS_DECL_NSIHTMLABSPOSEDITOR
104
105
  // nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
106
  NS_DECL_NSIHTMLINLINETABLEEDITOR
107
108
  // nsIEditorStyleSheets methods
109
  NS_DECL_NSIEDITORSTYLESHEETS
110
111
  // nsIEditorMailSupport methods
112
  NS_DECL_NSIEDITORMAILSUPPORT
113
114
  // nsITableEditor methods
115
  NS_DECL_NSITABLEEDITOR
116
117
  // nsISelectionListener overrides
118
  NS_DECL_NSISELECTIONLISTENER
119
120
  HTMLEditor();
121
122
  nsHTMLDocument* GetHTMLDocument() const;
123
124
  virtual void PreDestroy(bool aDestroyingFrames) override;
125
126
  bool GetReturnInParagraphCreatesNewParagraph();
127
128
  // TextEditor overrides
129
  virtual nsresult Init(nsIDocument& aDoc, Element* aRoot,
130
                        nsISelectionController* aSelCon, uint32_t aFlags,
131
                        const nsAString& aValue) override;
132
  NS_IMETHOD BeginningOfDocument() override;
133
  NS_IMETHOD SetFlags(uint32_t aFlags) override;
134
135
  NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
136
137
  NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
138
139
  NS_IMETHOD DeleteNode(nsINode* aNode) override;
140
141
  NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
142
                            int32_t* outNumTestsFailed) override;
143
144
  virtual nsresult HandleKeyPressEvent(
145
                     WidgetKeyboardEvent* aKeyboardEvent) override;
146
  virtual nsIContent* GetFocusedContent() override;
147
  virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
148
  virtual bool IsActiveInDOMWindow() override;
149
  virtual dom::EventTarget* GetDOMEventTarget() override;
150
  virtual already_AddRefed<nsIContent> FindSelectionRoot(
151
                                         nsINode *aNode) override;
152
  virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
153
  virtual nsresult GetPreferredIMEState(widget::IMEState* aState) override;
154
155
  /**
156
   * PasteAsQuotationAsAction() pastes content in clipboard with newly created
157
   * blockquote element.  If the editor is in plaintext mode, will paste the
158
   * content with appending ">" to start of each line.
159
   *
160
   * @param aClipboardType      nsIClipboard::kGlobalClipboard or
161
   *                            nsIClipboard::kSelectionClipboard.
162
   */
163
  virtual nsresult PasteAsQuotationAsAction(int32_t aClipboardType) override;
164
165
  /**
166
   * Can we paste |aTransferable| or, if |aTransferable| is null, will a call
167
   * to pasteTransferable later possibly succeed if given an instance of
168
   * nsITransferable then? True if the doc is modifiable, and, if
169
   * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
170
   */
171
  virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
172
173
  /**
174
   * OnInputLineBreak() is called when user inputs a line break with
175
   * Shift + Enter or something.
176
   */
177
  nsresult OnInputLineBreak();
178
179
  /**
180
   * CreateElementWithDefaults() creates new element whose name is
181
   * aTagName with some default attributes are set.  Note that this is a
182
   * public utility method.  I.e., just creates element, not insert it
183
   * into the DOM tree.
184
   * NOTE: This is available for internal use too since this does not change
185
   *       the DOM tree nor undo transactions, and does not refer Selection,
186
   *       HTMLEditRules, etc.
187
   *
188
   * @param aTagName            The new element's tag name.  If the name is
189
   *                            one of "href", "anchor" or "namedanchor",
190
   *                            this creates an <a> element.
191
   * @return                    Newly created element.
192
   */
193
  already_AddRefed<Element> CreateElementWithDefaults(const nsAtom& aTagName);
194
195
  /**
196
   * Indent or outdent content around Selection.
197
   */
198
  nsresult IndentAsAction();
199
  nsresult OutdentAsAction();
200
201
  /**
202
   * event callback when a mouse button is pressed
203
   * @param aX      [IN] horizontal position of the pointer
204
   * @param aY      [IN] vertical position of the pointer
205
   * @param aTarget [IN] the element triggering the event
206
   * @param aMouseEvent [IN] the event
207
   */
208
  nsresult OnMouseDown(int32_t aX, int32_t aY, Element* aTarget,
209
                       dom::Event* aMouseEvent);
210
211
  /**
212
   * event callback when a mouse button is released
213
   * @param aX      [IN] horizontal position of the pointer
214
   * @param aY      [IN] vertical position of the pointer
215
   * @param aTarget [IN] the element triggering the event
216
   */
217
  nsresult OnMouseUp(int32_t aX, int32_t aY, Element* aTarget);
218
219
  /**
220
   * event callback when the mouse pointer is moved
221
   * @param aMouseEvent [IN] the event
222
   */
223
  nsresult OnMouseMove(dom::MouseEvent* aMouseEvent);
224
225
  /**
226
   * IsCSSEnabled() returns true if this editor treats styles with style
227
   * attribute of HTML elements.  Otherwise, if this editor treats all styles
228
   * with "font style elements" like <b>, <i>, etc, and <blockquote> to indent,
229
   * align attribute to align contents, returns false.
230
   */
231
  bool IsCSSEnabled() const
232
0
  {
233
0
    // TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
234
0
    return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
235
0
  }
236
237
238
  /**
239
   * Enable/disable object resizers for <img> elements, <table> elements,
240
   * absolute positioned elements (required absolute position editor enabled).
241
   */
242
  void EnableObjectResizer(bool aEnable)
243
0
  {
244
0
    if (mIsObjectResizingEnabled == aEnable) {
245
0
      return;
246
0
    }
247
0
    mIsObjectResizingEnabled = aEnable;
248
0
    RefPtr<Selection> selection = GetSelection();
249
0
    if (NS_WARN_IF(!selection)) {
250
0
      return;
251
0
    }
252
0
    RefereshEditingUI(*selection);
253
0
  }
254
  bool IsObjectResizerEnabled() const
255
0
  {
256
0
    return mIsObjectResizingEnabled;
257
0
  }
258
259
  /**
260
   * Enable/disable inline table editor, e.g., adding new row or column,
261
   * removing existing row or column.
262
   */
263
  void EnableInlineTableEditor(bool aEnable)
264
0
  {
265
0
    if (mIsInlineTableEditingEnabled == aEnable) {
266
0
      return;
267
0
    }
268
0
    mIsInlineTableEditingEnabled = aEnable;
269
0
    RefPtr<Selection> selection = GetSelection();
270
0
    if (NS_WARN_IF(!selection)) {
271
0
      return;
272
0
    }
273
0
    RefereshEditingUI(*selection);
274
0
  }
275
  bool IsInlineTableEditorEnabled() const
276
0
  {
277
0
    return mIsInlineTableEditingEnabled;
278
0
  }
279
280
  /**
281
   * Enable/disable absolute position editor, resizing absolute positioned
282
   * elements (required object resizers enabled) or positioning them with
283
   * dragging grabber.
284
   */
285
  void EnableAbsolutePositionEditor(bool aEnable)
286
0
  {
287
0
    if (mIsAbsolutelyPositioningEnabled == aEnable) {
288
0
      return;
289
0
    }
290
0
    mIsAbsolutelyPositioningEnabled = aEnable;
291
0
    RefPtr<Selection> selection = GetSelection();
292
0
    if (NS_WARN_IF(!selection)) {
293
0
      return;
294
0
    }
295
0
    RefereshEditingUI(*selection);
296
0
  }
297
  bool IsAbsolutePositionEditorEnabled() const
298
0
  {
299
0
    return mIsAbsolutelyPositioningEnabled;
300
0
  }
301
302
  // non-virtual methods of interface methods
303
304
  /**
305
   * returns the deepest absolutely positioned container of the selection
306
   * if it exists or null.
307
   */
308
  already_AddRefed<Element> GetAbsolutelyPositionedSelectionContainer();
309
310
  Element* GetPositionedElement() const
311
0
  {
312
0
    return mAbsolutelyPositionedObject;
313
0
  }
314
315
  /**
316
   * extracts the selection from the normal flow of the document and
317
   * positions it.
318
   * @param aEnabled [IN] true to absolutely position the selection,
319
   *                      false to put it back in the normal flow
320
   */
321
  nsresult SetSelectionToAbsoluteOrStatic(bool aEnabled);
322
323
  /**
324
   * returns the absolute z-index of a positioned element. Never returns 'auto'
325
   * @return         the z-index of the element
326
   * @param aElement [IN] the element.
327
   */
328
  int32_t GetZIndex(Element& aElement);
329
330
  /**
331
   * adds aChange to the z-index of the currently positioned element.
332
   * @param aChange [IN] relative change to apply to current z-index
333
   */
334
  nsresult AddZIndex(int32_t aChange);
335
336
  nsresult SetInlineProperty(nsAtom& aProperty,
337
                             nsAtom* aAttribute,
338
                             const nsAString& aValue)
339
0
  {
340
0
    nsresult rv = SetInlinePropertyInternal(aProperty, aAttribute, aValue);
341
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
342
0
      return rv;
343
0
    }
344
0
    return NS_OK;
345
0
  }
346
347
  nsresult GetInlineProperty(nsAtom* aProperty,
348
                             nsAtom* aAttribute,
349
                             const nsAString& aValue,
350
                             bool* aFirst,
351
                             bool* aAny,
352
                             bool* aAll);
353
  nsresult GetInlinePropertyWithAttrValue(nsAtom* aProperty,
354
                                          nsAtom* aAttr,
355
                                          const nsAString& aValue,
356
                                          bool* aFirst,
357
                                          bool* aAny,
358
                                          bool* aAll,
359
                                          nsAString& outValue);
360
  nsresult RemoveInlineProperty(nsAtom* aProperty,
361
                                nsAtom* aAttribute)
362
0
  {
363
0
    nsresult rv = RemoveInlinePropertyInternal(aProperty, aAttribute);
364
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
365
0
      return rv;
366
0
    }
367
0
    return NS_OK;
368
0
  }
369
370
  /**
371
   * GetFontColorState() returns foreground color information in first
372
   * range of Selection.
373
   * If first range of Selection is collapsed and there is a cache of style for
374
   * new text, aIsMixed is set to false and aColor is set to the cached color.
375
   * If first range of Selection is collapsed and there is no cached color,
376
   * this returns the color of the node, aIsMixed is set to false and aColor is
377
   * set to the color.
378
   * If first range of Selection is not collapsed, this collects colors of
379
   * each node in the range.  If there are two or more colors, aIsMixed is set
380
   * to true and aColor is truncated.  If only one color is set to all of the
381
   * range, aIsMixed is set to false and aColor is set to the color.
382
   * If there is no Selection ranges, aIsMixed is set to false and aColor is
383
   * truncated.
384
   *
385
   * @param aIsMixed            Must not be nullptr.  This is set to true
386
   *                            if there is two or more colors in first
387
   *                            range of Selection.
388
   * @param aColor              Returns the color if only one color is set to
389
   *                            all of first range in Selection.  Otherwise,
390
   *                            returns empty string.
391
   * @return                    Returns error only when illegal cases, e.g.,
392
   *                            Selection instance has gone, first range
393
   *                            Selection is broken.
394
   */
395
  nsresult GetFontColorState(bool* aIsMixed, nsAString& aColor);
396
397
  /**
398
   * SetComposerCommandsUpdater() sets or unsets mComposerCommandsUpdater.
399
   * This will crash in debug build if the editor already has an instance
400
   * but called with another instance.
401
   */
402
  void SetComposerCommandsUpdater(
403
         ComposerCommandsUpdater* aComposerCommandsUpdater)
404
0
  {
405
0
    MOZ_ASSERT(!aComposerCommandsUpdater || !mComposerCommandsUpdater ||
406
0
               aComposerCommandsUpdater == mComposerCommandsUpdater);
407
0
    mComposerCommandsUpdater = aComposerCommandsUpdater;
408
0
  }
409
410
  ParagraphSeparator GetDefaultParagraphSeparator() const
411
0
  {
412
0
    return mDefaultParagraphSeparator;
413
0
  }
414
  void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
415
0
  {
416
0
    mDefaultParagraphSeparator = aSep;
417
0
  }
418
419
  /**
420
   * Modifies the table containing the selection according to the
421
   * activation of an inline table editing UI element
422
   * @param aUIAnonymousElement [IN] the inline table editing UI element
423
   */
424
  nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
425
426
  /**
427
   * GetElementOrParentByTagName() looks for an element node whose name matches
428
   * aTagName from aNode or anchor node of Selection to <body> element.
429
   *
430
   * @param aTagName        The tag name which you want to look for.
431
   *                        Must not be nsGkAtoms::_empty.
432
   *                        If nsGkAtoms::list, the result may be <ul>, <ol> or
433
   *                        <dl> element.
434
   *                        If nsGkAtoms::td, the result may be <td> or <th>.
435
   *                        If nsGkAtoms::href, the result may be <a> element
436
   *                        which has "href" attribute with non-empty value.
437
   *                        If nsGkAtoms::anchor, the result may be <a> which
438
   *                        has "name" attribute with non-empty value.
439
   * @param aNode           If non-nullptr, this starts to look for the result
440
   *                        from it.  Otherwise, i.e., nullptr, starts from
441
   *                        anchor node of Selection.
442
   * @return                If an element which matches aTagName, returns
443
   *                        an Element.  Otherwise, nullptr.
444
   */
445
  Element*
446
  GetElementOrParentByTagName(const nsAtom& aTagName, nsINode* aNode) const;
447
448
  /**
449
    * Get an active editor's editing host in DOM window.  If this editor isn't
450
    * active in the DOM window, this returns NULL.
451
    */
452
  Element* GetActiveEditingHost() const;
453
454
  /** Insert a string as quoted text
455
    * (whose representation is dependant on the editor type),
456
    * replacing the selected text (if any).
457
    *
458
    * @param aQuotedText    The actual text to be quoted
459
    * @parem aNodeInserted  Return the node which was inserted.
460
    */
461
  nsresult InsertAsQuotation(const nsAString& aQuotedText,
462
                             nsINode** aNodeInserted);
463
464
  /**
465
   * Inserts a plaintext string at the current location,
466
   * with special processing for lines beginning with ">",
467
   * which will be treated as mail quotes and inserted
468
   * as plaintext quoted blocks.
469
   * If the selection is not collapsed, the selection is deleted
470
   * and the insertion takes place at the resulting collapsed selection.
471
   *
472
   * @param aString   the string to be inserted
473
   */
474
   nsresult InsertTextWithQuotations(const nsAString& aStringToInsert);
475
476
protected: // May be called by friends.
477
  /****************************************************************************
478
   * Some classes like TextEditRules, HTMLEditRules, WSRunObject which are
479
   * part of handling edit actions are allowed to call the following protected
480
   * methods.  However, those methods won't prepare caches of some objects
481
   * which are necessary for them.  So, if you want some following methods
482
   * to do that for you, you need to create a wrapper method in public scope
483
   * and call it.
484
   ****************************************************************************/
485
486
  /**
487
   * DeleteSelectionWithTransaction() removes selected content or content
488
   * around caret with transactions.
489
   *
490
   * @param aDirection          How much range should be removed.
491
   * @param aStripWrappers      Whether the parent blocks should be removed
492
   *                            when they become empty.
493
   */
494
  virtual nsresult
495
  DeleteSelectionWithTransaction(EDirection aAction,
496
                                 EStripWrappers aStripWrappers) override;
497
498
  /**
499
   * DeleteNodeWithTransaction() removes aNode from the DOM tree if it's
500
   * modifiable.  Note that this is not an override of same method of
501
   * EditorBase.
502
   *
503
   * @param aNode       The node to be removed from the DOM tree.
504
   */
505
  nsresult DeleteNodeWithTransaction(nsINode& aNode);
506
507
  /**
508
   * DeleteTextWithTransaction() removes text in the range from aCharData if
509
   * it's modifiable.  Note that this not an override of same method of
510
   * EditorBase.
511
   *
512
   * @param aCharData           The data node which should be modified.
513
   * @param aOffset             Start offset of removing text in aCharData.
514
   * @param aLength             Length of removing text.
515
   */
516
  nsresult DeleteTextWithTransaction(dom::CharacterData& aTextNode,
517
                                     uint32_t aOffset, uint32_t aLength);
518
519
  /**
520
   * InsertTextWithTransaction() inserts aStringToInsert at aPointToInsert.
521
   */
522
  virtual nsresult
523
  InsertTextWithTransaction(nsIDocument& aDocument,
524
                            const nsAString& aStringToInsert,
525
                            const EditorRawDOMPoint& aPointToInsert,
526
                            EditorRawDOMPoint* aPointAfterInsertedString =
527
                              nullptr) override;
528
529
  /**
530
   * CopyLastEditableChildStyles() clones inline container elements into
531
   * aPreviousBlock to aNewBlock to keep using same style in it.
532
   *
533
   * @param aPreviousBlock      The previous block element.  All inline
534
   *                            elements which are last sibling of each level
535
   *                            are cloned to aNewBlock.
536
   * @param aNewBlock           New block container element.
537
   * @param aNewBrElement       If this method creates a new <br> element for
538
   *                            placeholder, this is set to the new <br>
539
   *                            element.
540
   */
541
  nsresult
542
  CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock,
543
                                             Element& aNewBlock,
544
                                             RefPtr<Element>* aNewBrElement);
545
546
  /**
547
   * RemoveBlockContainerWithTransaction() removes aElement from the DOM tree
548
   * but moves its all children to its parent node and if its parent needs <br>
549
   * element to have at least one line-height, this inserts <br> element
550
   * automatically.
551
   *
552
   * @param aElement            Block element to be removed.
553
   */
554
  nsresult RemoveBlockContainerWithTransaction(Element& aElement);
555
556
  virtual Element* GetEditorRoot() const override;
557
  using EditorBase::IsEditable;
558
  virtual nsresult RemoveAttributeOrEquivalent(
559
                     Element* aElement,
560
                     nsAtom* aAttribute,
561
                     bool aSuppressTransaction) override;
562
  virtual nsresult SetAttributeOrEquivalent(Element* aElement,
563
                                            nsAtom* aAttribute,
564
                                            const nsAString& aValue,
565
                                            bool aSuppressTransaction) override;
566
  using EditorBase::RemoveAttributeOrEquivalent;
567
  using EditorBase::SetAttributeOrEquivalent;
568
569
  /**
570
   * GetBlockNodeParent() returns parent or nearest ancestor of aNode if
571
   * there is a block parent.  If aAncestorLimiter is not nullptr,
572
   * this stops looking for the result.
573
   */
574
  static Element* GetBlockNodeParent(nsINode* aNode,
575
                                     nsINode* aAncestorLimiter = nullptr);
576
577
  /**
578
   * GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
579
   * if there is a block parent.  If aAncestorLimiter is not nullptr,
580
   * this stops looking for the result.
581
   */
582
  static Element* GetBlock(nsINode& aNode,
583
                           nsINode* aAncestorLimiter = nullptr);
584
585
  /**
586
   * Returns container element of ranges in Selection.  If Selection is
587
   * collapsed, returns focus container node (or its parent element).
588
   * If Selection selects only one element node, returns the element node.
589
   * If Selection is only one range, returns common ancestor of the range.
590
   * XXX If there are two or more Selection ranges, this returns parent node
591
   *     of start container of a range which starts with different node from
592
   *     start container of the first range.
593
   */
594
  Element* GetSelectionContainerElement(Selection& aSelection) const;
595
596
  /**
597
   * GetFirstSelectedTableCellElement() returns a <td> or <th> element if
598
   * first range of Selection (i.e., result of Selection::GetRangeAt(0))
599
   * selects a <td> element or <th> element.  Even if Selection is in
600
   * a cell element, this returns nullptr.  And even if 2nd or later
601
   * range of Selection selects a cell element, also returns nullptr.
602
   * Note that when this looks for a cell element, this resets the internal
603
   * index of ranges of Selection.  When you call
604
   * GetNextSelectedTableCellElement() after a call of this, it'll return 2nd
605
   * selected cell if there is.
606
   *
607
   * @param aSelection          Selection for this editor.
608
   * @param aRv                 Returns error if there is no selection or
609
   *                            first range of Selection is unexpected.
610
   * @return                    A <td> or <th> element is selected by first
611
   *                            range of Selection.  Note that the range must
612
   *                            be: startContaienr and endContainer are same
613
   *                            <tr> element, startOffset + 1 equals endOffset.
614
   */
615
  already_AddRefed<Element>
616
  GetFirstSelectedTableCellElement(Selection& aSelection,
617
                                   ErrorResult& aRv) const;
618
619
  /**
620
   * GetNextSelectedTableCellElement() is a stateful method to retrieve
621
   * selected table cell elements which are selected by 2nd or later ranges
622
   * of Selection.  When you call GetFirstSelectedTableCellElement(), it
623
   * resets internal counter of this method.  Then, following calls of
624
   * GetNextSelectedTableCellElement() scans the remaining ranges of Selection.
625
   * If a range selects a <td> or <th> element, returns the cell element.
626
   * If a range selects an element but neither <td> nor <th> element, this
627
   * ignores the range.  If a range is in a text node, returns null without
628
   * throwing exception, but stops scanning the remaining ranges even you
629
   * call this again.
630
   * Note that this may cross <table> boundaries since this method just
631
   * scans all ranges of Selection.  Therefore, returning cells which
632
   * belong to different <table> elements.
633
   *
634
   * @param Selection           Selection for this editor.
635
   * @param aRv                 Returns error if Selection doesn't have
636
   *                            range properly.
637
   * @return                    A <td> or <th> element if one of remaining
638
   *                            ranges selects a <td> or <th> element unless
639
   *                            this does not meet a range in a text node.
640
   */
641
  already_AddRefed<Element>
642
  GetNextSelectedTableCellElement(Selection& aSelection,
643
                                  ErrorResult& aRv) const;
644
645
  /**
646
   * DeleteTableCellContentsWithTransaction() removes any contents in cell
647
   * elements.  If two or more cell elements are selected, this removes
648
   * all selected cells' contents.  Otherwise, this removes contents of
649
   * a cell which contains first selection range.  This does not return
650
   * error even if selection is not in cell element, just does nothing.
651
   */
652
  nsresult DeleteTableCellContentsWithTransaction();
653
654
  void IsNextCharInNodeWhitespace(nsIContent* aContent,
655
                                  int32_t aOffset,
656
                                  bool* outIsSpace,
657
                                  bool* outIsNBSP,
658
                                  nsIContent** outNode = nullptr,
659
                                  int32_t* outOffset = 0);
660
  void IsPrevCharInNodeWhitespace(nsIContent* aContent,
661
                                  int32_t aOffset,
662
                                  bool* outIsSpace,
663
                                  bool* outIsNBSP,
664
                                  nsIContent** outNode = nullptr,
665
                                  int32_t* outOffset = 0);
666
667
  /**
668
   * @param aElement        Must not be null.
669
   */
670
  static bool NodeIsBlockStatic(const nsINode* aElement);
671
672
  /**
673
   * extracts an element from the normal flow of the document and
674
   * positions it, and puts it back in the normal flow.
675
   * @param aElement [IN] the element
676
   * @param aEnabled [IN] true to absolutely position the element,
677
   *                      false to put it back in the normal flow
678
   */
679
  nsresult SetPositionToAbsoluteOrStatic(Element& aElement,
680
                                         bool aEnabled);
681
682
  /**
683
   * adds aChange to the z-index of an arbitrary element.
684
   * @param aElement [IN] the element
685
   * @param aChange  [IN] relative change to apply to current z-index of
686
   *                      the element
687
   * @param aReturn  [OUT] the new z-index of the element
688
   */
689
  nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
690
                                       int32_t* aReturn);
691
692
  virtual bool IsBlockNode(nsINode *aNode) override;
693
  using EditorBase::IsBlockNode;
694
695
  /**
696
   * returns true if aParentTag can contain a child of type aChildTag.
697
   */
698
  virtual bool TagCanContainTag(nsAtom& aParentTag,
699
                                nsAtom& aChildTag) const override;
700
701
  /**
702
   * Returns true if aNode is a container.
703
   */
704
  virtual bool IsContainer(nsINode* aNode) override;
705
706
  /**
707
   * Join together any adjacent editable text nodes in the range.
708
   */
709
  nsresult CollapseAdjacentTextNodes(nsRange* aRange);
710
711
  /**
712
   * IsInVisibleTextFrames() returns true if all text in aText is in visible
713
   * text frames.  Callers have to guarantee that there is no pending reflow.
714
   */
715
  bool IsInVisibleTextFrames(dom::Text& aText);
716
717
  /**
718
   * IsVisibleTextNode() returns true if aText has visible text.  If it has
719
   * only whitespaces and they are collapsed, returns false.
720
   */
721
  bool IsVisibleTextNode(Text& aText);
722
723
  /**
724
   * aNode must be a non-null text node.
725
   * outIsEmptyNode must be non-null.
726
   */
727
  nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
728
                       bool aMozBRDoesntCount = false,
729
                       bool aListOrCellNotEmpty = false,
730
                       bool aSafeToAskFrames = false);
731
  nsresult IsEmptyNodeImpl(nsINode* aNode,
732
                           bool* outIsEmptyBlock,
733
                           bool aMozBRDoesntCount,
734
                           bool aListOrCellNotEmpty,
735
                           bool aSafeToAskFrames,
736
                           bool* aSeenBR);
737
738
  static bool HasAttributes(Element* aElement)
739
0
  {
740
0
    MOZ_ASSERT(aElement);
741
0
    uint32_t attrCount = aElement->GetAttrCount();
742
0
    return attrCount > 1 ||
743
0
           (1 == attrCount &&
744
0
            !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
745
0
  }
746
747
  /**
748
   * Content-based query returns true if <aProperty aAttribute=aValue> effects
749
   * aNode.  If <aProperty aAttribute=aValue> contains aNode, but
750
   * <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
751
   * more deeply nested than the first, then the first does not effect aNode.
752
   *
753
   * @param aNode      The target of the query
754
   * @param aProperty  The property that we are querying for
755
   * @param aAttribute The attribute of aProperty, example: color in
756
   *                   <FONT color="blue"> May be null.
757
   * @param aValue     The value of aAttribute, example: blue in
758
   *                   <FONT color="blue"> May be null.  Ignored if aAttribute
759
   *                   is null.
760
   * @param outValue   [OUT] the value of the attribute, if aIsSet is true
761
   * @return           true if <aProperty aAttribute=aValue> effects
762
   *                   aNode.
763
   *
764
   * The nsIContent variant returns aIsSet instead of using an out parameter.
765
   */
766
  bool IsTextPropertySetByContent(nsINode* aNode,
767
                                  nsAtom* aProperty,
768
                                  nsAtom* aAttribute,
769
                                  const nsAString* aValue,
770
                                  nsAString* outValue = nullptr);
771
772
  static dom::Element* GetLinkElement(nsINode* aNode);
773
774
  /**
775
   * Small utility routine to test if a break node is visible to user.
776
   */
777
  bool IsVisibleBRElement(nsINode* aNode);
778
779
  /**
780
   * Helper routines for font size changing.
781
   */
782
  enum class FontSize { incr, decr };
783
  nsresult RelativeFontChangeOnTextNode(FontSize aDir,
784
                                        Text& aTextNode,
785
                                        int32_t aStartOffset,
786
                                        int32_t aEndOffset);
787
788
  nsresult SetInlinePropertyOnNode(nsIContent& aNode,
789
                                   nsAtom& aProperty,
790
                                   nsAtom* aAttribute,
791
                                   const nsAString& aValue);
792
793
  nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
794
                                nsAtom* aProperty,
795
                                nsAtom* aAttribute,
796
                                nsIContent** aOutLeftNode = nullptr,
797
                                nsIContent** aOutRightNode = nullptr);
798
799
  nsIContent* GetPriorHTMLSibling(nsINode* aNode);
800
801
  nsIContent* GetNextHTMLSibling(nsINode* aNode);
802
803
  /**
804
   * GetPreviousHTMLElementOrText*() methods are similar to
805
   * EditorBase::GetPreviousElementOrText*() but this won't return nodes
806
   * outside active editing host.
807
   */
808
  nsIContent* GetPreviousHTMLElementOrText(nsINode& aNode)
809
0
  {
810
0
    return GetPreviousHTMLElementOrTextInternal(aNode, false);
811
0
  }
812
  nsIContent* GetPreviousHTMLElementOrTextInBlock(nsINode& aNode)
813
0
  {
814
0
    return GetPreviousHTMLElementOrTextInternal(aNode, true);
815
0
  }
816
  template<typename PT, typename CT>
817
  nsIContent*
818
  GetPreviousHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
819
  {
820
    return GetPreviousHTMLElementOrTextInternal(aPoint, false);
821
  }
822
  template<typename PT, typename CT>
823
  nsIContent*
824
  GetPreviousHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
825
  {
826
    return GetPreviousHTMLElementOrTextInternal(aPoint, true);
827
  }
828
829
  /**
830
   * GetPreviousHTMLElementOrTextInternal() methods are common implementation
831
   * of above methods.  Please don't use this method directly.
832
   */
833
  nsIContent* GetPreviousHTMLElementOrTextInternal(nsINode& aNode,
834
                                                   bool aNoBlockCrossing);
835
  template<typename PT, typename CT>
836
  nsIContent*
837
  GetPreviousHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
838
                                       bool aNoBlockCrossing);
839
840
  /**
841
   * GetPreviousEditableHTMLNode*() methods are similar to
842
   * EditorBase::GetPreviousEditableNode() but this won't return nodes outside
843
   * active editing host.
844
   */
845
  nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode)
846
0
  {
847
0
    return GetPreviousEditableHTMLNodeInternal(aNode, false);
848
0
  }
849
  nsIContent* GetPreviousEditableHTMLNodeInBlock(nsINode& aNode)
850
0
  {
851
0
    return GetPreviousEditableHTMLNodeInternal(aNode, true);
852
0
  }
853
  template<typename PT, typename CT>
854
  nsIContent*
855
  GetPreviousEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
856
0
  {
857
0
    return GetPreviousEditableHTMLNodeInternal(aPoint, false);
858
0
  }
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetPreviousEditableHTMLNode<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&)
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetPreviousEditableHTMLNode<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&)
859
  template<typename PT, typename CT>
860
  nsIContent* GetPreviousEditableHTMLNodeInBlock(
861
                const EditorDOMPointBase<PT, CT>& aPoint)
862
0
  {
863
0
    return GetPreviousEditableHTMLNodeInternal(aPoint, true);
864
0
  }
865
866
  /**
867
   * GetPreviousEditableHTMLNodeInternal() methods are common implementation
868
   * of above methods.  Please don't use this method directly.
869
   */
870
  nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode,
871
                                                  bool aNoBlockCrossing);
872
  template<typename PT, typename CT>
873
  nsIContent* GetPreviousEditableHTMLNodeInternal(
874
                const EditorDOMPointBase<PT, CT>& aPoint,
875
                bool aNoBlockCrossing);
876
877
  /**
878
   * GetNextHTMLElementOrText*() methods are similar to
879
   * EditorBase::GetNextElementOrText*() but this won't return nodes outside
880
   * active editing host.
881
   *
882
   * Note that same as EditorBase::GetTextEditableNode(), methods which take
883
   * |const EditorRawDOMPoint&| start to search from the node pointed by it.
884
   * On the other hand, methods which take |nsINode&| start to search from
885
   * next node of aNode.
886
   */
887
  nsIContent* GetNextHTMLElementOrText(nsINode& aNode)
888
0
  {
889
0
    return GetNextHTMLElementOrTextInternal(aNode, false);
890
0
  }
891
  nsIContent* GetNextHTMLElementOrTextInBlock(nsINode& aNode)
892
0
  {
893
0
    return GetNextHTMLElementOrTextInternal(aNode, true);
894
0
  }
895
  template<typename PT, typename CT>
896
  nsIContent*
897
  GetNextHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
898
  {
899
    return GetNextHTMLElementOrTextInternal(aPoint, false);
900
  }
901
  template<typename PT, typename CT>
902
  nsIContent*
903
  GetNextHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
904
  {
905
    return GetNextHTMLElementOrTextInternal(aPoint, true);
906
  }
907
908
  /**
909
   * GetNextHTMLNodeInternal() methods are common implementation
910
   * of above methods.  Please don't use this method directly.
911
   */
912
  nsIContent* GetNextHTMLElementOrTextInternal(nsINode& aNode,
913
                                               bool aNoBlockCrossing);
914
  template<typename PT, typename CT>
915
  nsIContent*
916
  GetNextHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
917
                                   bool aNoBlockCrossing);
918
919
  /**
920
   * GetNextEditableHTMLNode*() methods are similar to
921
   * EditorBase::GetNextEditableNode() but this won't return nodes outside
922
   * active editing host.
923
   *
924
   * Note that same as EditorBase::GetTextEditableNode(), methods which take
925
   * |const EditorRawDOMPoint&| start to search from the node pointed by it.
926
   * On the other hand, methods which take |nsINode&| start to search from
927
   * next node of aNode.
928
   */
929
  nsIContent* GetNextEditableHTMLNode(nsINode& aNode)
930
0
  {
931
0
    return GetNextEditableHTMLNodeInternal(aNode, false);
932
0
  }
933
  nsIContent* GetNextEditableHTMLNodeInBlock(nsINode& aNode)
934
0
  {
935
0
    return GetNextEditableHTMLNodeInternal(aNode, true);
936
0
  }
937
  template<typename PT, typename CT>
938
  nsIContent* GetNextEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
939
0
  {
940
0
    return GetNextEditableHTMLNodeInternal(aPoint, false);
941
0
  }
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNode<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&)
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNode<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&)
942
  template<typename PT, typename CT>
943
  nsIContent* GetNextEditableHTMLNodeInBlock(
944
                const EditorDOMPointBase<PT, CT>& aPoint)
945
0
  {
946
0
    return GetNextEditableHTMLNodeInternal(aPoint, true);
947
0
  }
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNodeInBlock<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> >(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&)
Unexecuted instantiation: nsIContent* mozilla::HTMLEditor::GetNextEditableHTMLNodeInBlock<nsINode*, nsIContent*>(mozilla::EditorDOMPointBase<nsINode*, nsIContent*> const&)
948
949
  /**
950
   * GetNextEditableHTMLNodeInternal() methods are common implementation
951
   * of above methods.  Please don't use this method directly.
952
   */
953
  nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode,
954
                                              bool aNoBlockCrossing);
955
  template<typename PT, typename CT>
956
  nsIContent* GetNextEditableHTMLNodeInternal(
957
                const EditorDOMPointBase<PT, CT>& aPoint,
958
                bool aNoBlockCrossing);
959
960
  bool IsFirstEditableChild(nsINode* aNode);
961
  bool IsLastEditableChild(nsINode* aNode);
962
  nsIContent* GetFirstEditableChild(nsINode& aNode);
963
  nsIContent* GetLastEditableChild(nsINode& aNode);
964
965
  nsIContent* GetFirstEditableLeaf(nsINode& aNode);
966
  nsIContent* GetLastEditableLeaf(nsINode& aNode);
967
968
  nsresult GetInlinePropertyBase(nsAtom& aProperty,
969
                                 nsAtom* aAttribute,
970
                                 const nsAString* aValue,
971
                                 bool* aFirst,
972
                                 bool* aAny,
973
                                 bool* aAll,
974
                                 nsAString* outValue);
975
976
  nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
977
                      nsAtom* aProperty, nsAtom* aAttribute);
978
979
  nsresult SetPositionToAbsolute(Element& aElement);
980
  nsresult SetPositionToStatic(Element& aElement);
981
982
protected: // Called by helper classes.
983
  virtual void
984
  OnStartToHandleTopLevelEditSubAction(
985
    EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
986
  virtual void OnEndHandlingTopLevelEditSubAction() override;
987
988
protected: // Shouldn't be used by friend classes
989
  virtual ~HTMLEditor();
990
991
  virtual nsresult SelectAllInternal() override;
992
993
  /**
994
   * SelectContentInternal() sets Selection to aContentToSelect to
995
   * aContentToSelect + 1 in parent of aContentToSelect.
996
   *
997
   * @param aSelection          The Selection, callers have to guarantee the
998
   *                            lifetime.
999
   * @param aContentToSelect    The content which should be selected.
1000
   */
1001
  nsresult SelectContentInternal(Selection& aSelection,
1002
                                 nsIContent& aContentToSelect);
1003
1004
  /**
1005
   * CollapseSelectionAfter() collapses Selection after aElement.
1006
   * If aElement is an orphan node or not in editing host, returns error.
1007
   */
1008
  nsresult CollapseSelectionAfter(Selection& aSelection,
1009
                                  Element& aElement);
1010
1011
  /**
1012
   * GetElementOrParentByTagNameAtSelection() looks for an element node whose
1013
   * name matches aTagName from anchor node of Selection to <body> element.
1014
   *
1015
   * @param aSelection      The Selection for this editor.
1016
   * @param aTagName        The tag name which you want to look for.
1017
   *                        Must not be nsGkAtoms::_empty.
1018
   *                        If nsGkAtoms::list, the result may be <ul>, <ol> or
1019
   *                        <dl> element.
1020
   *                        If nsGkAtoms::td, the result may be <td> or <th>.
1021
   *                        If nsGkAtoms::href, the result may be <a> element
1022
   *                        which has "href" attribute with non-empty value.
1023
   *                        If nsGkAtoms::anchor, the result may be <a> which
1024
   *                        has "name" attribute with non-empty value.
1025
   * @return                If an element which matches aTagName, returns
1026
   *                        an Element.  Otherwise, nullptr.
1027
   */
1028
  Element*
1029
  GetElementOrParentByTagNameAtSelection(Selection& aSelection,
1030
                                         const nsAtom& aTagName) const;
1031
1032
  /**
1033
   * GetElementOrParentByTagNameInternal() looks for an element node whose
1034
   * name matches aTagName from aNode to <body> element.
1035
   *
1036
   * @param aTagName        The tag name which you want to look for.
1037
   *                        Must not be nsGkAtoms::_empty.
1038
   *                        If nsGkAtoms::list, the result may be <ul>, <ol> or
1039
   *                        <dl> element.
1040
   *                        If nsGkAtoms::td, the result may be <td> or <th>.
1041
   *                        If nsGkAtoms::href, the result may be <a> element
1042
   *                        which has "href" attribute with non-empty value.
1043
   *                        If nsGkAtoms::anchor, the result may be <a> which
1044
   *                        has "name" attribute with non-empty value.
1045
   * @param aNode           Start node to look for the element.
1046
   * @return                If an element which matches aTagName, returns
1047
   *                        an Element.  Otherwise, nullptr.
1048
   */
1049
  Element*
1050
  GetElementOrParentByTagNameInternal(const nsAtom& aTagName,
1051
                                      nsINode& aNode) const;
1052
1053
  /**
1054
   * GetSelectedElement() returns an element node which is in first range of
1055
   * aSelection.  The rule is a little bit complicated and the rules do not
1056
   * make sense except in a few cases.  If you want to use this newly,
1057
   * you should create new method instead.  This needs to be here for
1058
   * comm-central.
1059
   * The rules are:
1060
   *   1. If Selection selects an element node, i.e., both containers are
1061
   *      same node and start offset and end offset is start offset + 1.
1062
   *      (XXX However, if last child is selected, this path is not used.)
1063
   *   2. If the argument is "href", look for anchor elements whose href
1064
   *      attribute is not empty from container of anchor/focus of Selection
1065
   *      to <body> element.  Then, both result are same one, returns the node.
1066
   *      (i.e., this allows collapsed selection.)
1067
   *   3. If the Selection is collapsed, returns null.
1068
   *   4. Otherwise, listing up all nodes with content iterator (post-order).
1069
   *     4-1. When first element node does *not* match with the argument,
1070
   *          *returns* the element.
1071
   *     4-2. When first element node matches with the argument, returns
1072
   *          *next* element node.
1073
   *
1074
   * @param aSelection          The Selection.
1075
   * @param aTagName            The atom of tag name in lower case.
1076
   *                            If nullptr, look for any element node.
1077
   *                            If nsGkAtoms::href, look for an <a> element
1078
   *                            which has non-empty href attribute.
1079
   *                            If nsGkAtoms::anchor or atomized "namedanchor",
1080
   *                            look for an <a> element which has non-empty
1081
   *                            name attribute.
1082
   * @param aRv                 Returns error code.
1083
   * @return                    An element in first range of aSelection.
1084
   */
1085
  already_AddRefed<Element>
1086
  GetSelectedElement(Selection& aSelection,
1087
                     const nsAtom* aTagName,
1088
                     ErrorResult& aRv);
1089
1090
  /**
1091
   * GetFirstTableRowElement() returns the first <tr> element in the most
1092
   * nearest ancestor of aTableOrElementInTable or itself.
1093
   *
1094
   * @param aTableOrElementInTable      <table> element or another element.
1095
   *                                    If this is a <table> element, returns
1096
   *                                    first <tr> element in it.  Otherwise,
1097
   *                                    returns first <tr> element in nearest
1098
   *                                    ancestor <table> element.
1099
   * @param aRv                         Returns an error code.  When
1100
   *                                    aTableOrElementInTable is neither
1101
   *                                    <table> nor in a <table> element,
1102
   *                                    returns NS_ERROR_FAILURE.
1103
   *                                    However, if <table> does not have
1104
   *                                    <tr> element, returns NS_OK.
1105
   */
1106
  Element*
1107
  GetFirstTableRowElement(Element& aTableOrElementInTable,
1108
                          ErrorResult& aRv) const;
1109
1110
  /**
1111
   * GetNextTableRowElement() returns next <tr> element of aTableRowElement.
1112
   * This won't cross <table> element boundary but may cross table section
1113
   * elements like <tbody>.
1114
   *
1115
   * @param aTableRowElement    A <tr> element.
1116
   * @param aRv                 Returns error.  If given element is <tr> but
1117
   *                            there is no next <tr> element, this returns
1118
   *                            nullptr but does not return error.
1119
   */
1120
  Element*
1121
  GetNextTableRowElement(Element& aTableRowElement,
1122
                         ErrorResult& aRv) const;
1123
1124
  struct CellAndIndexes;
1125
1126
  /**
1127
   * CellIndexes store both row index and column index of a table cell.
1128
   */
1129
  struct MOZ_STACK_CLASS CellIndexes final
1130
  {
1131
    int32_t mRow;
1132
    int32_t mColumn;
1133
1134
    /**
1135
     * This constructor initializes mRowIndex and mColumnIndex with indexes of
1136
     * aCellElement.
1137
     *
1138
     * @param aCellElement      An <td> or <th> element.
1139
     * @param aRv               Returns error if layout information is not
1140
     *                          available or given element is not a table cell.
1141
     */
1142
    CellIndexes(Element& aCellElement, ErrorResult& aRv)
1143
      : mRow(-1)
1144
      , mColumn(-1)
1145
0
    {
1146
0
      MOZ_ASSERT(!aRv.Failed());
1147
0
      Update(aCellElement, aRv);
1148
0
    }
1149
1150
    /**
1151
     * Update mRowIndex and mColumnIndex with indexes of aCellElement.
1152
     *
1153
     * @param                   See above.
1154
     */
1155
    void Update(Element& aCellElement, ErrorResult& aRv);
1156
1157
    /**
1158
     * This constructor initializes mRowIndex and mColumnIndex with indexes of
1159
     * cell element which contains anchor of Selection.
1160
     *
1161
     * @param aHTMLEditor       The editor which creates the instance.
1162
     * @param aSelection        The Selection for the editor.
1163
     * @param aRv               Returns error if there is no cell element
1164
     *                          which contains anchor of Selection, or layout
1165
     *                          information is not available.
1166
     */
1167
    CellIndexes(HTMLEditor& aHTMLEditor, Selection& aSelection,
1168
                ErrorResult& aRv)
1169
      : mRow(-1)
1170
      , mColumn(-1)
1171
0
    {
1172
0
      Update(aHTMLEditor, aSelection, aRv);
1173
0
    }
1174
1175
    /**
1176
     * Update mRowIndex and mColumnIndex with indexes of cell element which
1177
     * contains anchor of Selection.
1178
     *
1179
     * @param                   See above.
1180
     */
1181
    void Update(HTMLEditor& aHTMLEditor, Selection& aSelection,
1182
                ErrorResult& aRv);
1183
1184
  private:
1185
    CellIndexes()
1186
      : mRow(-1)
1187
      , mColumn(-1)
1188
0
    {
1189
0
    }
1190
1191
    friend struct CellAndIndexes;
1192
  };
1193
1194
  struct MOZ_STACK_CLASS CellAndIndexes final
1195
  {
1196
    RefPtr<Element> mElement;
1197
    CellIndexes mIndexes;
1198
1199
    /**
1200
     * This constructor initializes the members with cell element which is
1201
     * selected by first range of the Selection.  Note that even if the
1202
     * first range is in the cell element, this does not treat it as the
1203
     * cell element is selected.
1204
     */
1205
    CellAndIndexes(HTMLEditor& aHTMLEditor, Selection& aSelection,
1206
                   ErrorResult& aRv)
1207
0
    {
1208
0
      Update(aHTMLEditor, aSelection, aRv);
1209
0
    }
1210
1211
    /**
1212
     * Update mElement and mIndexes with cell element which is selected by
1213
     * first range of the Selection.  Note that even if the first range is
1214
     * in the cell element, this does not treat it as the cell element is
1215
     * selected.
1216
     */
1217
    void Update(HTMLEditor& aHTMLEditor, Selection& aSelection,
1218
                ErrorResult& aRv);
1219
  };
1220
1221
  /**
1222
   * TableSize stores and computes number of rows and columns of a <table>
1223
   * element.
1224
   */
1225
  struct MOZ_STACK_CLASS TableSize final
1226
  {
1227
    int32_t mRowCount;
1228
    int32_t mColumnCount;
1229
1230
    /**
1231
     * @param aHTMLEditor               The editor which creates the instance.
1232
     * @param aTableOrElementInTable    If a <table> element, computes number
1233
     *                                  of rows and columns of it.
1234
     *                                  If another element in a <table> element,
1235
     *                                  computes number of rows and columns
1236
     *                                  of nearest ancestor <table> element.
1237
     *                                  Otherwise, i.e., non-<table> element
1238
     *                                  not in <table>, returns error.
1239
     * @param aRv                       Returns error if the element is not
1240
     *                                  in <table> or layout information is
1241
     *                                  not available.
1242
     */
1243
    TableSize(HTMLEditor& aHTMLEditor, Element& aTableOrElementInTable,
1244
              ErrorResult& aRv)
1245
      : mRowCount(-1)
1246
      , mColumnCount(-1)
1247
0
    {
1248
0
      MOZ_ASSERT(!aRv.Failed());
1249
0
      Update(aHTMLEditor, aTableOrElementInTable, aRv);
1250
0
    }
1251
1252
    /**
1253
     * Update mRowCount and mColumnCount for aTableOrElementInTable.
1254
     * See above for the detail.
1255
     */
1256
    void Update(HTMLEditor& aHTMLEditor, Element& aTableOrElementInTable,
1257
                ErrorResult& aRv);
1258
1259
    bool IsEmpty() const
1260
0
    {
1261
0
      return !mRowCount || !mColumnCount;
1262
0
    }
1263
  };
1264
1265
  /**
1266
   * GetTableCellElementAt() returns a <td> or <th> element of aTableElement
1267
   * if there is a cell at the indexes.
1268
   *
1269
   * @param aTableElement       Must be a <table> element.
1270
   * @param aCellIndexes        Indexes of cell which you want.
1271
   *                            If rowspan and/or colspan is specified 2 or
1272
   *                            larger, any indexes are allowed to retrieve
1273
   *                            the cell in the area.
1274
   * @return                    The cell element if there is in the <table>.
1275
   *                            Returns nullptr without error if the indexes
1276
   *                            are out of bounds.
1277
   */
1278
  Element* GetTableCellElementAt(Element& aTableElement,
1279
                                 const CellIndexes& aCellIndexes) const
1280
0
  {
1281
0
    return GetTableCellElementAt(aTableElement, aCellIndexes.mRow,
1282
0
                                 aCellIndexes.mColumn);
1283
0
  }
1284
  Element* GetTableCellElementAt(Element& aTableElement,
1285
                                 int32_t aRowIndex,
1286
                                 int32_t aColumnIndex) const;
1287
1288
  /**
1289
   * GetSelectedOrParentTableElement() returns <td>, <th>, <tr> or <table>
1290
   * element:
1291
   *   #1 if the first selection range selects a cell, returns it.
1292
   *   #2 if the first selection range does not select a cell and
1293
   *      the selection anchor refers a <table>, returns it.
1294
   *   #3 if the first selection range does not select a cell and
1295
   *      the selection anchor refers a <tr>, returns it.
1296
   *   #4 if the first selection range does not select a cell and
1297
   *      the selection anchor refers a <td>, returns it.
1298
   *   #5 otherwise, nearest ancestor <td> or <th> element of the
1299
   *      selection anchor if there is.
1300
   * In #1 and #4, *aIsCellSelected will be set to true (i.e,, when
1301
   * a selection range selects a cell element).
1302
   */
1303
  already_AddRefed<Element>
1304
  GetSelectedOrParentTableElement(Selection& aSelection,
1305
                                  ErrorResult& aRv,
1306
                                  bool* aIsCellSelected = nullptr) const;
1307
1308
  /**
1309
   * PasteInternal() pasts text with replacing selected content.
1310
   * This tries to dispatch ePaste event first.  If its defaultPrevent() is
1311
   * called, this does nothing but returns NS_OK.
1312
   *
1313
   * @param aClipboardType  nsIClipboard::kGlobalClipboard or
1314
   *                        nsIClipboard::kSelectionClipboard.
1315
   */
1316
  nsresult PasteInternal(int32_t aClipboardType);
1317
1318
  /**
1319
   * InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
1320
   * into the document, at aPointToInsert.  Checks with strict dtd to see if
1321
   * containment is allowed.  If not allowed, will attempt to find a parent
1322
   * in the parent hierarchy of aPointToInsert.GetContainer() that will accept
1323
   * aNode as a child.  If such a parent is found, will split the document
1324
   * tree from aPointToInsert up to parent, and then insert aNode.
1325
   * aPointToInsert is then adjusted to point to the actual location that
1326
   * aNode was inserted at.  aSplitAtEdges specifies if the splitting process
1327
   * is allowed to result in empty nodes.
1328
   *
1329
   * @param aNode             Node to insert.
1330
   * @param aPointToInsert    Insertion point.
1331
   * @param aSplitAtEdges     Splitting can result in empty nodes?
1332
   * @return                  Returns inserted point if succeeded.
1333
   *                          Otherwise, the result is not set.
1334
   */
1335
  template<typename PT, typename CT>
1336
  EditorDOMPoint
1337
  InsertNodeIntoProperAncestorWithTransaction(
1338
    nsIContent& aNode,
1339
    const EditorDOMPointBase<PT, CT>& aPointToInsert,
1340
    SplitAtEdges aSplitAtEdges);
1341
1342
  /**
1343
   * InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at
1344
   * selection.  If there is non-collapsed selection ranges, the selected
1345
   * ranges is deleted first.
1346
   */
1347
  nsresult InsertBrElementAtSelectionWithTransaction();
1348
1349
  /**
1350
   * InsertTextWithQuotationsInternal() replaces selection with new content.
1351
   * First, this method splits aStringToInsert to multiple chunks which start
1352
   * with non-linebreaker except first chunk and end with a linebreaker except
1353
   * last chunk.  Then, each chunk starting with ">" is inserted after wrapping
1354
   * with <span _moz_quote="true">, and each chunk not starting with ">" is
1355
   * inserted as normal text.
1356
   */
1357
  nsresult InsertTextWithQuotationsInternal(const nsAString& aStringToInsert);
1358
1359
  /**
1360
   * IndentOrOutdentAsSubAction() indents or outdents the content around
1361
   * Selection.  Callers have to guarantee that there is a placeholder
1362
   * transaction.
1363
   *
1364
   * @param aEditSubAction      Must be EditSubAction::eIndent or
1365
   *                            EditSubAction::eOutdent.
1366
   */
1367
  nsresult IndentOrOutdentAsSubAction(EditSubAction aEditSubAction);
1368
1369
  nsresult LoadHTML(const nsAString& aInputString);
1370
1371
  nsresult SetInlinePropertyInternal(nsAtom& aProperty,
1372
                                     nsAtom* aAttribute,
1373
                                     const nsAString& aValue);
1374
  nsresult RemoveInlinePropertyInternal(nsAtom* aProperty,
1375
                                        nsAtom* aAttribute);
1376
1377
  /**
1378
   * ReplaceHeadContentsWithSourceWithTransaction() replaces all children of
1379
   * <head> element with given source code.  This is undoable.
1380
   *
1381
   * @param aSourceToInsert     HTML source fragment to replace the children
1382
   *                            of <head> element.
1383
   */
1384
  nsresult
1385
  ReplaceHeadContentsWithSourceWithTransaction(
1386
    const nsAString& aSourceToInsert);
1387
1388
  nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
1389
                                      bool aBlockLevel);
1390
  nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
1391
1392
  nsresult GetLastCellInRow(nsINode* aRowNode,
1393
                            nsINode** aCellNode);
1394
1395
  static nsresult GetCellFromRange(nsRange* aRange, Element** aCell);
1396
1397
  /**
1398
   * This sets background on the appropriate container element (table, cell,)
1399
   * or calls into nsTextEditor to set the page background.
1400
   */
1401
  nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
1402
  nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
1403
1404
  virtual void
1405
  InitializeSelectionAncestorLimit(Selection& aSelection,
1406
                                   nsIContent& aAncestorLimit) override;
1407
1408
  /**
1409
   * Make the given selection span the entire document.
1410
   */
1411
  virtual nsresult SelectEntireDocument(Selection* aSelection) override;
1412
1413
  /**
1414
   * Use this to assure that selection is set after attribute nodes when
1415
   * trying to collapse selection at begining of a block node
1416
   * e.g., when setting at beginning of a table cell
1417
   * This will stop at a table, however, since we don't want to
1418
   * "drill down" into nested tables.
1419
   * @param aSelection      Optional. If null, we get current selection.
1420
   */
1421
  void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
1422
                                                    nsINode* aNode);
1423
1424
  /**
1425
   * Returns TRUE if sheet was loaded, false if it wasn't.
1426
   */
1427
  bool EnableExistingStyleSheet(const nsAString& aURL);
1428
1429
  /**
1430
   * GetStyleSheetForURL() returns a pointer to StyleSheet which was added
1431
   * with AddOverrideStyleSheetInternal().  If it's not found, returns nullptr.
1432
   *
1433
   * @param aURL        URL to the style sheet.
1434
   */
1435
  StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
1436
1437
  /**
1438
   * Add a url + known style sheet to the internal lists.
1439
   */
1440
  nsresult AddNewStyleSheetToList(const nsAString &aURL,
1441
                                  StyleSheet* aStyleSheet);
1442
1443
  /**
1444
   * Removes style sheet from the internal lists.
1445
   *
1446
   * @param aURL        URL to the style sheet.
1447
   * @return            If the URL is in the internal list, returns the
1448
   *                    removed style sheet.  Otherwise, i.e., not found,
1449
   *                    nullptr.
1450
   */
1451
  already_AddRefed<StyleSheet> RemoveStyleSheetFromList(const nsAString& aURL);
1452
1453
  /**
1454
   * Add and apply the style sheet synchronously.
1455
   *
1456
   * @param aURL        URL to the style sheet.
1457
   */
1458
  nsresult AddOverrideStyleSheetInternal(const nsAString& aURL);
1459
1460
  /**
1461
   * Remove the style sheet from this editor synchronously.
1462
   *
1463
   * @param aURL        URL to the style sheet.
1464
   * @return            Even if there is no specified style sheet in the
1465
   *                    internal lists, this returns NS_OK.
1466
   */
1467
  nsresult RemoveOverrideStyleSheetInternal(const nsAString& aURL);
1468
1469
  /**
1470
   * Enable or disable the style sheet synchronously.
1471
   * aURL is just a key to specify a style sheet in the internal array.
1472
   * I.e., the style sheet has already been registered with
1473
   * AddOverrideStyleSheetInternal().
1474
   *
1475
   * @param aURL        URL to the style sheet.
1476
   * @param aEnable     true if enable the style sheet.  false if disable it.
1477
   */
1478
  void EnableStyleSheetInternal(const nsAString& aURL, bool aEnable);
1479
1480
  /**
1481
   * MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at
1482
   * proper position to staring to edit.  If there is a non-editable node
1483
   * before any editable text nodes or inline elements which can have text
1484
   * nodes as their children, collapse selection at start of the editing
1485
   * host.  If there is an editable text node which is not collapsed, collapses
1486
   * selection at the start of the text node.  If there is an editable inline
1487
   * element which cannot have text nodes as its child, collapses selection at
1488
   * before the element node.  Otherwise, collapses selection at start of the
1489
   * editing host.
1490
   *
1491
   * @param aIgnoreIfSelectionInEditingHost
1492
   *                        This method does nothing if selection is in the
1493
   *                        editing host except if it's collapsed at start of
1494
   *                        the editing host.
1495
   *                        Note that if selection ranges were outside of
1496
   *                        current selection limiter, selection was collapsed
1497
   *                        at the start of the editing host therefore, if
1498
   *                        you call this with setting this to true, you can
1499
   *                        keep selection ranges if user has already been
1500
   *                        changed.
1501
   */
1502
  nsresult
1503
  MaybeCollapseSelectionAtFirstEditableNode(
1504
    bool aIgnoreIfSelectionInEditingHost);
1505
1506
  class BlobReader final
1507
  {
1508
  public:
1509
    BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
1510
               bool aIsSafe, nsIDocument* aSourceDoc,
1511
               nsINode* aDestinationNode, int32_t aDestOffset,
1512
               bool aDoDeleteSelection);
1513
1514
    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BlobReader)
1515
    NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(BlobReader)
1516
1517
    nsresult OnResult(const nsACString& aResult);
1518
    nsresult OnError(const nsAString& aErrorName);
1519
1520
  private:
1521
    ~BlobReader()
1522
0
    {
1523
0
    }
1524
1525
    RefPtr<dom::BlobImpl> mBlob;
1526
    RefPtr<HTMLEditor> mHTMLEditor;
1527
    bool mIsSafe;
1528
    nsCOMPtr<nsIDocument> mSourceDoc;
1529
    nsCOMPtr<nsINode> mDestinationNode;
1530
    int32_t mDestOffset;
1531
    bool mDoDeleteSelection;
1532
  };
1533
1534
  virtual nsresult InitRules() override;
1535
1536
  virtual void CreateEventListeners() override;
1537
  virtual nsresult InstallEventListeners() override;
1538
  virtual void RemoveEventListeners() override;
1539
1540
  bool ShouldReplaceRootElement();
1541
  void NotifyRootChanged();
1542
  Element* GetBodyElement();
1543
1544
  /**
1545
   * Get the focused node of this editor.
1546
   * @return    If the editor has focus, this returns the focused node.
1547
   *            Otherwise, returns null.
1548
   */
1549
  already_AddRefed<nsINode> GetFocusedNode();
1550
1551
  virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
1552
1553
  /**
1554
   * Return TRUE if aElement is a table-related elemet and caret was set.
1555
   */
1556
  bool SetCaretInTableCell(dom::Element* aElement);
1557
1558
  nsresult TabInTable(bool inIsShift, bool* outHandled);
1559
1560
  /**
1561
   * InsertPosition is an enum to indicate where the method should insert to.
1562
   */
1563
  enum class InsertPosition
1564
  {
1565
    // Before selected cell or a cell containing first selection range.
1566
    eBeforeSelectedCell,
1567
    // After selected cell or a cell containing first selection range.
1568
    eAfterSelectedCell,
1569
  };
1570
1571
  /**
1572
   * InsertTableCellsWithTransaction() inserts <td> elements before or after
1573
   * a cell element containing first selection range.  I.e., if the cell
1574
   * spans columns and aInsertPosition is eAfterSelectedCell, new columns
1575
   * will be inserted after the right-most column which contains the cell.
1576
   * Note that this simply inserts <td> elements, i.e., colspan and rowspan
1577
   * around the cell containing selection are not modified.  So, for example,
1578
   * adding a cell to rectangular table changes non-rectangular table.
1579
   * And if the cell containing selection is at left of row-spanning cell,
1580
   * it may be moved to right side of the row-spanning cell after inserting
1581
   * some cell elements before it.  Similarly, colspan won't be adjusted
1582
   * for keeping table rectangle.
1583
   * If first selection range is not in table cell element, this does nothing
1584
   * but does not return error.
1585
   *
1586
   * @param aNumberOfCellssToInsert     Number of cells to insert.
1587
   * @param aInsertPosition             Before or after the target cell which
1588
   *                                    contains first selection range.
1589
   */
1590
  nsresult InsertTableCellsWithTransaction(int32_t aNumberOfCellsToInsert,
1591
                                           InsertPosition aInsertPosition);
1592
1593
  /**
1594
   * InsertTableColumnsWithTransaction() inserts columns before or after
1595
   * a cell element containing first selection range.  I.e., if the cell
1596
   * spans columns and aInsertPosition is eAfterSelectedCell, new columns
1597
   * will be inserted after the right-most row which contains the cell.
1598
   * If first selection range is not in table cell element, this does nothing
1599
   * but does not return error.
1600
   *
1601
   * @param aNumberOfColumnsToInsert    Number of columns to insert.
1602
   * @param aInsertPosition             Before or after the target cell which
1603
   *                                    contains first selection range.
1604
   */
1605
  nsresult InsertTableColumnsWithTransaction(int32_t aNumberOfColumnsToInsert,
1606
                                             InsertPosition aInsertPosition);
1607
1608
  /**
1609
   * InsertTableRowsWithTransaction() inserts <tr> elements before or after
1610
   * a cell element containing first selection range.  I.e., if the cell
1611
   * spans rows and aInsertPosition is eAfterSelectedCell, new rows will be
1612
   * inserted after the most-bottom row which contains the cell.  If first
1613
   * selection range is not in table cell element, this does nothing but
1614
   * does not return error.
1615
   *
1616
   * @param aNumberOfRowsToInsert       Number of rows to insert.
1617
   * @param aInsertPosition             Before or after the target cell which
1618
   *                                    contains first selection range.
1619
   */
1620
  nsresult InsertTableRowsWithTransaction(int32_t aNumberOfRowsToInsert,
1621
                                          InsertPosition aInsertPosition);
1622
1623
  /**
1624
   * Insert a new cell after or before supplied aCell.
1625
   * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
1626
   * of course)
1627
   * This doesn't change or use the current selection.
1628
   */
1629
  nsresult InsertCell(Element* aCell, int32_t aRowSpan,
1630
                      int32_t aColSpan, bool aAfter, bool aIsHeader,
1631
                      Element** aNewCell);
1632
1633
  /**
1634
   * DeleteSelectedTableColumnsWithTransaction() removes cell elements which
1635
   * belong to same columns of selected cell elements.
1636
   * If only one cell element is selected or first selection range is
1637
   * in a cell, removes cell elements which belong to same column.
1638
   * If 2 or more cell elements are selected, removes cell elements which
1639
   * belong to any of all selected columns.  In this case,
1640
   * aNumberOfColumnsToDelete is ignored.
1641
   * If there is no selection ranges, returns error.
1642
   * If selection is not in a cell element, this does not return error,
1643
   * just does nothing.
1644
   * WARNING: This does not remove <col> nor <colgroup> elements.
1645
   *
1646
   * @param aNumberOfColumnsToDelete    Number of columns to remove.  This is
1647
   *                                    ignored if 2 ore more cells are
1648
   *                                    selected.
1649
   */
1650
  nsresult
1651
  DeleteSelectedTableColumnsWithTransaction(int32_t aNumberOfColumnsToDelete);
1652
1653
  /**
1654
   * DeleteTableColumnWithTransaction() removes cell elements which belong
1655
   * to the specified column.
1656
   * This method adjusts colspan attribute value if cells spanning the
1657
   * column to delete.
1658
   * WARNING: This does not remove <col> nor <colgroup> elements.
1659
   *
1660
   * @param aTableElement       The <table> element which contains the
1661
   *                            column which you want to remove.
1662
   * @param aRowIndex           Index of the column which you want to remove.
1663
   *                            0 is the first column.
1664
   */
1665
  nsresult
1666
  DeleteTableColumnWithTransaction(Element& aTableElement,
1667
                                   int32_t aColumnIndex);
1668
1669
  /**
1670
   * DeleteSelectedTableRowsWithTransaction() removes <tr> elements.
1671
   * If only one cell element is selected or first selection range is
1672
   * in a cell, removes <tr> elements starting from a <tr> element
1673
   * containing the selected cell or first selection range.
1674
   * If 2 or more cell elements are selected, all <tr> elements
1675
   * which contains selected cell(s).  In this case, aNumberOfRowsToDelete
1676
   * is ignored.
1677
   * If there is no selection ranges, returns error.
1678
   * If selection is not in a cell element, this does not return error,
1679
   * just does nothing.
1680
   *
1681
   * @param aNumberOfRowsToDelete   Number of rows to remove.  This is ignored
1682
   *                                if 2 or more cells are selected.
1683
   */
1684
  nsresult
1685
  DeleteSelectedTableRowsWithTransaction(int32_t aNumberOfRowsToDelete);
1686
1687
  /**
1688
   * DeleteTableRowWithTransaction() removes a <tr> element whose index in
1689
   * the <table> is aRowIndex.
1690
   * This method adjusts rowspan attribute value if the <tr> element contains
1691
   * cells which spans rows.
1692
   *
1693
   * @param aTableElement       The <table> element which contains the
1694
   *                            <tr> element which you want to remove.
1695
   * @param aRowIndex           Index of the <tr> element which you want to
1696
   *                            remove.  0 is the first row.
1697
   */
1698
  nsresult
1699
  DeleteTableRowWithTransaction(Element& aTableElement, int32_t aRowIndex);
1700
1701
  /**
1702
   * DeleteTableCellWithTransaction() removes table cell elements.  If two or
1703
   * more cell elements are selected, this removes all selected cell elements.
1704
   * Otherwise, this removes some cell elements starting from selected cell
1705
   * element or a cell containing first selection range.  When this removes
1706
   * last cell element in <tr> or <table>, this removes the <tr> or the
1707
   * <table> too.  Note that when removing a cell causes number of its row
1708
   * becomes less than the others, this method does NOT fill the place with
1709
   * rowspan nor colspan.  This does not return error even if selection is not
1710
   * in cell element, just does nothing.
1711
   *
1712
   * @param aNumberOfCellsToDelete  Number of cells to remove.  This is ignored
1713
   *                                if 2 or more cells are selected.
1714
   */
1715
  nsresult DeleteTableCellWithTransaction(int32_t aNumberOfCellsToDelete);
1716
1717
  /**
1718
   * DeleteAllChildrenWithTransaction() removes all children of aElement from
1719
   * the tree.
1720
   *
1721
   * @param aElement        The element whose children you want to remove.
1722
   */
1723
  nsresult DeleteAllChildrenWithTransaction(Element& aElement);
1724
1725
  /**
1726
   * Move all contents from aCellToMerge into aTargetCell (append at end).
1727
   */
1728
  nsresult MergeCells(RefPtr<Element> aTargetCell,
1729
                      RefPtr<Element> aCellToMerge,
1730
                      bool aDeleteCellToMerge);
1731
1732
  /**
1733
   * DeleteTableElementAndChildren() removes aTableElement (and its children)
1734
   * from the DOM tree with transaction.
1735
   *
1736
   * @param aSelection      The normal Selection for the editor.
1737
   * @param aTableElement   The <table> element which you want to remove.
1738
   */
1739
  nsresult
1740
  DeleteTableElementAndChildrenWithTransaction(Selection& aSelection,
1741
                                               Element& aTableElement);
1742
1743
  nsresult SetColSpan(Element* aCell, int32_t aColSpan);
1744
  nsresult SetRowSpan(Element* aCell, int32_t aRowSpan);
1745
1746
  /**
1747
   * Helper used to get nsTableWrapperFrame for a table.
1748
   */
1749
  static nsTableWrapperFrame* GetTableFrame(Element* aTable);
1750
1751
  /**
1752
   * GetNumberOfCellsInRow() returns number of actual cell elements in the row.
1753
   * If some cells appear by "rowspan" in other rows, they are ignored.
1754
   *
1755
   * @param aTableElement   The <table> element.
1756
   * @param aRowIndex       Valid row index in aTableElement.  This method
1757
   *                        counts cell elements in the row.
1758
   * @return                -1 if this meets unexpected error.
1759
   *                        Otherwise, number of cells which this method found.
1760
   */
1761
  int32_t GetNumberOfCellsInRow(Element& aTableElement, int32_t aRowIndex);
1762
1763
  /**
1764
   * Test if all cells in row or column at given index are selected.
1765
   */
1766
  bool AllCellsInRowSelected(Element* aTable, int32_t aRowIndex,
1767
                             int32_t aNumberOfColumns);
1768
  bool AllCellsInColumnSelected(Element* aTable, int32_t aColIndex,
1769
                                int32_t aNumberOfRows);
1770
1771
  bool IsEmptyCell(Element* aCell);
1772
1773
  /**
1774
   * Most insert methods need to get the same basic context data.
1775
   * Any of the pointers may be null if you don't need that datum (for more
1776
   * efficiency).
1777
   * Input: *aCell is a known cell,
1778
   *        if null, cell is obtained from the anchor node of the selection.
1779
   * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
1780
   * null.
1781
   */
1782
  nsresult GetCellContext(Selection** aSelection, Element** aTable,
1783
                          Element** aCell, nsINode** aCellParent,
1784
                          int32_t* aCellOffset, int32_t* aRowIndex,
1785
                          int32_t* aColIndex);
1786
1787
  nsresult GetCellSpansAt(Element* aTable, int32_t aRowIndex,
1788
                          int32_t aColIndex, int32_t& aActualRowSpan,
1789
                          int32_t& aActualColSpan);
1790
1791
  nsresult SplitCellIntoColumns(Element* aTable, int32_t aRowIndex,
1792
                                int32_t aColIndex, int32_t aColSpanLeft,
1793
                                int32_t aColSpanRight,
1794
                                Element** aNewCell);
1795
1796
  nsresult SplitCellIntoRows(Element* aTable, int32_t aRowIndex,
1797
                             int32_t aColIndex, int32_t aRowSpanAbove,
1798
                             int32_t aRowSpanBelow, Element** aNewCell);
1799
1800
  nsresult CopyCellBackgroundColor(Element* aDestCell,
1801
                                   Element* aSourceCell);
1802
1803
  /**
1804
   * Reduce rowspan/colspan when cells span into nonexistent rows/columns.
1805
   */
1806
  nsresult FixBadRowSpan(Element* aTable, int32_t aRowIndex,
1807
                         int32_t& aNewRowCount);
1808
  nsresult FixBadColSpan(Element* aTable, int32_t aColIndex,
1809
                         int32_t& aNewColCount);
1810
1811
  /**
1812
   * XXX NormalizeTable() is broken.  If it meets a cell which has bigger or
1813
   *     smaller rowspan or colspan than actual number of cells, this always
1814
   *     failed to scan the table.  Therefore, this does nothing when the
1815
   *     table should be normalized.
1816
   *
1817
   * @param aSelection              The Selection for the editor.
1818
   * @param aTableOrElementInTable  An element which is in a <table> element
1819
   *                                or <table> element itself.  Otherwise,
1820
   *                                this returns NS_OK but does nothing.
1821
   */
1822
  nsresult NormalizeTable(Selection& aSelection,
1823
                          Element& aTableOrElementInTable);
1824
1825
  /**
1826
   * Fallback method: Call this after using ClearSelection() and you
1827
   * failed to set selection to some other content in the document.
1828
   */
1829
  nsresult SetSelectionAtDocumentStart(Selection* aSelection);
1830
1831
  static Element* GetEnclosingTable(nsINode* aNode);
1832
1833
  // Methods for handling plaintext quotations
1834
  nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
1835
1836
  /**
1837
   * Insert a string as quoted text, replacing the selected text (if any).
1838
   * @param aQuotedText     The string to insert.
1839
   * @param aAddCites       Whether to prepend extra ">" to each line
1840
   *                        (usually true, unless those characters
1841
   *                        have already been added.)
1842
   * @return aNodeInserted  The node spanning the insertion, if applicable.
1843
   *                        If aAddCites is false, this will be null.
1844
   */
1845
  nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
1846
                                      bool aAddCites,
1847
                                      nsINode** aNodeInserted);
1848
1849
  nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
1850
                        bool aIsSafe,
1851
                        nsIDocument* aSourceDoc,
1852
                        nsINode* aDestinationNode,
1853
                        int32_t aDestOffset,
1854
                        bool aDoDeleteSelection);
1855
1856
  // factored methods for handling insertion of data from transferables
1857
  // (drag&drop or clipboard)
1858
  virtual nsresult PrepareTransferable(nsITransferable** transferable) override;
1859
  nsresult PrepareHTMLTransferable(nsITransferable** transferable);
1860
  nsresult InsertFromTransferable(nsITransferable* transferable,
1861
                                    nsIDocument* aSourceDoc,
1862
                                    const nsAString& aContextStr,
1863
                                    const nsAString& aInfoStr,
1864
                                    bool havePrivateHTMLFlavor,
1865
                                    bool aDoDeleteSelection);
1866
  virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
1867
                                          int32_t aIndex,
1868
                                          nsIDocument* aSourceDoc,
1869
                                          nsINode* aDestinationNode,
1870
                                          int32_t aDestOffset,
1871
                                          bool aDoDeleteSelection) override;
1872
  bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
1873
  nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
1874
                       char16_t** aCfcontext);
1875
1876
  nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
1877
  nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
1878
                                      const nsAString& aContextStr,
1879
                                      const nsAString& aInfoStr,
1880
                                      nsCOMPtr<nsINode>* outFragNode,
1881
                                      nsCOMPtr<nsINode>* outStartNode,
1882
                                      nsCOMPtr<nsINode>* outEndNode,
1883
                                      int32_t* outStartOffset,
1884
                                      int32_t* outEndOffset,
1885
                                      bool aTrustedInput);
1886
  nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
1887
                         nsIDocument* aTargetDoc,
1888
                         dom::DocumentFragment** aFragment, bool aTrustedInput);
1889
  void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
1890
                                nsTArray<OwningNonNull<nsINode>>& outNodeList,
1891
                                nsINode* aStartContainer,
1892
                                int32_t aStartOffset,
1893
                                nsINode* aEndContainer,
1894
                                int32_t aEndOffset);
1895
  enum class StartOrEnd { start, end };
1896
  void GetListAndTableParents(StartOrEnd aStartOrEnd,
1897
                              nsTArray<OwningNonNull<nsINode>>& aNodeList,
1898
                              nsTArray<OwningNonNull<Element>>& outArray);
1899
  int32_t DiscoverPartialListsAndTables(
1900
            nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
1901
            nsTArray<OwningNonNull<Element>>& aListsAndTables);
1902
  nsINode* ScanForListAndTableStructure(
1903
             StartOrEnd aStartOrEnd,
1904
             nsTArray<OwningNonNull<nsINode>>& aNodes,
1905
             Element& aListOrTable);
1906
  void ReplaceOrphanedStructure(
1907
         StartOrEnd aStartOrEnd,
1908
         nsTArray<OwningNonNull<nsINode>>& aNodeArray,
1909
         nsTArray<OwningNonNull<Element>>& aListAndTableArray,
1910
         int32_t aHighWaterMark);
1911
1912
  /**
1913
   * GetBetterInsertionPointFor() returns better insertion point to insert
1914
   * aNodeToInsert.
1915
   *
1916
   * @param aNodeToInsert       The node to insert.
1917
   * @param aPointToInsert      A candidate point to insert the node.
1918
   * @return                    Better insertion point if next visible node
1919
   *                            is a <br> element and previous visible node
1920
   *                            is neither none, another <br> element nor
1921
   *                            different block level element.
1922
   */
1923
  EditorRawDOMPoint
1924
  GetBetterInsertionPointFor(nsINode& aNodeToInsert,
1925
                             const EditorRawDOMPoint& aPointToInsert);
1926
1927
  /**
1928
   * MakeDefinitionListItemWithTransaction() replaces parent list of current
1929
   * selection with <dl> or create new <dl> element and creates a definition
1930
   * list item whose name is aTagName.
1931
   *
1932
   * @param aTagName            Must be nsGkAtoms::dt or nsGkAtoms::dd.
1933
   */
1934
  nsresult MakeDefinitionListItemWithTransaction(nsAtom& aTagName);
1935
1936
  /**
1937
   * InsertBasicBlockWithTransaction() inserts a block element whose name
1938
   * is aTagName at selection.
1939
   *
1940
   * @param aTagName            A block level element name.  Must NOT be
1941
   *                            nsGkAtoms::dt nor nsGkAtoms::dd.
1942
   */
1943
  nsresult InsertBasicBlockWithTransaction(nsAtom& aTagName);
1944
1945
  /**
1946
   * Increase/decrease the font size of selection.
1947
   */
1948
  nsresult RelativeFontChange(FontSize aDir);
1949
1950
  nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
1951
  nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
1952
1953
  /**
1954
   * Helper routines for inline style.
1955
   */
1956
  nsresult SetInlinePropertyOnTextNode(Text& aData,
1957
                                       int32_t aStartOffset,
1958
                                       int32_t aEndOffset,
1959
                                       nsAtom& aProperty,
1960
                                       nsAtom* aAttribute,
1961
                                       const nsAString& aValue);
1962
1963
  nsresult PromoteInlineRange(nsRange& aRange);
1964
  nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
1965
  nsresult SplitStyleAboveRange(nsRange* aRange,
1966
                                nsAtom* aProperty,
1967
                                nsAtom* aAttribute);
1968
  nsresult RemoveStyleInside(nsIContent& aNode,
1969
                             nsAtom* aProperty,
1970
                             nsAtom* aAttribute,
1971
                             const bool aChildrenOnly = false);
1972
1973
  bool NodeIsProperty(nsINode& aNode);
1974
  bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
1975
  bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
1976
  bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute);
1977
1978
  bool HasStyleOrIdOrClass(Element* aElement);
1979
  nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
1980
1981
  /**
1982
   * Whether the outer window of the DOM event target has focus or not.
1983
   */
1984
  bool OurWindowHasFocus();
1985
1986
  /**
1987
   * This function is used to insert a string of HTML input optionally with some
1988
   * context information into the editable field.  The HTML input either comes
1989
   * from a transferable object created as part of a drop/paste operation, or
1990
   * from the InsertHTML method.  We may want the HTML input to be sanitized
1991
   * (for example, if it's coming from a transferable object), in which case
1992
   * aTrustedInput should be set to false, otherwise, the caller should set it
1993
   * to true, which means that the HTML will be inserted in the DOM verbatim.
1994
   *
1995
   * aClearStyle should be set to false if you want the paste to be affected by
1996
   * local style (e.g., for the insertHTML command).
1997
   */
1998
  nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
1999
                                   const nsAString& aContextStr,
2000
                                   const nsAString& aInfoStr,
2001
                                   const nsAString& aFlavor,
2002
                                   nsIDocument* aSourceDoc,
2003
                                   nsINode* aDestNode,
2004
                                   int32_t aDestOffset,
2005
                                   bool aDeleteSelection,
2006
                                   bool aTrustedInput,
2007
                                   bool aClearStyle = true);
2008
2009
  /**
2010
   * sets the position of an element; warning it does NOT check if the
2011
   * element is already positioned or not and that's on purpose.
2012
   * @param aElement [IN] the element
2013
   * @param aX       [IN] the x position in pixels.
2014
   * @param aY       [IN] the y position in pixels.
2015
   */
2016
  void SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY);
2017
2018
  /**
2019
   * Reset a selected cell or collapsed selection (the caret) after table
2020
   * editing.
2021
   *
2022
   * @param aTable      A table in the document.
2023
   * @param aRow        The row ...
2024
   * @param aCol        ... and column defining the cell where we will try to
2025
   *                    place the caret.
2026
   * @param aSelected   If true, we select the whole cell instead of setting
2027
   *                    caret.
2028
   * @param aDirection  If cell at (aCol, aRow) is not found, search for
2029
   *                    previous cell in the same column (aPreviousColumn) or
2030
   *                    row (ePreviousRow) or don't search for another cell
2031
   *                    (aNoSearch).  If no cell is found, caret is place just
2032
   *                    before table; and if that fails, at beginning of
2033
   *                    document.  Thus we generally don't worry about the
2034
   *                    return value and can use the
2035
   *                    AutoSelectionSetterAfterTableEdit stack-based object to
2036
   *                    insure we reset the caret in a table-editing method.
2037
   */
2038
  void SetSelectionAfterTableEdit(Element* aTable,
2039
                                  int32_t aRow, int32_t aCol,
2040
                                  int32_t aDirection, bool aSelected);
2041
2042
  void RemoveListenerAndDeleteRef(const nsAString& aEvent,
2043
                                  nsIDOMEventListener* aListener,
2044
                                  bool aUseCapture,
2045
                                  ManualNACPtr aElement,
2046
                                  nsIPresShell* aShell);
2047
  void DeleteRefToAnonymousNode(ManualNACPtr aContent,
2048
                                nsIPresShell* aShell);
2049
2050
  /**
2051
   * RefereshEditingUI() may refresh editing UIs for current Selection, focus,
2052
   * etc.  If this shows or hides some UIs, it causes reflow.  So, this is
2053
   * not safe method.
2054
   */
2055
  nsresult RefereshEditingUI(Selection& aSelection);
2056
2057
  /**
2058
   * Returns the offset of an element's frame to its absolute containing block.
2059
   */
2060
  nsresult GetElementOrigin(Element& aElement,
2061
                            int32_t& aX, int32_t& aY);
2062
  nsresult GetPositionAndDimensions(Element& aElement,
2063
                                    int32_t& aX, int32_t& aY,
2064
                                    int32_t& aW, int32_t& aH,
2065
                                    int32_t& aBorderLeft,
2066
                                    int32_t& aBorderTop,
2067
                                    int32_t& aMarginLeft,
2068
                                    int32_t& aMarginTop);
2069
2070
  bool IsInObservedSubtree(nsIContent* aChild);
2071
2072
  void UpdateRootElement();
2073
2074
  /**
2075
   * SetAllResizersPosition() moves all resizers to proper position.
2076
   * If the resizers are hidden or replaced with another set of resizers
2077
   * while this is running, this returns error.  So, callers shouldn't
2078
   * keep handling the resizers if this returns error.
2079
   */
2080
  nsresult SetAllResizersPosition();
2081
2082
  /**
2083
   * Shows active resizers around an element's frame
2084
   * @param aResizedElement [IN] a DOM Element
2085
   */
2086
  nsresult ShowResizersInternal(Element& aResizedElement);
2087
2088
  /**
2089
   * Hide resizers if they are visible.  If this is called while there is no
2090
   * visible resizers, this does not return error, but does nothing.
2091
   */
2092
  nsresult HideResizersInternal();
2093
2094
  /**
2095
   * RefreshResizersInternal() moves resizers to proper position.  This does
2096
   * nothing if there is no resizing target.
2097
   */
2098
  nsresult RefreshResizersInternal();
2099
2100
  ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent);
2101
  void SetAnonymousElementPosition(int32_t aX, int32_t aY,
2102
                                   Element* aResizer);
2103
2104
  ManualNACPtr CreateShadow(nsIContent& aParentContent,
2105
                            Element& aOriginalObject);
2106
2107
  /**
2108
   * SetShadowPosition() moves the shadow element to proper position.
2109
   *
2110
   * @param aShadowElement      Must be mResizingShadow or mPositioningShadow.
2111
   * @param aElement            The element which has the shadow.
2112
   * @param aElementX           Left of aElement.
2113
   * @param aElementY           Top of aElement.
2114
   */
2115
  nsresult SetShadowPosition(Element& aShadowElement,
2116
                             Element& aElement,
2117
                             int32_t aElementLeft,
2118
                             int32_t aElementTop);
2119
2120
  ManualNACPtr CreateResizingInfo(nsIContent& aParentContent);
2121
  nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
2122
                                   int32_t aW, int32_t aH);
2123
2124
  enum class ResizeAt
2125
  {
2126
    eX,
2127
    eY,
2128
    eWidth,
2129
    eHeight,
2130
  };
2131
  int32_t GetNewResizingIncrement(int32_t aX, int32_t aY,
2132
                                  ResizeAt aResizeAt);
2133
2134
  nsresult StartResizing(Element* aHandle);
2135
  int32_t GetNewResizingX(int32_t aX, int32_t aY);
2136
  int32_t GetNewResizingY(int32_t aX, int32_t aY);
2137
  int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
2138
  int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
2139
  void HideShadowAndInfo();
2140
  void SetFinalSize(int32_t aX, int32_t aY);
2141
  void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
2142
                           bool aPreserveRatio);
2143
2144
  /**
2145
   * HideAnonymousEditingUIs() forcibly hides all editing UIs (resizers,
2146
   * inline-table-editing UI, absolute positioning UI).
2147
   */
2148
  void HideAnonymousEditingUIs();
2149
2150
  /**
2151
   * HideAnonymousEditingUIsIfUnnecessary() hides all editing UIs if some of
2152
   * visible UIs are now unnecessary.
2153
   */
2154
  void HideAnonymousEditingUIsIfUnnecessary();
2155
2156
  /**
2157
   * sets the z-index of an element.
2158
   * @param aElement [IN] the element
2159
   * @param aZorder  [IN] the z-index
2160
   */
2161
  void SetZIndex(Element& aElement, int32_t aZorder);
2162
2163
  /**
2164
   * shows a grabber attached to an arbitrary element. The grabber is an image
2165
   * positioned on the left hand side of the top border of the element. Draggin
2166
   * and dropping it allows to change the element's absolute position in the
2167
   * document. See chrome://editor/content/images/grabber.gif
2168
   * @param aElement [IN] the element
2169
   */
2170
  nsresult ShowGrabberInternal(Element& aElement);
2171
2172
  /**
2173
   * Setting grabber to proper position for current mAbsolutelyPositionedObject.
2174
   * For example, while an element has grabber, the element may be resized
2175
   * or repositioned by script or something.  Then, you need to reset grabber
2176
   * position with this.
2177
   */
2178
  nsresult RefreshGrabberInternal();
2179
2180
  /**
2181
   * hide the grabber if it shown.
2182
   */
2183
  void HideGrabberInternal();
2184
2185
  /**
2186
   * CreateGrabberInternal() creates a grabber for moving aParentContent.
2187
   * This sets mGrabber to the new grabber.  If this returns true, it's
2188
   * always non-nullptr.  Otherwise, i.e., the grabber is hidden during
2189
   * creation, this returns false.
2190
   */
2191
  bool CreateGrabberInternal(nsIContent& aParentContent);
2192
2193
  nsresult StartMoving();
2194
  nsresult SetFinalPosition(int32_t aX, int32_t aY);
2195
  void AddPositioningOffset(int32_t& aX, int32_t& aY);
2196
  void SnapToGrid(int32_t& newX, int32_t& newY);
2197
  nsresult GrabberClicked();
2198
  nsresult EndMoving();
2199
  nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
2200
                                                        nsAString& aReturn);
2201
2202
  /**
2203
   * Shows inline table editing UI around a <table> element which contains
2204
   * aCellElement.  This returns error if creating UI is hidden during this,
2205
   * or detects another set of UI during this.  In such case, callers
2206
   * shouldn't keep handling anything for the UI.
2207
   *
2208
   * @param aCellElement    Must be an <td> or <th> element.
2209
   */
2210
  nsresult ShowInlineTableEditingUIInternal(Element& aCellElement);
2211
2212
  /**
2213
   * Hide all inline table editing UI.
2214
   */
2215
  void HideInlineTableEditingUIInternal();
2216
2217
  /**
2218
   * RefreshInlineTableEditingUIInternal() moves inline table editing UI to
2219
   * proper position.  This returns error if the UI is hidden or replaced
2220
   * during moving.
2221
   */
2222
  nsresult RefreshInlineTableEditingUIInternal();
2223
2224
  /**
2225
   * IsEmptyTextNode() returns true if aNode is a text node and does not have
2226
   * any visible characters.
2227
   */
2228
  bool IsEmptyTextNode(nsINode& aNode);
2229
2230
  bool IsSimpleModifiableNode(nsIContent* aContent,
2231
                              nsAtom* aProperty,
2232
                              nsAtom* aAttribute,
2233
                              const nsAString* aValue);
2234
  nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
2235
                                       nsAtom& aProperty,
2236
                                       nsAtom* aAttribute,
2237
                                       const nsAString& aValue);
2238
  typedef enum { eInserted, eAppended } InsertedOrAppended;
2239
  void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
2240
2241
  /**
2242
   * Returns an anonymous Element of type aTag,
2243
   * child of aParentContent. If aIsCreatedHidden is true, the class
2244
   * "hidden" is added to the created element. If aAnonClass is not
2245
   * the empty string, it becomes the value of the attribute "_moz_anonclass"
2246
   * @return a Element
2247
   * @param aTag             [IN] desired type of the element to create
2248
   * @param aParentContent   [IN] the parent node of the created anonymous
2249
   *                              element
2250
   * @param aAnonClass       [IN] contents of the _moz_anonclass attribute
2251
   * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
2252
   *                              is to be added to the created anonymous
2253
   *                              element
2254
   */
2255
  ManualNACPtr CreateAnonymousElement(nsAtom* aTag,
2256
                                      nsIContent& aParentContent,
2257
                                      const nsAString& aAnonClass,
2258
                                      bool aIsCreatedHidden);
2259
2260
  /**
2261
   * Reads a blob into memory and notifies the BlobReader object when the read
2262
   * operation is finished.
2263
   *
2264
   * @param aBlob       The input blob
2265
   * @param aWindow     The global object under which the read should happen.
2266
   * @param aBlobReader The blob reader object to be notified when finished.
2267
   */
2268
  static nsresult SlurpBlob(dom::Blob* aBlob,
2269
                            nsPIDOMWindowOuter* aWindow,
2270
                            BlobReader* aBlobReader);
2271
protected:
2272
  RefPtr<TypeInState> mTypeInState;
2273
  RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
2274
2275
  bool mCRInParagraphCreatesParagraph;
2276
2277
  bool mCSSAware;
2278
  UniquePtr<CSSEditUtils> mCSSEditUtils;
2279
2280
  // mSelectedCellIndex is reset by GetFirstSelectedTableCellElement(),
2281
  // then, it'll be referred and incremented by
2282
  // GetNextSelectedTableCellElement().
2283
  mutable uint32_t mSelectedCellIndex;
2284
2285
  nsString mLastStyleSheetURL;
2286
  nsString mLastOverrideStyleSheetURL;
2287
2288
  // Maintain a list of associated style sheets and their urls.
2289
  nsTArray<nsString> mStyleSheetURLs;
2290
  nsTArray<RefPtr<StyleSheet>> mStyleSheets;
2291
2292
  // resizing
2293
  // If the instance has shown resizers at least once, mHasShownResizers is
2294
  // set to true.
2295
  bool mHasShownResizers;
2296
  bool mIsObjectResizingEnabled;
2297
  bool mIsResizing;
2298
  bool mPreserveRatio;
2299
  bool mResizedObjectIsAnImage;
2300
2301
  // absolute positioning
2302
  bool mIsAbsolutelyPositioningEnabled;
2303
  bool mResizedObjectIsAbsolutelyPositioned;
2304
  // If the instance has shown grabber at least once, mHasShownGrabber is
2305
  // set to true.
2306
  bool mHasShownGrabber;
2307
  bool mGrabberClicked;
2308
  bool mIsMoving;
2309
2310
  bool mSnapToGridEnabled;
2311
2312
  // inline table editing
2313
  // If the instance has shown inline table editor at least once,
2314
  // mHasShownInlineTableEditor is set to true.
2315
  bool mHasShownInlineTableEditor;
2316
  bool mIsInlineTableEditingEnabled;
2317
2318
  // resizing
2319
  ManualNACPtr mTopLeftHandle;
2320
  ManualNACPtr mTopHandle;
2321
  ManualNACPtr mTopRightHandle;
2322
  ManualNACPtr mLeftHandle;
2323
  ManualNACPtr mRightHandle;
2324
  ManualNACPtr mBottomLeftHandle;
2325
  ManualNACPtr mBottomHandle;
2326
  ManualNACPtr mBottomRightHandle;
2327
2328
  RefPtr<Element> mActivatedHandle;
2329
2330
  ManualNACPtr mResizingShadow;
2331
  ManualNACPtr mResizingInfo;
2332
2333
  RefPtr<Element> mResizedObject;
2334
2335
  nsCOMPtr<nsIDOMEventListener>  mMouseMotionListenerP;
2336
  nsCOMPtr<nsIDOMEventListener>  mResizeEventListenerP;
2337
2338
  int32_t mOriginalX;
2339
  int32_t mOriginalY;
2340
2341
  int32_t mResizedObjectX;
2342
  int32_t mResizedObjectY;
2343
  int32_t mResizedObjectWidth;
2344
  int32_t mResizedObjectHeight;
2345
2346
  int32_t mResizedObjectMarginLeft;
2347
  int32_t mResizedObjectMarginTop;
2348
  int32_t mResizedObjectBorderLeft;
2349
  int32_t mResizedObjectBorderTop;
2350
2351
  int32_t mXIncrementFactor;
2352
  int32_t mYIncrementFactor;
2353
  int32_t mWidthIncrementFactor;
2354
  int32_t mHeightIncrementFactor;
2355
2356
  // When resizers, grabber and/or inline table editor are operated by user
2357
  // actually, the following counters are increased.
2358
  uint32_t mResizerUsedCount;
2359
  uint32_t mGrabberUsedCount;
2360
  uint32_t mInlineTableEditorUsedCount;
2361
2362
  int8_t  mInfoXIncrement;
2363
  int8_t  mInfoYIncrement;
2364
2365
  // absolute positioning
2366
  int32_t mPositionedObjectX;
2367
  int32_t mPositionedObjectY;
2368
  int32_t mPositionedObjectWidth;
2369
  int32_t mPositionedObjectHeight;
2370
2371
  int32_t mPositionedObjectMarginLeft;
2372
  int32_t mPositionedObjectMarginTop;
2373
  int32_t mPositionedObjectBorderLeft;
2374
  int32_t mPositionedObjectBorderTop;
2375
2376
  RefPtr<Element> mAbsolutelyPositionedObject;
2377
  ManualNACPtr mGrabber;
2378
  ManualNACPtr mPositioningShadow;
2379
2380
  int32_t mGridSize;
2381
2382
  // inline table editing
2383
  RefPtr<Element> mInlineEditedCell;
2384
2385
  ManualNACPtr mAddColumnBeforeButton;
2386
  ManualNACPtr mRemoveColumnButton;
2387
  ManualNACPtr mAddColumnAfterButton;
2388
2389
  ManualNACPtr mAddRowBeforeButton;
2390
  ManualNACPtr mRemoveRowButton;
2391
  ManualNACPtr mAddRowAfterButton;
2392
2393
  void AddMouseClickListener(Element* aElement);
2394
  void RemoveMouseClickListener(Element* aElement);
2395
2396
  nsCOMPtr<nsILinkHandler> mLinkHandler;
2397
2398
  ParagraphSeparator mDefaultParagraphSeparator;
2399
2400
  friend class AutoSelectionSetterAfterTableEdit;
2401
  friend class CSSEditUtils;
2402
  friend class DocumentResizeEventListener;
2403
  friend class EditorBase;
2404
  friend class EmptyEditableFunctor;
2405
  friend class HTMLEditRules;
2406
  friend class SlurpBlobEventListener;
2407
  friend class TextEditor;
2408
  friend class WSRunObject;
2409
};
2410
2411
} // namespace mozilla
2412
2413
mozilla::HTMLEditor*
2414
nsIEditor::AsHTMLEditor()
2415
0
{
2416
0
  return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
2417
0
           static_cast<mozilla::HTMLEditor*>(this) : nullptr;
2418
0
}
2419
2420
const mozilla::HTMLEditor*
2421
nsIEditor::AsHTMLEditor() const
2422
0
{
2423
0
  return static_cast<const mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
2424
0
           static_cast<const mozilla::HTMLEditor*>(this) : nullptr;
2425
0
}
2426
2427
#endif // #ifndef mozilla_HTMLEditor_h