Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/HTMLEditRules.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 HTMLEditRules_h
7
#define HTMLEditRules_h
8
9
#include "TypeInState.h"
10
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
11
#include "mozilla/SelectionState.h"
12
#include "mozilla/TextEditRules.h"
13
#include "nsCOMPtr.h"
14
#include "nsIEditor.h"
15
#include "nsIHTMLEditor.h"
16
#include "nsISupportsImpl.h"
17
#include "nsTArray.h"
18
#include "nscore.h"
19
20
class nsAtom;
21
class nsIEditor;
22
class nsINode;
23
class nsRange;
24
25
namespace mozilla {
26
27
class EditActionResult;
28
class HTMLEditor;
29
class SplitNodeResult;
30
class TextEditor;
31
enum class EditSubAction : int32_t;
32
33
namespace dom {
34
class Element;
35
class Selection;
36
} // namespace dom
37
38
struct StyleCache final : public PropItem
39
{
40
  bool mPresent;
41
42
  StyleCache()
43
    : PropItem()
44
    , mPresent(false)
45
0
  {
46
0
    MOZ_COUNT_CTOR(StyleCache);
47
0
  }
48
49
  StyleCache(nsAtom* aTag,
50
             nsAtom* aAttr,
51
             const nsAString& aValue)
52
    : PropItem(aTag, aAttr, aValue)
53
    , mPresent(false)
54
0
  {
55
0
    MOZ_COUNT_CTOR(StyleCache);
56
0
  }
57
58
  StyleCache(nsAtom* aTag,
59
             nsAtom* aAttr)
60
    : PropItem(aTag, aAttr, EmptyString())
61
    , mPresent(false)
62
0
  {
63
0
    MOZ_COUNT_CTOR(StyleCache);
64
0
  }
65
66
  ~StyleCache()
67
0
  {
68
0
    MOZ_COUNT_DTOR(StyleCache);
69
0
  }
70
};
71
72
/**
73
 * Same as TextEditRules, any methods which may modify the DOM tree or
74
 * Selection should be marked as MOZ_MUST_USE and return nsresult directly
75
 * or with simple class like EditActionResult.  And every caller of them
76
 * has to check whether the result is NS_ERROR_EDITOR_DESTROYED and if it is,
77
 * its callers should stop handling edit action since after mutation event
78
 * listener or selectionchange event listener disables the editor, we should
79
 * not modify the DOM tree nor Selection anymore.  And also when methods of
80
 * this class call methods of other classes like HTMLEditor and WSRunObject,
81
 * they should check whether CanHandleEditAtion() returns false immediately
82
 * after the calls.  If it returns false, they should return
83
 * NS_ERROR_EDITOR_DESTROYED.
84
 */
85
86
0
#define SIZE_STYLE_TABLE 19
87
88
class HTMLEditRules : public TextEditRules
89
{
90
public:
91
  NS_DECL_ISUPPORTS_INHERITED
92
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditRules, TextEditRules)
93
94
  HTMLEditRules();
95
96
  // TextEditRules methods
97
  virtual nsresult Init(TextEditor* aTextEditor) override;
98
  virtual nsresult DetachEditor() override;
99
  virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
100
                              nsIEditor::EDirection aDirection) override;
101
  virtual nsresult AfterEdit(EditSubAction aEditSubAction,
102
                             nsIEditor::EDirection aDirection) override;
103
  virtual nsresult WillDoAction(Selection* aSelection,
104
                                EditSubActionInfo& aInfo,
105
                                bool* aCancel,
106
                                bool* aHandled) override;
107
  virtual nsresult DidDoAction(Selection* aSelection,
108
                               EditSubActionInfo& aInfo,
109
                               nsresult aResult) override;
110
  virtual bool DocumentIsEmpty() override;
111
  virtual nsresult DocumentModified() override;
112
113
  nsresult GetListState(bool* aMixed, bool* aOL, bool* aUL, bool* aDL);
114
  nsresult GetListItemState(bool* aMixed, bool* aLI, bool* aDT, bool* aDD);
115
  nsresult GetAlignment(bool* aMixed, nsIHTMLEditor::EAlignment* aAlign);
116
  nsresult GetParagraphState(bool* aMixed, nsAString& outFormat);
117
118
  /**
119
   * MakeSureElemStartsAndEndsOnCR() inserts <br> element at start (and/or end)
120
   * of aNode if neither:
121
   * - first (last) editable child of aNode is a block or a <br>,
122
   * - previous (next) sibling of aNode is block or a <br>
123
   * - nor no previous (next) sibling of aNode.
124
   *
125
   * @param aNode               The node which may be inserted <br> elements.
126
   */
127
  MOZ_MUST_USE nsresult MakeSureElemStartsAndEndsOnCR(nsINode& aNode);
128
129
  void DidCreateNode(Selection& aSelection, Element& aNewElement);
130
  void DidInsertNode(Selection& aSelection, nsIContent& aNode);
131
  void WillDeleteNode(Selection& aSelection, nsINode& aChild);
132
  void DidSplitNode(Selection& aSelection,
133
                    nsINode& aExistingRightNode,
134
                    nsINode& aNewLeftNode);
135
  void WillJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
136
  void DidJoinNodes(Selection& aSelection,
137
                    nsINode& aLeftNode, nsINode& aRightNode);
138
  void DidInsertText(Selection& aSelection,
139
                     nsINode& aTextNode, int32_t aOffset,
140
                     const nsAString& aString);
141
  void DidDeleteText(Selection& aSelection,
142
                     nsINode& aTextNode, int32_t aOffset, int32_t aLength);
143
  void WillDeleteSelection(Selection& aSelection);
144
145
0
  void StartToListenToEditSubActions() { mListenerEnabled = true; }
146
0
  void EndListeningToEditSubActions() { mListenerEnabled = false; }
147
148
protected:
149
  virtual ~HTMLEditRules();
150
151
  HTMLEditor& HTMLEditorRef() const
152
0
  {
153
0
    MOZ_ASSERT(mData);
154
0
    return mData->HTMLEditorRef();
155
0
  }
156
157
  static bool IsBlockNode(const nsINode& aNode)
158
0
  {
159
0
    return HTMLEditor::NodeIsBlockStatic(&aNode);
160
0
  }
161
  static bool IsInlineNode(const nsINode& aNode)
162
0
  {
163
0
    return !IsBlockNode(aNode);
164
0
  }
165
166
  enum RulesEndpoint
167
  {
168
    kStart,
169
    kEnd
170
  };
171
172
  void InitFields();
173
174
  /**
175
   * Called before inserting something into the editor.
176
   * This method may removes mBougsNode if there is.  Therefore, this method
177
   * might cause destroying the editor.
178
   *
179
   * @param aCancel             Returns true if the operation is canceled.
180
   *                            This can be nullptr.
181
   */
182
  MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
183
184
  /**
185
   * Called before inserting text.
186
   * This method may actually inserts text into the editor.  Therefore, this
187
   * might cause destroying the editor.
188
   *
189
   * @param aEditSubAction      Must be EditSubAction::eInsertTextComingFromIME
190
   *                            or EditSubAction::eInsertText.
191
   * @param aCancel             Returns true if the operation is canceled.
192
   * @param aHandled            Returns true if the edit action is handled.
193
   * @param inString            String to be inserted.
194
   * @param outString           String actually inserted.
195
   * @param aMaxLength          The maximum string length which the editor
196
   *                            allows to set.
197
   */
198
  MOZ_MUST_USE nsresult
199
  WillInsertText(EditSubAction aEditSubAction, bool* aCancel, bool* aHandled,
200
                 const nsAString* inString, nsAString* outString,
201
                 int32_t aMaxLength);
202
203
  /**
204
   * WillLoadHTML() is called before loading enter document from source.
205
   * This removes bogus node if there is.
206
   */
207
  MOZ_MUST_USE nsresult WillLoadHTML();
208
209
  /**
210
   * WillInsertBreak() is called when insertParagraph command is executed
211
   * or something equivalent.  This method actually tries to insert new
212
   * paragraph or <br> element, etc.
213
   *
214
   * @param aCancel             Returns true if target node is not editable.
215
   * @param aHandled            Returns true if actually insert new break.
216
   */
217
  nsresult WillInsertBreak(bool* aCancel, bool* aHandled);
218
219
  /**
220
   * If aNode is a text node that contains only collapsed whitespace, delete
221
   * it.  It doesn't serve any useful purpose, and we don't want it to confuse
222
   * code that doesn't correctly skip over it.
223
   *
224
   * If deleting the node fails (like if it's not editable), the caller should
225
   * proceed as usual, so don't return any errors.
226
   */
227
  MOZ_MUST_USE nsresult DeleteNodeIfCollapsedText(nsINode& aNode);
228
229
  /**
230
   * InsertBRElement() inserts a <br> element into aInsertToBreak.
231
   *
232
   * @param aInsertToBreak      The point where new <br> element will be
233
   *                            inserted before.
234
   */
235
  MOZ_MUST_USE nsresult InsertBRElement(const EditorDOMPoint& aInsertToBreak);
236
237
  /**
238
   * SplitMailCites() splits mail-cite elements at start of Selection if
239
   * Selection starts from inside a mail-cite element.  Of course, if it's
240
   * necessary, this inserts <br> node to new left nodes or existing right
241
   * nodes.
242
   *
243
   * @param aHandled            Returns true if succeeded to split mail-cite
244
   *                            elements.
245
   */
246
  MOZ_MUST_USE nsresult SplitMailCites(bool* aHandled);
247
248
  /**
249
   * Called before deleting selected contents.  This method actually removes
250
   * selected contents.
251
   *
252
   * @param aAction             Direction of the deletion.
253
   * @param aStripWrappers      Must be eStrip or eNoStrip.
254
   * @param aCancel             Returns true if the operation is canceled.
255
   * @param aHandled            Returns true if the edit action is handled.
256
   */
257
  MOZ_MUST_USE nsresult
258
  WillDeleteSelection(nsIEditor::EDirection aAction,
259
                      nsIEditor::EStripWrappers aStripWrappers,
260
                      bool* aCancel, bool* aHandled);
261
262
  /**
263
   * Called after deleting selected content.
264
   * This method removes unnecessary empty nodes and/or inserts <br> if
265
   * necessary.
266
   */
267
  MOZ_MUST_USE nsresult DidDeleteSelection();
268
269
  /**
270
   * InsertBRIfNeeded() determines if a br is needed for current selection to
271
   * not be spastic.  If so, it inserts one.  Callers responsibility to only
272
   * call with collapsed selection.
273
   */
274
  MOZ_MUST_USE nsresult InsertBRIfNeeded();
275
276
  /**
277
   * CanContainParagraph() returns true if aElement can have a <p> element as
278
   * its child or its descendant.
279
   */
280
  bool CanContainParagraph(Element& aElement) const;
281
282
  /**
283
   * Insert normal <br> element into aNode when aNode is a block and it has
284
   * no children.
285
   */
286
  MOZ_MUST_USE nsresult InsertBRIfNeeded(nsINode& aNode)
287
0
  {
288
0
    return InsertBRIfNeededInternal(aNode, false);
289
0
  }
290
291
  /**
292
   * Insert moz-<br> element (<br type="_moz">) into aNode when aNode is a
293
   * block and it has no children.
294
   */
295
  MOZ_MUST_USE nsresult InsertMozBRIfNeeded(nsINode& aNode)
296
0
  {
297
0
    return InsertBRIfNeededInternal(aNode, true);
298
0
  }
299
300
  /**
301
   * Insert a normal <br> element or a moz-<br> element to aNode when
302
   * aNode is a block and it has no children.  Use InsertBRIfNeeded() or
303
   * InsertMozBRIfNeeded() instead.
304
   *
305
   * @param aNode           Reference to a block parent.
306
   * @param aInsertMozBR    true if this should insert a moz-<br> element.
307
   *                        Otherwise, i.e., this should insert a normal <br>
308
   *                        element, false.
309
   */
310
  MOZ_MUST_USE nsresult
311
  InsertBRIfNeededInternal(nsINode& aNode, bool aInsertMozBR);
312
313
  /**
314
   * GetGoodSelPointForNode() finds where at a node you would want to set the
315
   * selection if you were trying to have a caret next to it.  Always returns a
316
   * valid value (unless mHTMLEditor has gone away).
317
   *
318
   * @param aNode         The node
319
   * @param aAction       Which edge to find:
320
   *                        eNext/eNextWord/eToEndOfLine indicates beginning,
321
   *                        ePrevious/PreviousWord/eToBeginningOfLine ending.
322
   */
323
  EditorDOMPoint GetGoodSelPointForNode(nsINode& aNode,
324
                                        nsIEditor::EDirection aAction);
325
326
  /**
327
   * TryToJoinBlocksWithTransaction() tries to join two block elements.  The
328
   * right element is always joined to the left element.  If the elements are
329
   * the same type and not nested within each other,
330
   * JoinEditableNodesWithTransaction() is called (example, joining two list
331
   * items together into one).  If the elements are not the same type, or one
332
   * is a descendant of the other, we instead destroy the right block placing
333
   * its children into leftblock.  DTD containment rules are followed
334
   * throughout.
335
   *
336
   * @return            Sets canceled to true if the operation should do
337
   *                    nothing anymore even if this doesn't join the blocks.
338
   *                    Sets handled to true if this actually handles the
339
   *                    request.  Note that this may set it to true even if this
340
   *                    does not join the block.  E.g., if the blocks shouldn't
341
   *                    be joined or it's impossible to join them but it's not
342
   *                    unexpected case, this returns true with this.
343
   */
344
  MOZ_MUST_USE EditActionResult
345
  TryToJoinBlocksWithTransaction(nsIContent& aLeftNode,
346
                                 nsIContent& aRightNode);
347
348
  /**
349
   * MoveBlock() moves the content from aRightBlock starting from aRightOffset
350
   * into aLeftBlock at aLeftOffset. Note that the "block" can be inline nodes
351
   * between <br>s, or between blocks, etc.  DTD containment rules are followed
352
   * throughout.
353
   *
354
   * @return            Sets handled to true if this actually joins the nodes.
355
   *                    canceled is always false.
356
   */
357
  MOZ_MUST_USE EditActionResult
358
  MoveBlock(Element& aLeftBlock, Element& aRightBlock,
359
            int32_t aLeftOffset, int32_t aRightOffset);
360
361
  /**
362
   * MoveNodeSmart() moves aNode to (aDestElement, aInOutDestOffset).
363
   * DTD containment rules are followed throughout.
364
   *
365
   * @param aOffset                 returns the point after inserted content.
366
   * @return                        Sets true to handled if this actually moves
367
   *                                the nodes.
368
   *                                canceled is always false.
369
   */
370
  MOZ_MUST_USE EditActionResult
371
  MoveNodeSmart(nsIContent& aNode, Element& aDestElement,
372
                int32_t* aInOutDestOffset);
373
374
  /**
375
   * MoveContents() moves the contents of aElement to (aDestElement,
376
   * aInOutDestOffset).  DTD containment rules are followed throughout.
377
   *
378
   * @param aInOutDestOffset        updated to point after inserted content.
379
   * @return                        Sets true to handled if this actually moves
380
   *                                the nodes.
381
   *                                canceled is always false.
382
   */
383
  MOZ_MUST_USE EditActionResult
384
  MoveContents(Element& aElement, Element& aDestElement,
385
               int32_t* aInOutDestOffset);
386
387
  /**
388
   * DeleteElementsExceptTableRelatedElements() removes elements except
389
   * table related elements (except <table> itself) and their contents
390
   * from the DOM tree.
391
   *
392
   * @param aNode               If this is not a table related element, this
393
   *                            node will be removed from the DOM tree.
394
   *                            Otherwise, this method calls itself recursively
395
   *                            with its children.
396
   *
397
   */
398
  MOZ_MUST_USE nsresult
399
  DeleteElementsExceptTableRelatedElements(nsINode& aNode);
400
401
  /**
402
   * XXX Should document what this does.
403
   */
404
  MOZ_MUST_USE nsresult
405
  WillMakeList(const nsAString* aListType, bool aEntireList,
406
               const nsAString* aBulletType,
407
               bool* aCancel, bool* aHandled,
408
               const nsAString* aItemType = nullptr);
409
410
  /**
411
   * Called before removing a list element.  This method actually removes
412
   * list elements and list item elements at Selection.  And move contents
413
   * in them where the removed list was.
414
   *
415
   * @param aCancel             Returns true if the operation is canceled.
416
   * @param aHandled            Returns true if the edit action is handled.
417
   */
418
  MOZ_MUST_USE nsresult WillRemoveList(bool* aCancel, bool* aHandled);
419
420
  /**
421
   * Called before indenting around Selection.  This method actually tries to
422
   * indent the contents.
423
   *
424
   * @param aCancel             Returns true if the operation is canceled.
425
   * @param aHandled            Returns true if the edit action is handled.
426
   */
427
  MOZ_MUST_USE nsresult WillIndent(bool* aCancel, bool* aHandled);
428
429
  /**
430
   * Called before indenting around Selection and it's in CSS mode.
431
   * This method actually tries to indent the contents.
432
   *
433
   * @param aCancel             Returns true if the operation is canceled.
434
   * @param aHandled            Returns true if the edit action is handled.
435
   */
436
  MOZ_MUST_USE nsresult WillCSSIndent(bool* aCancel, bool* aHandled);
437
438
  /**
439
   * Called before indenting around Selection and it's not in CSS mode.
440
   * This method actually tries to indent the contents.
441
   *
442
   * @param aCancel             Returns true if the operation is canceled.
443
   * @param aHandled            Returns true if the edit action is handled.
444
   */
445
  MOZ_MUST_USE nsresult WillHTMLIndent(bool* aCancel, bool* aHandled);
446
447
  /**
448
   * Called before outdenting around Selection.  This method actually tries
449
   * to indent the contents.
450
   *
451
   * @param aCancel             Returns true if the operation is canceled.
452
   * @param aHandled            Returns true if the edit action is handled.
453
   */
454
  MOZ_MUST_USE nsresult WillOutdent(bool* aCancel, bool* aHandled);
455
456
  /**
457
   * Called before aligning contents around Selection.  This method actually
458
   * sets align attributes to align contents.
459
   *
460
   * @param aAlignType          New align attribute value where the contents
461
   *                            should be aligned to.
462
   * @param aCancel             Returns true if the operation is canceled.
463
   * @param aHandled            Returns true if the edit action is handled.
464
   */
465
  nsresult WillAlign(const nsAString& aAlignType,
466
                     bool* aCancel, bool* aHandled);
467
468
  /**
469
   * Called before changing absolute positioned element to static positioned.
470
   * This method actually changes the position property of nearest absolute
471
   * positioned element.  Therefore, this might cause destroying the HTML
472
   * editor.
473
   *
474
   * @param aCancel             Returns true if the operation is canceled.
475
   * @param aHandled            Returns true if the edit action is handled.
476
   */
477
  MOZ_MUST_USE nsresult
478
  WillRemoveAbsolutePosition(bool* aCancel, bool* aHandled);
479
480
  /**
481
   * Called before changing z-index.
482
   * This method actually changes z-index of nearest absolute positioned
483
   * element relatively.  Therefore, this might cause destroying the HTML
484
   * editor.
485
   *
486
   * @param aChange             Amount to change z-index.
487
   * @param aCancel             Returns true if the operation is canceled.
488
   * @param aHandled            Returns true if the edit action is handled.
489
   */
490
  MOZ_MUST_USE nsresult
491
  WillRelativeChangeZIndex(int32_t aChange, bool* aCancel, bool* aHandled);
492
493
  /**
494
   * Called before creating aDefinitionListItemTag around Selection.  This
495
   * method just calls WillMakeList() with "dl" as aListType and
496
   * aDefinitionListItemTag as aItemType.
497
   *
498
   * @param aDefinitionListItemTag  Should be "dt" or "dd".
499
   * @param aEntireList             XXX not sure
500
   * @param aCancel                 Returns true if the operation is canceled.
501
   * @param aHandled                Returns true if the edit action is handled.
502
   */
503
  MOZ_MUST_USE nsresult
504
  WillMakeDefListItem(const nsAString* aBlockType, bool aEntireList,
505
                      bool* aCancel, bool* aHandled);
506
507
  /**
508
   * WillMakeBasicBlock() called before changing block style around Selection.
509
   * This method actually does something with calling MakeBasicBlock().
510
   *
511
   * @param aBlockType          Necessary block style as string.
512
   * @param aCancel             Returns true if the operation is canceled.
513
   * @param aHandled            Returns true if the edit action is handled.
514
   */
515
  MOZ_MUST_USE nsresult WillMakeBasicBlock(const nsAString& aBlockType,
516
                                           bool* aCancel, bool* aHandled);
517
518
  /**
519
   * MakeBasicBlock() applies or clears block style around Selection.
520
   * This method creates AutoSelectionRestorer.  Therefore, each caller
521
   * need to check if the editor is still available even if this returns
522
   * NS_OK.
523
   *
524
   * @param aBlockType          New block tag name.
525
   *                            If nsGkAtoms::normal or nsGkAtoms::_empty,
526
   *                            RemoveBlockStyle() will be called.
527
   *                            If nsGkAtoms::blockquote, MakeBlockquote()
528
   *                            will be called.
529
   *                            Otherwise, ApplyBlockStyle() will be called.
530
   */
531
  MOZ_MUST_USE nsresult MakeBasicBlock(nsAtom& aBlockType);
532
533
  /**
534
   * Called after creating a basic block, indenting, outdenting or aligning
535
   * contents.  This method inserts moz-<br> element if start container of
536
   * Selection needs it.
537
   */
538
  MOZ_MUST_USE nsresult DidMakeBasicBlock();
539
540
  /**
541
   * Called before changing an element to absolute positioned.
542
   * This method only prepares the operation since DidAbsolutePosition() will
543
   * change it actually later.  mNewBlock is set to the target element and
544
   * if necessary, some ancestor nodes of selection may be split.
545
   *
546
   * @param aCancel             Returns true if the operation is canceled.
547
   * @param aHandled            Returns true if the edit action is handled.
548
   */
549
  MOZ_MUST_USE nsresult WillAbsolutePosition(bool* aCancel, bool* aHandled);
550
551
  /**
552
   * PrepareToMakeElementAbsolutePosition() is helper method of
553
   * WillAbsolutePosition() since in some cases, needs to restore selection
554
   * with AutoSelectionRestorer.  So, all callers have to check if
555
   * CanHandleEditAction() still returns true after a call of this method.
556
   * XXX Should be documented outline of this method.
557
   *
558
   * @param aHandled            Returns true if the edit action is handled.
559
   * @param aTargetElement      Returns target element which should be
560
   *                            changed to absolute positioned.
561
   */
562
  MOZ_MUST_USE nsresult
563
  PrepareToMakeElementAbsolutePosition(bool* aHandled,
564
                                       RefPtr<Element>* aTargetElement);
565
566
  /**
567
   * Called if nobody handles the edit action to make an element absolute
568
   * positioned.
569
   * This method actually changes the element which is computed by
570
   * WillAbsolutePosition() to absolute positioned.
571
   * Therefore, this might cause destroying the HTML editor.
572
   */
573
  MOZ_MUST_USE nsresult DidAbsolutePosition();
574
575
  /**
576
   * AlignInnerBlocks() calls AlignBlockContents() for every list item element
577
   * and table cell element in aNode.
578
   *
579
   * @param aNode               The node whose descendants should be aligned
580
   *                            to aAlignType.
581
   * @param aAlignType          New value of align attribute of <div>.
582
   */
583
  MOZ_MUST_USE nsresult
584
  AlignInnerBlocks(nsINode& aNode, const nsAString& aAlignType);
585
586
  /**
587
   * AlignBlockContents() sets align attribute of <div> element which is
588
   * only child of aNode to aAlignType.  If aNode has 2 or more children or
589
   * does not have a <div> element has only child, inserts a <div> element
590
   * into aNode and move all children of aNode into the new <div> element.
591
   *
592
   * @param aNode               The node whose contents should be aligned
593
   *                            to aAlignType.
594
   * @param aAlignType          New value of align attribute of <div> which
595
   *                            is only child of aNode.
596
   */
597
  MOZ_MUST_USE nsresult
598
  AlignBlockContents(nsINode& aNode, const nsAString& aAlignType);
599
600
  /**
601
   * AlignContentsAtSelection() aligns contents around Selection to aAlignType.
602
   * This creates AutoSelectionRestorer.  Therefore, even if this returns
603
   * NS_OK, CanHandleEditAction() may return false if the editor is destroyed
604
   * during restoring the Selection.  So, every caller needs to check if
605
   * CanHandleEditAction() returns true before modifying the DOM tree or
606
   * changing Selection.
607
   *
608
   * @param aAlignType          New align attribute value where the contents
609
   *                            should be aligned to.
610
   */
611
  MOZ_MUST_USE nsresult
612
  AlignContentsAtSelection(const nsAString& aAlignType);
613
614
  nsresult AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
615
                                  nsINode* aNode);
616
  nsresult GetFormatString(nsINode* aNode, nsAString &outFormat);
617
618
  /**
619
   * aLists and aTables allow the caller to specify what kind of content to
620
   * "look inside".  If aTables is Tables::yes, look inside any table content,
621
   * and insert the inner content into the supplied nsTArray at offset
622
   * aIndex.  Similarly with aLists and list content.  aIndex is updated to
623
   * point past inserted elements.
624
   */
625
  enum class Lists { no, yes };
626
  enum class Tables { no, yes };
627
  void GetInnerContent(nsINode& aNode,
628
                       nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
629
                       int32_t* aIndex, Lists aLists = Lists::yes,
630
                       Tables aTables = Tables::yes);
631
632
  /**
633
   * If aNode is the descendant of a listitem, return that li.  But table
634
   * element boundaries are stoppers on the search.  Also stops on the active
635
   * editor host (contenteditable).  Also test if aNode is an li itself.
636
   */
637
  Element* IsInListItem(nsINode* aNode);
638
639
  nsAtom& DefaultParagraphSeparator();
640
641
  /**
642
   * ReturnInHeader() handles insertParagraph command (i.e., handling Enter
643
   * key press) in a heading element.  This splits aHeader element at
644
   * aOffset in aNode.  Then, if right heading element is empty, it'll be
645
   * removed and new paragraph is created (its type is decided with default
646
   * paragraph separator).
647
   *
648
   * @param aHeader             The heading element to be split.
649
   * @param aNode               Typically, Selection start container,
650
   *                            where to be split.
651
   * @param aOffset             Typically, Selection start offset in the
652
   *                            start container, where to be split.
653
   */
654
  MOZ_MUST_USE nsresult
655
  ReturnInHeader(Element& aHeader, nsINode& aNode, int32_t aOffset);
656
657
  /**
658
   * ReturnInParagraph() does the right thing for Enter key press or
659
   * 'insertParagraph' command in aParentDivOrP.  aParentDivOrP will be
660
   * split at start of first selection range.
661
   *
662
   * @param aParentDivOrP   The parent block.  This must be <p> or <div>
663
   *                        element.
664
   * @return                Returns with NS_OK if this doesn't meat any
665
   *                        unexpected situation.  If this method tries to
666
   *                        split the paragraph, marked as handled.
667
   */
668
  MOZ_MUST_USE EditActionResult ReturnInParagraph(Element& aParentDivOrP);
669
670
  /**
671
   * SplitParagraph() splits the parent block, aPara, at aSelNode - aOffset.
672
   *
673
   * @param aParentDivOrP       The parent block to be split.  This must be <p>
674
   *                            or <div> element.
675
   * @param aStartOfRightNode   The point to be start of right node after
676
   *                            split.  This must be descendant of
677
   *                            aParentDivOrP.
678
   * @param aNextBRNode         Next <br> node if there is.  Otherwise, nullptr.
679
   *                            If this is not nullptr, the <br> node may be
680
   *                            removed.
681
   */
682
  template<typename PT, typename CT>
683
  MOZ_MUST_USE nsresult
684
  SplitParagraph(Element& aParentDivOrP,
685
                 const EditorDOMPointBase<PT, CT>& aStartOfRightNode,
686
                 nsIContent* aBRNode);
687
688
  /**
689
   * ReturnInListItem() handles insertParagraph command (i.e., handling
690
   * Enter key press) in a list item element.
691
   *
692
   * @param aListItem           The list item which has the following point.
693
   * @param aNode               Typically, Selection start container, where to
694
   *                            insert a break.
695
   * @param aOffset             Typically, Selection start offset in the
696
   *                            start container, where to insert a break.
697
   */
698
  MOZ_MUST_USE nsresult
699
  ReturnInListItem(Element& aListItem, nsINode& aNode, int32_t aOffset);
700
701
  /**
702
   * Called after handling edit action.  This may adjust Selection, remove
703
   * unnecessary empty nodes, create <br> elements if needed, etc.
704
   */
705
  MOZ_MUST_USE nsresult
706
  AfterEditInner(EditSubAction aEditSubAction,
707
                 nsIEditor::EDirection aDirection);
708
709
  /**
710
   * IndentAroundSelectionWithCSS() indents around Selection with CSS.
711
   * This method creates AutoSelectionRestorer.  Therefore, each caller
712
   * need to check if the editor is still available even if this returns
713
   * NS_OK.
714
   */
715
  MOZ_MUST_USE nsresult IndentAroundSelectionWithCSS();
716
717
  /**
718
   * IndentAroundSelectionWithHTML() indents around Selection with HTML.
719
   * This method creates AutoSelectionRestorer.  Therefore, each caller
720
   * need to check if the editor is still available even if this returns
721
   * NS_OK.
722
   */
723
  MOZ_MUST_USE nsresult IndentAroundSelectionWithHTML();
724
725
  /**
726
   * OutdentAroundSelection() outdents contents around Selection.
727
   * This method creates AutoSelectionRestorer.  Therefore, each caller
728
   * need to check if the editor is still available even if this returns
729
   * NS_OK.
730
   *
731
   * @return                    The left content is left content of last
732
   *                            outdented element.
733
   *                            The right content is right content of last
734
   *                            outdented element.
735
   *                            The middle content is middle content of last
736
   *                            outdented element.
737
   */
738
  MOZ_MUST_USE SplitRangeOffFromNodeResult OutdentAroundSelection();
739
740
  /**
741
   * SplitRangeOffFromBlockAndRemoveMiddleContainer() splits the nodes
742
   * between aStartOfRange and aEndOfRange, then, removes the middle element
743
   * and moves its content to where the middle element was.
744
   *
745
   * @param aBlockElement           The node which will be split.
746
   * @param aStartOfRange           The first node which will be unwrapped
747
   *                                from aBlockElement.
748
   * @param aEndOfRange             The last node which will be unwrapped from
749
   *                                aBlockElement.
750
   * @return                        The left content is new created left
751
   *                                element of aBlockElement.
752
   *                                The right content is split element,
753
   *                                i.e., must be aBlockElement.
754
   *                                The middle content is nullptr since
755
   *                                removing it is the job of this method.
756
   */
757
  MOZ_MUST_USE SplitRangeOffFromNodeResult
758
  SplitRangeOffFromBlockAndRemoveMiddleContainer(Element& aBlockElement,
759
                                                 nsIContent& aStartOfRange,
760
                                                 nsIContent& aEndOfRange);
761
762
  /**
763
   * SplitRangeOffFromBlock() splits aBlock at two points, before aStartChild
764
   * and after aEndChild.  If they are very start or very end of aBlcok, this
765
   * won't create empty block.
766
   *
767
   * @param aBlockElement           A block element which will be split.
768
   * @param aStartOfMiddleElement   Start node of middle block element.
769
   * @param aEndOfMiddleElement     End node of middle block element.
770
   */
771
  MOZ_MUST_USE SplitRangeOffFromNodeResult
772
  SplitRangeOffFromBlock(Element& aBlockElement,
773
                         nsIContent& aStartOfMiddleElement,
774
                         nsIContent& aEndOfMiddleElement);
775
776
  /**
777
   * OutdentPartOfBlock() outdents the nodes between aStartOfOutdent and
778
   * aEndOfOutdent.  This splits the range off from aBlockElement first.
779
   * Then, removes the middle element if aIsBlockIndentedWithCSS is false.
780
   * Otherwise, decreases the margin of the middle element.
781
   *
782
   * @param aBlockElement           A block element which includes both
783
   *                                aStartOfOutdent and aEndOfOutdent.
784
   * @param aStartOfOutdent         First node which is descendant of
785
   *                                aBlockElement will be outdented.
786
   * @param aEndOfOutdent           Last node which is descandant of
787
   *                                aBlockElement will be outdented.
788
   * @param aIsBlockIndentedWithCSS true if aBlockElement is indented with
789
   *                                CSS margin property.
790
   *                                false if aBlockElement is <blockquote>
791
   *                                or something.
792
   * @return                        The left content is new created element
793
   *                                splitting before aStartOfOutdent.
794
   *                                The right content is existing element.
795
   *                                The middle content is outdented element
796
   *                                if aIsBlockIndentedWithCSS is true.
797
   *                                Otherwise, nullptr.
798
   */
799
  MOZ_MUST_USE SplitRangeOffFromNodeResult
800
  OutdentPartOfBlock(Element& aBlockElement,
801
                     nsIContent& aStartOfOutdent, nsIContent& aEndOutdent,
802
                     bool aIsBlockIndentedWithCSS);
803
804
  /**
805
   * XXX Should document what this does.
806
   * This method creates AutoSelectionRestorer.  Therefore, each caller
807
   * need to check if the editor is still available even if this returns
808
   * NS_OK.
809
   */
810
  MOZ_MUST_USE nsresult
811
  MakeList(nsAtom& aListType, bool aEntireList, const nsAString* aBulletType,
812
           bool* aCancel, nsAtom& aItemType);
813
814
  /**
815
   * ConvertListType() replaces child list items of aListElement with
816
   * new list item element whose tag name is aNewListItemTag.
817
   * Note that if there are other list elements as children of aListElement,
818
   * this calls itself recursively even though it's invalid structure.
819
   *
820
   * @param aListElement        The list element whose list items will be
821
   *                            replaced.
822
   * @param aNewListTag         New list tag name.
823
   * @param aNewListItemTag     New list item tag name.
824
   * @return                    New list element or an error code if it fails.
825
   *                            New list element may be aListElement if its
826
   *                            tag name is same as aNewListTag.
827
   */
828
  MOZ_MUST_USE CreateElementResult
829
  ConvertListType(Element& aListElement, nsAtom& aListType, nsAtom& aItemType);
830
831
  /**
832
   * CreateStyleForInsertText() sets CSS properties which are stored in
833
   * TypeInState to proper element node.
834
   *
835
   * @param aDocument           The document of the editor.
836
   */
837
  MOZ_MUST_USE nsresult CreateStyleForInsertText(nsIDocument& aDocument);
838
839
  /**
840
   * IsEmptyBlockElement() returns true if aElement is a block level element
841
   * and it doesn't have any visible content.
842
   */
843
  enum class IgnoreSingleBR
844
  {
845
    eYes,
846
    eNo
847
  };
848
  bool IsEmptyBlockElement(Element& aElement,
849
                           IgnoreSingleBR aIgnoreSingleBR);
850
851
  /**
852
   * MaybeDeleteTopMostEmptyAncestor() looks for top most empty block ancestor
853
   * of aStartNode in aEditingHostElement.
854
   * If found empty ancestor is a list item element, inserts a <br> element
855
   * before its parent element if grand parent is a list element.  Then,
856
   * collapse Selection to after the empty block.
857
   * If found empty ancestor is not a list item element, collapse Selection to
858
   * somewhere depending on aAction.
859
   * Finally, removes the empty block ancestor.
860
   *
861
   * @param aStartNode          Start node to look for empty ancestors.
862
   * @param aEditingHostElement Current editing host.
863
   * @param aAction             If found empty ancestor block is a list item
864
   *                            element, this is ignored.  Otherwise:
865
   *                            - If eNext, eNextWord or eToEndOfLine, collapse
866
   *                              Selection to after found empty ancestor.
867
   *                            - If ePrevious, ePreviousWord or
868
   *                              eToBeginningOfLine, collapse Selection to
869
   *                              end of previous editable node.
870
   *                            Otherwise, eNone is allowed but does nothing.
871
   * @param aHandled            Returns true if this method removes an empty
872
   *                            block ancestor of aStartNode.
873
   */
874
  MOZ_MUST_USE nsresult
875
  MaybeDeleteTopMostEmptyAncestor(nsINode& aStartNode,
876
                                  Element& aEditingHostElement,
877
                                  nsIEditor::EDirection aAction,
878
                                  bool* aHandled);
879
880
  enum class BRLocation { beforeBlock, blockEnd };
881
  Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
882
                               int32_t aOffset = 0);
883
884
  /**
885
   * ExpandSelectionForDeletion() may expand Selection range if it's not
886
   * collapsed and there is only one range.  This may expand to include
887
   * invisible <br> element for preventing delete action handler to keep
888
   * unexpected nodes.
889
   */
890
  MOZ_MUST_USE nsresult ExpandSelectionForDeletion();
891
892
  /**
893
   * NormalizeSelection() adjust Selection if it's not collapsed and there is
894
   * only one range.  If range start and/or end point is <br> node or something
895
   * non-editable point, they should be moved to nearest text node or something
896
   * where the other methods easier to handle edit action.
897
   */
898
  MOZ_MUST_USE nsresult NormalizeSelection();
899
900
  /**
901
   * GetPromotedPoint() figures out where a start or end point for a block
902
   * operation really is.
903
   */
904
  EditorDOMPoint
905
  GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode, int32_t aOffset,
906
                   EditSubAction aEditSubAction);
907
908
  /**
909
   * GetPromotedRanges() runs all the selection range endpoint through
910
   * GetPromotedPoint().
911
   */
912
  void GetPromotedRanges(nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
913
                         EditSubAction aEditSubAction);
914
915
  /**
916
   * PromoteRange() expands a range to include any parents for which all
917
   * editable children are already in range.
918
   */
919
  void PromoteRange(nsRange& aRange, EditSubAction aEditSubAction);
920
921
  /**
922
   * GetNodesForOperation() runs through the ranges in the array and construct a
923
   * new array of nodes to be acted on.
924
   *
925
   * XXX This name stats with "Get" but actually this modifies the DOM tree with
926
   *     transaction.  We should rename this to making clearer what this does.
927
   */
928
  enum class TouchContent { no, yes };
929
  MOZ_MUST_USE nsresult
930
  GetNodesForOperation(nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
931
                       nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
932
                       EditSubAction aEditSubAction,
933
                       TouchContent aTouchContent);
934
935
  void GetChildNodesForOperation(
936
         nsINode& aNode,
937
         nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
938
939
  /**
940
   * GetNodesFromPoint() constructs a list of nodes from a point that will be
941
   * operated on.
942
   */
943
  MOZ_MUST_USE nsresult
944
  GetNodesFromPoint(const EditorDOMPoint& aPoint, EditSubAction aEditSubAction,
945
                    nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
946
                    TouchContent aTouchContent);
947
948
  /**
949
   * GetNodesFromSelection() constructs a list of nodes from the selection that
950
   * will be operated on.
951
   */
952
  MOZ_MUST_USE nsresult
953
  GetNodesFromSelection(EditSubAction aEditSubAction,
954
                        nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
955
                        TouchContent aTouchContent);
956
957
  enum class EntireList { no, yes };
958
  MOZ_MUST_USE nsresult
959
  GetListActionNodes(nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
960
                     EntireList aEntireList, TouchContent aTouchContent);
961
  void GetDefinitionListItemTypes(Element* aElement, bool* aDT, bool* aDD);
962
  nsresult
963
  GetParagraphFormatNodes(nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
964
  void LookInsideDivBQandList(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
965
966
  /**
967
   * BustUpInlinesAtRangeEndpoints() splits nodes at both start and end of
968
   * aRangeItem.  If this splits at every point, this modifies aRangeItem
969
   * to point each split point (typically, right node).  Note that this splits
970
   * nodes only in highest inline element at every point.
971
   *
972
   * @param aRangeItem          One or two DOM points where should be split.
973
   *                            Will be modified to split point if they're
974
   *                            split.
975
   */
976
  MOZ_MUST_USE nsresult BustUpInlinesAtRangeEndpoints(RangeItem& aRangeItem);
977
978
  /**
979
   * BustUpInlinesAtBRs() splits before all <br> elements in aNode.  All <br>
980
   * nodes will be moved before right node at splitting its parent.  Finally,
981
   * this returns all <br> elements, every left node and aNode with
982
   * aOutArrayNodes.
983
   *
984
   * @param aNode               An inline container element.
985
   * @param aOutArrayOfNodes    All found <br> elements, left nodes (may not
986
   *                            be set if <br> is at start edge of aNode) and
987
   *                            aNode itself.
988
   */
989
  MOZ_MUST_USE nsresult
990
  BustUpInlinesAtBRs(nsIContent& aNode,
991
                     nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
992
993
  /**
994
   * GetHiestInlineParent() returns the highest inline node parent between
995
   * aNode and the editing host.  Even if the editing host is an inline
996
   * element, this method never returns the editing host as the result.
997
   */
998
  nsIContent* GetHighestInlineParent(nsINode& aNode);
999
1000
  /**
1001
   * MakeTransitionList() detects all the transitions in the array, where a
1002
   * transition means that adjacent nodes in the array don't have the same
1003
   * parent.
1004
   */
1005
  void MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
1006
                          nsTArray<bool>& aTransitionArray);
1007
1008
  /**
1009
   * RemoveBlockStyle() removes all format blocks, table related element,
1010
   * etc in aNodeArray.
1011
   * If aNodeArray has a format node, it will be removed and its contents
1012
   * will be moved to where it was.
1013
   * If aNodeArray has a table related element, <li>, <blockquote> or <div>,
1014
   * it will removed and its contents will be moved to where it was.
1015
   */
1016
  nsresult RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
1017
1018
  /**
1019
   * ApplyBlockStyle() formats all nodes in aNodeArray with block elements
1020
   * whose name is aBlockTag.
1021
   * If aNodeArray has an inline element, a block element is created and the
1022
   * inline element and following inline elements are moved into the new block
1023
   * element.
1024
   * If aNodeArray has <br> elements, they'll be removed from the DOM tree and
1025
   * new block element will be created when there are some remaining inline
1026
   * elements.
1027
   * If aNodeArray has a block element, this calls itself with children of
1028
   * the block element.  Then, new block element will be created when there
1029
   * are some remaining inline elements.
1030
   *
1031
   * @param aNodeArray      Must be descendants of a node.
1032
   * @param aBlockTag       The element name of new block elements.
1033
   */
1034
  MOZ_MUST_USE nsresult
1035
  ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
1036
                  nsAtom& aBlockTag);
1037
1038
  /**
1039
   * MakeBlockquote() inserts at least one <blockquote> element and moves
1040
   * nodes in aNodeArray into new <blockquote> elements.  If aNodeArray
1041
   * includes a table related element except <table>, this calls itself
1042
   * recursively to insert <blockquote> into the cell.
1043
   *
1044
   * @param aNodeArray          Nodes which will be moved into created
1045
   *                            <blockquote> elements.
1046
   */
1047
  MOZ_MUST_USE nsresult
1048
  MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
1049
1050
  /**
1051
   * MaybeSplitAncestorsForInsertWithTransaction() does nothing if container of
1052
   * aStartOfDeepestRightNode can have an element whose tag name is aTag.
1053
   * Otherwise, looks for an ancestor node which is or is in active editing
1054
   * host and can have an element whose name is aTag.  If there is such
1055
   * ancestor, its descendants are split.
1056
   *
1057
   * Note that this may create empty elements while splitting ancestors.
1058
   *
1059
   * @param aTag                        The name of element to be inserted
1060
   *                                    after calling this method.
1061
   * @param aStartOfDeepestRightNode    The start point of deepest right node.
1062
   *                                    This point must be descendant of
1063
   *                                    active editing host.
1064
   * @return                            When succeeded, SplitPoint() returns
1065
   *                                    the point to insert the element.
1066
   */
1067
  template<typename PT, typename CT>
1068
  MOZ_MUST_USE SplitNodeResult
1069
  MaybeSplitAncestorsForInsertWithTransaction(
1070
    nsAtom& aTag, const EditorDOMPointBase<PT, CT>& aStartOfDeepestRightNode);
1071
1072
  /**
1073
   * JoinNearestEditableNodesWithTransaction() joins two editable nodes which
1074
   * are themselves or the nearest editable node of aLeftNode and aRightNode.
1075
   * XXX This method's behavior is odd.  For example, if user types Backspace
1076
   *     key at the second editable paragraph in this case:
1077
   *     <div contenteditable>
1078
   *       <p>first editable paragraph</p>
1079
   *       <p contenteditable="false">non-editable paragraph</p>
1080
   *       <p>second editable paragraph</p>
1081
   *     </div>
1082
   *     The first editable paragraph's content will be moved into the second
1083
   *     editable paragraph and the non-editable paragraph becomes the first
1084
   *     paragraph of the editor.  I don't think that it's expected behavior of
1085
   *     any users...
1086
   *
1087
   * @param aLeftNode   The node which will be removed.
1088
   * @param aRightNode  The node which will be inserted the content of
1089
   *                    aLeftNode.
1090
   * @param aNewFirstChildOfRightNode
1091
   *                    The point at the first child of aRightNode.
1092
   */
1093
  MOZ_MUST_USE nsresult
1094
  JoinNearestEditableNodesWithTransaction(
1095
    nsIContent& aLeftNode, nsIContent& aRightNode,
1096
    EditorDOMPoint* aNewFirstChildOfRightNode);
1097
1098
  Element* GetTopEnclosingMailCite(nsINode& aNode);
1099
1100
  /**
1101
   * PopListItem() tries to move aListItem outside its parent.  If it's
1102
   * in a middle of a list element, the parent list element is split before
1103
   * aListItem.  Then, moves aListItem to before its parent list element.
1104
   * I.e., moves aListItem between the 2 list elements if original parent
1105
   * was split.  Then, if new parent is not a list element, the list item
1106
   * element is removed and its contents are moved to where the list item
1107
   * element was.
1108
   *
1109
   * @param aListItem           Should be a <li>, <dt> or <dd> element.
1110
   *                            If it's not so, returns NS_ERROR_FAILURE.
1111
   * @param aOutOfList          Returns true if the list item element is
1112
   *                            removed (i.e., unwrapped contents of
1113
   *                            aListItem).  Otherwise, false.
1114
   */
1115
  MOZ_MUST_USE nsresult
1116
  PopListItem(nsIContent& aListItem, bool* aOutOfList = nullptr);
1117
1118
  /**
1119
   * RemoveListStructure() destroys the list structure of aListElement.
1120
   * If aListElement has <li>, <dl> or <dt> as a child, the element is removed
1121
   * but its descendants are moved to where the list item element was.
1122
   * If aListElement has another <ul>, <ol> or <dl> as a child, this method
1123
   * is called recursively.
1124
   * If aListElement has other nodes as its child, they are just removed.
1125
   * Finally, aListElement is removed. and its all children are moved to
1126
   * where the aListElement was.
1127
   *
1128
   * @param aListElement        A <ul>, <ol> or <dl> element.
1129
   */
1130
  MOZ_MUST_USE nsresult RemoveListStructure(Element& aListElement);
1131
1132
  /**
1133
   * CacheInlineStyles() caches style of aNode into mCachedStyles.
1134
   * This may cause flushing layout at retrieving computed value of CSS
1135
   * properties.
1136
   */
1137
  MOZ_MUST_USE nsresult CacheInlineStyles(nsINode* aNode);
1138
1139
  /**
1140
   * ReapplyCachedStyles() restores some styles which are disappeared during
1141
   * handling edit action and it should be restored.  This may cause flushing
1142
   * layout at retrieving computed value of CSS properties.
1143
   */
1144
  MOZ_MUST_USE nsresult ReapplyCachedStyles();
1145
1146
  void ClearCachedStyles();
1147
1148
  /**
1149
   * InsertBRElementToEmptyListItemsAndTableCellsInChangedRange() inserts
1150
   * <br> element into empty list item or table cell elements.
1151
   */
1152
  MOZ_MUST_USE nsresult
1153
  InsertBRElementToEmptyListItemsAndTableCellsInChangedRange();
1154
1155
  /**
1156
   * AdjustWhitespace() may replace whitespaces with NBSP or something.
1157
   * See WSRunObject::AdjustWhitespace() for the detail.
1158
   */
1159
  MOZ_MUST_USE nsresult AdjustWhitespace();
1160
1161
  /**
1162
   * PinSelectionToNewBlock() may collapse Selection around mNewNode if it's
1163
   * necessary,
1164
   */
1165
  MOZ_MUST_USE nsresult PinSelectionToNewBlock();
1166
1167
  void CheckInterlinePosition();
1168
1169
  /**
1170
   * AdjustSelection() may adjust Selection range to nearest editable content.
1171
   * Despite of the name, this may change the DOM tree.  If it needs to create
1172
   * a <br> to put caret, this tries to create a <br> element.
1173
   *
1174
   * @param aAction     Maybe used to look for a good point to put caret.
1175
   */
1176
  MOZ_MUST_USE nsresult AdjustSelection(nsIEditor::EDirection aAction);
1177
1178
  /**
1179
   * FindNearEditableNode() tries to find an editable node near aPoint.
1180
   *
1181
   * @param aPoint      The DOM point where to start to search from.
1182
   * @param aDirection  If nsIEditor::ePrevious is set, this searches an
1183
   *                    editable node from next nodes.  Otherwise, from
1184
   *                    previous nodes.
1185
   * @return            If found, returns non-nullptr.  Otherwise, nullptr.
1186
   *                    Note that if found node is in different table element,
1187
   *                    this returns nullptr.
1188
   *                    And also if aDirection is not nsIEditor::ePrevious,
1189
   *                    the result may be the node pointed by aPoint.
1190
   */
1191
  template<typename PT, typename CT>
1192
  nsIContent* FindNearEditableNode(const EditorDOMPointBase<PT, CT>& aPoint,
1193
                                   nsIEditor::EDirection aDirection);
1194
  /**
1195
   * Returns true if aNode1 or aNode2 or both is the descendant of some type of
1196
   * table element, but their nearest table element ancestors differ.  "Table
1197
   * element" here includes not just <table> but also <td>, <tbody>, <tr>, etc.
1198
   * The nodes count as being their own descendants for this purpose, so a
1199
   * table element is its own nearest table element ancestor.
1200
   */
1201
  bool InDifferentTableElements(nsINode* aNode1, nsINode* aNode2);
1202
1203
  /**
1204
   * RemoveEmptyNodesInChangedRange() removes all empty nodes in
1205
   * mDocChangeRange.  However, if mail-cite node has only a <br> element,
1206
   * the node will be removed but <br> element is moved to where the
1207
   * mail-cite node was.
1208
   * XXX This method is expensive if mDocChangeRange is too wide and may
1209
   *     remove unexpected empty element, e.g., it was created by JS, but
1210
   *     we haven't touched it.  Cannot we remove this method and make
1211
   *     guarantee that empty nodes won't be created?
1212
   */
1213
  MOZ_MUST_USE nsresult RemoveEmptyNodesInChangedRange();
1214
1215
  nsresult SelectionEndpointInNode(nsINode* aNode, bool* aResult);
1216
  nsresult UpdateDocChangeRange(nsRange* aRange);
1217
1218
  /**
1219
   * ConfirmSelectionInBody() makes sure that Selection is in editor root
1220
   * element typically <body> element (see HTMLEditor::UpdateRootElement())
1221
   * and only one Selection range.
1222
   * XXX This method is not necessary because even if selection is outside the
1223
   *     <body> element, elements outside the <body> element should be
1224
   *     editable, e.g., any element can be inserted siblings as <body> element
1225
   *     and other browsers allow to edit such elements.
1226
   */
1227
  MOZ_MUST_USE nsresult ConfirmSelectionInBody();
1228
1229
  /**
1230
   * IsEmptyInline: Return true if aNode is an empty inline container
1231
   */
1232
  bool IsEmptyInline(nsINode& aNode);
1233
1234
  bool ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& arrayOfNodes);
1235
1236
  /**
1237
   * RemoveAlignment() removes align attributes, text-align properties and
1238
   * <center> elements in aNode.
1239
   *
1240
   * @param aNode               Alignment information of the node and/or its
1241
   *                            descendants will be removed.
1242
   * @param aAlignType          New align value to be set only when it's in
1243
   *                            CSS mode and this method meets <table> or <hr>.
1244
   *                            XXX This is odd and not clear when you see
1245
   *                                caller of this method.  Do you have better
1246
   *                                idea?
1247
   * @param aDescendantsOnly    true if align information of aNode itself
1248
   *                            shouldn't be removed.  Otherwise, false.
1249
   */
1250
  MOZ_MUST_USE nsresult
1251
  RemoveAlignment(nsINode& aNode, const nsAString& aAlignType,
1252
                  bool aDescendantsOnly);
1253
1254
  /**
1255
   * MakeSureElemStartsOrEndsOnCR() inserts <br> element at start (end) of
1256
   * aNode if neither:
1257
   * - first (last) editable child of aNode is a block or a <br>,
1258
   * - previous (next) sibling of aNode is block or a <br>
1259
   * - nor no previous (next) sibling of aNode.
1260
   *
1261
   * @param aNode               The node which may be inserted <br> element.
1262
   * @param aStarts             true for trying to insert <br> to the start.
1263
   *                            false for trying to insert <br> to the end.
1264
   */
1265
  MOZ_MUST_USE nsresult
1266
  MakeSureElemStartsOrEndsOnCR(nsINode& aNode, bool aStarts);
1267
1268
  /**
1269
   * AlignBlock() resets align attribute, text-align property, etc first.
1270
   * Then, aligns contents of aElement on aAlignType.
1271
   *
1272
   * @param aElement            The element whose contents will be aligned.
1273
   * @param aAlignType          Boundary or "center" which contents should be
1274
   *                            aligned on.
1275
   * @param aResetAlignOf       Resets align of whether element and its
1276
   *                            descendants or only descendants.
1277
   */
1278
  enum class ResetAlignOf { ElementAndDescendants, OnlyDescendants };
1279
  MOZ_MUST_USE nsresult
1280
  AlignBlock(Element& aElement, const nsAString& aAlignType,
1281
             ResetAlignOf aResetAlignOf);
1282
1283
  /**
1284
   * IncreaseMarginToIndent() increases the margin of aElement.  See the
1285
   * document of ChangeMarginStart() for the detail.
1286
   * XXX This is not aware of vertical writing-mode.
1287
   *
1288
   * @param aElement            The element to be indented.
1289
   */
1290
  MOZ_MUST_USE nsresult IncreaseMarginToIndent(Element& aElement)
1291
0
  {
1292
0
    return ChangeMarginStart(aElement, true);
1293
0
  }
1294
1295
  /**
1296
   * DecreaseMarginToOutdent() decreases the margin of aElement.  See the
1297
   * document of ChangeMarginStart() for the detail.
1298
   * XXX This is not aware of vertical writing-mode.
1299
   *
1300
   * @param aElement            The element to be outdented.
1301
   */
1302
  MOZ_MUST_USE nsresult DecreaseMarginToOutdent(Element& aElement)
1303
0
  {
1304
0
    return ChangeMarginStart(aElement, false);
1305
0
  }
1306
1307
  /**
1308
   * ChangeMarginStart() changes margin of aElement to indent or outdent.
1309
   * However, use IncreaseMarginToIndent() and DecreaseMarginToOutdent()
1310
   * instead.  If it's rtl text, margin-right will be changed.  Otherwise,
1311
   * margin-left.
1312
   * XXX This is not aware of vertical writing-mode.
1313
   *
1314
   * @param aElement            The element to be indented or outdented.
1315
   * @param aIncrease           true for indent, false for outdent.
1316
   */
1317
  MOZ_MUST_USE nsresult ChangeMarginStart(Element& aElement, bool aIncrease);
1318
1319
  void DocumentModifiedWorker();
1320
1321
  /**
1322
   * InitStyleCacheArray() initializes aStyleCache for usable with
1323
   * GetInlineStyles().
1324
   */
1325
  void InitStyleCacheArray(StyleCache aStyleCache[SIZE_STYLE_TABLE]);
1326
1327
  /**
1328
   * GetInlineStyles() retrieves the style of aNode and modifies each item of
1329
   * aStyleCache.  This might cause flushing layout at retrieving computed
1330
   * values of CSS properties.
1331
   */
1332
  MOZ_MUST_USE nsresult
1333
  GetInlineStyles(nsINode* aNode, StyleCache aStyleCache[SIZE_STYLE_TABLE]);
1334
1335
protected:
1336
  HTMLEditor* mHTMLEditor;
1337
  RefPtr<nsRange> mDocChangeRange;
1338
  bool mListenerEnabled;
1339
  bool mReturnInEmptyLIKillsList;
1340
  bool mDidDeleteSelection;
1341
  bool mDidRangedDelete;
1342
  bool mRestoreContentEditableCount;
1343
  RefPtr<nsRange> mUtilRange;
1344
  // Need to remember an int across willJoin/didJoin...
1345
  uint32_t mJoinOffset;
1346
  RefPtr<Element> mNewBlock;
1347
  RefPtr<RangeItem> mRangeItem;
1348
1349
  // XXX In strict speaking, mCachedStyles isn't enough to cache inline styles
1350
  //     because inline style can be specified with "style" attribute and/or
1351
  //     CSS in <style> elements or CSS files.  So, we need to look for better
1352
  //     implementation about this.
1353
  StyleCache mCachedStyles[SIZE_STYLE_TABLE];
1354
};
1355
1356
} // namespace mozilla
1357
1358
#endif // #ifndef HTMLEditRules_h
1359