Replace OptionSet |= and -= operators with add() and remove() functions
[WebKit-https.git] / Source / WebCore / editing / CompositeEditCommand.cpp
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "CompositeEditCommand.h"
28
29 #include "AXObjectCache.h"
30 #include "AppendNodeCommand.h"
31 #include "ApplyStyleCommand.h"
32 #include "BreakBlockquoteCommand.h"
33 #include "DataTransfer.h"
34 #include "DeleteFromTextNodeCommand.h"
35 #include "DeleteSelectionCommand.h"
36 #include "Document.h"
37 #include "DocumentFragment.h"
38 #include "DocumentMarkerController.h"
39 #include "Editing.h"
40 #include "Editor.h"
41 #include "EditorInsertAction.h"
42 #include "ElementTraversal.h"
43 #include "Event.h"
44 #include "Frame.h"
45 #include "HTMLBRElement.h"
46 #include "HTMLDivElement.h"
47 #include "HTMLLIElement.h"
48 #include "HTMLNames.h"
49 #include "HTMLSpanElement.h"
50 #include "InlineTextBox.h"
51 #include "InsertIntoTextNodeCommand.h"
52 #include "InsertLineBreakCommand.h"
53 #include "InsertNodeBeforeCommand.h"
54 #include "InsertParagraphSeparatorCommand.h"
55 #include "InsertTextCommand.h"
56 #include "MergeIdenticalElementsCommand.h"
57 #include "NodeTraversal.h"
58 #include "Range.h"
59 #include "RemoveNodeCommand.h"
60 #include "RemoveNodePreservingChildrenCommand.h"
61 #include "RenderBlockFlow.h"
62 #include "RenderText.h"
63 #include "RenderedDocumentMarker.h"
64 #include "ReplaceNodeWithSpanCommand.h"
65 #include "ReplaceSelectionCommand.h"
66 #include "ScopedEventQueue.h"
67 #include "SetNodeAttributeCommand.h"
68 #include "SplitElementCommand.h"
69 #include "SplitTextNodeCommand.h"
70 #include "SplitTextNodeContainingElementCommand.h"
71 #include "StaticRange.h"
72 #include "Text.h"
73 #include "TextIterator.h"
74 #include "VisibleUnits.h"
75 #include "WrapContentsInDummySpanCommand.h"
76 #include "markup.h"
77
78 namespace WebCore {
79
80 using namespace HTMLNames;
81
82 int AccessibilityUndoReplacedText::indexForVisiblePosition(const VisiblePosition& position, RefPtr<ContainerNode>& scope) const
83 {
84     if (position.deepEquivalent().isNull())
85         return -1;
86     return WebCore::indexForVisiblePosition(position, scope);
87 }
88
89 void AccessibilityUndoReplacedText::configureRangeDeletedByReapplyWithEndingSelection(const VisibleSelection& selection)
90 {
91     if (!AXObjectCache::accessibilityEnabled())
92         return;
93     if (selection.isNone())
94         return;
95     m_rangeDeletedByReapply.endIndex.value = indexForVisiblePosition(selection.end(), m_rangeDeletedByReapply.endIndex.scope);
96 }
97
98 void AccessibilityUndoReplacedText::configureRangeDeletedByReapplyWithStartingSelection(const VisibleSelection& selection)
99 {
100     if (!AXObjectCache::accessibilityEnabled())
101         return;
102     if (selection.isNone())
103         return;
104     if (m_rangeDeletedByReapply.startIndex.value == -1)
105         m_rangeDeletedByReapply.startIndex.value = indexForVisiblePosition(selection.start(), m_rangeDeletedByReapply.startIndex.scope);
106 }
107
108 void AccessibilityUndoReplacedText::setRangeDeletedByUnapply(const VisiblePositionIndexRange& range)
109 {
110     if (m_rangeDeletedByUnapply.isNull())
111         m_rangeDeletedByUnapply = range;
112 }
113
114 void AccessibilityUndoReplacedText::captureTextForUnapply()
115 {
116     if (!AXObjectCache::accessibilityEnabled())
117         return;
118     m_replacedText = textDeletedByReapply();
119 }
120
121 void AccessibilityUndoReplacedText::captureTextForReapply()
122 {
123     if (!AXObjectCache::accessibilityEnabled())
124         return;
125     m_replacedText = textDeletedByUnapply();
126 }
127
128 static String stringForVisiblePositionIndexRange(const VisiblePositionIndexRange& range)
129 {
130     if (range.isNull())
131         return String();
132     VisiblePosition start = visiblePositionForIndex(range.startIndex.value, range.startIndex.scope.get());
133     VisiblePosition end = visiblePositionForIndex(range.endIndex.value, range.endIndex.scope.get());
134     return AccessibilityObject::stringForVisiblePositionRange(VisiblePositionRange(start, end));
135 }
136
137 String AccessibilityUndoReplacedText::textDeletedByUnapply()
138 {
139     if (!AXObjectCache::accessibilityEnabled())
140         return String();
141     return stringForVisiblePositionIndexRange(m_rangeDeletedByUnapply);
142 }
143
144 String AccessibilityUndoReplacedText::textDeletedByReapply()
145 {
146     if (!AXObjectCache::accessibilityEnabled())
147         return String();
148     return stringForVisiblePositionIndexRange(m_rangeDeletedByReapply);
149 }
150
151 static void postTextStateChangeNotification(AXObjectCache* cache, const VisiblePosition& position, const String& deletedText, const String& insertedText)
152 {
153     ASSERT(cache);
154     auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole);
155     if (!node)
156         return;
157     if (insertedText.length() && deletedText.length())
158         cache->postTextReplacementNotification(node, AXTextEditTypeDelete, insertedText, AXTextEditTypeInsert, deletedText, position);
159     else if (deletedText.length())
160         cache->postTextStateChangeNotification(node, AXTextEditTypeInsert, deletedText, position);
161     else if (insertedText.length())
162         cache->postTextStateChangeNotification(node, AXTextEditTypeDelete, insertedText, position);
163 }
164
165 void AccessibilityUndoReplacedText::postTextStateChangeNotificationForUnapply(AXObjectCache* cache)
166 {
167     if (!cache)
168         return;
169     if (!AXObjectCache::accessibilityEnabled())
170         return;
171     if (m_rangeDeletedByUnapply.isNull())
172         return;
173     VisiblePosition position = visiblePositionForIndex(m_rangeDeletedByUnapply.endIndex.value, m_rangeDeletedByUnapply.endIndex.scope.get());
174     if (position.isNull())
175         return;
176     postTextStateChangeNotification(cache, position, textDeletedByUnapply(), m_replacedText);
177     m_replacedText = String();
178 }
179
180 void AccessibilityUndoReplacedText::postTextStateChangeNotificationForReapply(AXObjectCache* cache)
181 {
182     if (!cache)
183         return;
184     if (!AXObjectCache::accessibilityEnabled())
185         return;
186     if (m_rangeDeletedByReapply.isNull())
187         return;
188     VisiblePosition position = visiblePositionForIndex(m_rangeDeletedByReapply.startIndex.value, m_rangeDeletedByReapply.startIndex.scope.get());
189     if (position.isNull())
190         return;
191     postTextStateChangeNotification(cache, position, textDeletedByReapply(), m_replacedText);
192     m_replacedText = String();
193 }
194
195 Ref<EditCommandComposition> EditCommandComposition::create(Document& document,
196     const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
197 {
198     return adoptRef(*new EditCommandComposition(document, startingSelection, endingSelection, editAction));
199 }
200
201 EditCommandComposition::EditCommandComposition(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
202     : m_document(&document)
203     , m_startingSelection(startingSelection)
204     , m_endingSelection(endingSelection)
205     , m_startingRootEditableElement(startingSelection.rootEditableElement())
206     , m_endingRootEditableElement(endingSelection.rootEditableElement())
207     , m_editAction(editAction)
208 {
209     m_replacedText.configureRangeDeletedByReapplyWithStartingSelection(startingSelection);
210 }
211
212 void EditCommandComposition::unapply()
213 {
214     ASSERT(m_document);
215     RefPtr<Frame> frame = m_document->frame();
216     if (!frame)
217         return;
218
219     m_replacedText.captureTextForUnapply();
220
221     // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
222     // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
223     // if one is necessary (like for the creation of VisiblePositions).
224     m_document->updateLayoutIgnorePendingStylesheets();
225 #if PLATFORM(IOS)
226     // FIXME: Where should iPhone code deal with the composition?
227     // Since editing commands don't save/restore the composition, undoing without fixing
228     // up the composition will leave a stale, invalid composition, as in <rdar://problem/6831637>.
229     // Desktop handles this in -[WebHTMLView _updateSelectionForInputManager], but the phone
230     // goes another route.
231     frame->editor().cancelComposition();
232 #endif
233
234     if (!frame->editor().willUnapplyEditing(*this))
235         return;
236
237     size_t size = m_commands.size();
238     for (size_t i = size; i; --i)
239         m_commands[i - 1]->doUnapply();
240
241     frame->editor().unappliedEditing(*this);
242
243     if (AXObjectCache::accessibilityEnabled())
244         m_replacedText.postTextStateChangeNotificationForUnapply(m_document->existingAXObjectCache());
245 }
246
247 void EditCommandComposition::reapply()
248 {
249     ASSERT(m_document);
250     RefPtr<Frame> frame = m_document->frame();
251     if (!frame)
252         return;
253
254     m_replacedText.captureTextForReapply();
255
256     // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
257     // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
258     // if one is necessary (like for the creation of VisiblePositions).
259     m_document->updateLayoutIgnorePendingStylesheets();
260
261     if (!frame->editor().willReapplyEditing(*this))
262         return;
263
264     for (auto& command : m_commands)
265         command->doReapply();
266
267     frame->editor().reappliedEditing(*this);
268
269     if (AXObjectCache::accessibilityEnabled())
270         m_replacedText.postTextStateChangeNotificationForReapply(m_document->existingAXObjectCache());
271 }
272
273 void EditCommandComposition::append(SimpleEditCommand* command)
274 {
275     m_commands.append(command);
276 }
277
278 void EditCommandComposition::setStartingSelection(const VisibleSelection& selection)
279 {
280     m_startingSelection = selection;
281     m_startingRootEditableElement = selection.rootEditableElement();
282     m_replacedText.configureRangeDeletedByReapplyWithStartingSelection(selection);
283 }
284
285 void EditCommandComposition::setEndingSelection(const VisibleSelection& selection)
286 {
287     m_endingSelection = selection;
288     m_endingRootEditableElement = selection.rootEditableElement();
289     m_replacedText.configureRangeDeletedByReapplyWithEndingSelection(selection);
290 }
291
292 void EditCommandComposition::setRangeDeletedByUnapply(const VisiblePositionIndexRange& range)
293 {
294     m_replacedText.setRangeDeletedByUnapply(range);
295 }
296
297 #ifndef NDEBUG
298 void EditCommandComposition::getNodesInCommand(HashSet<Node*>& nodes)
299 {
300     for (auto& command : m_commands)
301         command->getNodesInCommand(nodes);
302 }
303 #endif
304
305 CompositeEditCommand::CompositeEditCommand(Document& document, EditAction editingAction)
306     : EditCommand(document, editingAction)
307 {
308 }
309
310 CompositeEditCommand::~CompositeEditCommand()
311 {
312     ASSERT(isTopLevelCommand() || !m_composition);
313 }
314
315 bool CompositeEditCommand::willApplyCommand()
316 {
317     return frame().editor().willApplyEditing(*this, targetRangesForBindings());
318 }
319
320 void CompositeEditCommand::apply()
321 {
322     if (!endingSelection().isContentRichlyEditable()) {
323         switch (editingAction()) {
324         case EditActionTypingDeleteSelection:
325         case EditActionTypingDeleteBackward:
326         case EditActionTypingDeleteForward:
327         case EditActionTypingDeleteWordBackward:
328         case EditActionTypingDeleteWordForward:
329         case EditActionTypingDeleteLineBackward:
330         case EditActionTypingDeleteLineForward:
331         case EditActionTypingDeletePendingComposition:
332         case EditActionTypingDeleteFinalComposition:
333         case EditActionTypingInsertText:
334         case EditActionTypingInsertLineBreak:
335         case EditActionTypingInsertParagraph:
336         case EditActionTypingInsertPendingComposition:
337         case EditActionTypingInsertFinalComposition:
338         case EditActionPaste:
339         case EditActionDeleteByDrag:
340         case EditActionSetWritingDirection:
341         case EditActionCut:
342         case EditActionUnspecified:
343         case EditActionInsert:
344         case EditActionInsertReplacement:
345         case EditActionInsertFromDrop:
346         case EditActionDelete:
347         case EditActionDictation:
348             break;
349         default:
350             ASSERT_NOT_REACHED();
351             return;
352         }
353     }
354     ensureComposition();
355
356     // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
357     // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
358     // if one is necessary (like for the creation of VisiblePositions).
359     document().updateLayoutIgnorePendingStylesheets();
360
361     if (!willApplyCommand())
362         return;
363
364     {
365         EventQueueScope eventQueueScope;
366         doApply();
367     }
368
369     didApplyCommand();
370     setShouldRetainAutocorrectionIndicator(false);
371 }
372
373 void CompositeEditCommand::didApplyCommand()
374 {
375     frame().editor().appliedEditing(*this);
376 }
377
378 Vector<RefPtr<StaticRange>> CompositeEditCommand::targetRanges() const
379 {
380     ASSERT(!isEditingTextAreaOrTextInput());
381     auto firstRange = frame().selection().selection().firstRange();
382     if (!firstRange)
383         return { };
384
385     RefPtr<StaticRange> range = StaticRange::createFromRange(*firstRange);
386     return { 1, range };
387 }
388
389 Vector<RefPtr<StaticRange>> CompositeEditCommand::targetRangesForBindings() const
390 {
391     if (isEditingTextAreaOrTextInput())
392         return { };
393
394     return targetRanges();
395 }
396
397 RefPtr<DataTransfer> CompositeEditCommand::inputEventDataTransfer() const
398 {
399     return nullptr;
400 }
401
402 EditCommandComposition* CompositeEditCommand::composition() const
403 {
404     for (auto* command = this; command; command = command->parent()) {
405         if (auto composition = command->m_composition) {
406             ASSERT(!command->parent());
407             return composition.get();
408         }
409     }
410     return nullptr;
411 }
412
413 EditCommandComposition& CompositeEditCommand::ensureComposition()
414 {
415     auto* command = this;
416     while (auto* parent = command->parent())
417         command = parent;
418     if (!command->m_composition)
419         command->m_composition = EditCommandComposition::create(document(), startingSelection(), endingSelection(), editingAction());
420     return *command->m_composition;
421 }
422
423 bool CompositeEditCommand::isCreateLinkCommand() const
424 {
425     return false;
426 }
427
428 bool CompositeEditCommand::preservesTypingStyle() const
429 {
430     return false;
431 }
432
433 bool CompositeEditCommand::isTypingCommand() const
434 {
435     return false;
436 }
437
438 bool CompositeEditCommand::shouldRetainAutocorrectionIndicator() const
439 {
440     return false;
441 }
442
443 void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool)
444 {
445 }
446
447 String CompositeEditCommand::inputEventTypeName() const
448 {
449     return inputTypeNameForEditingAction(editingAction());
450 }
451
452 //
453 // sugary-sweet convenience functions to help create and apply edit commands in composite commands
454 //
455 void CompositeEditCommand::applyCommandToComposite(Ref<EditCommand>&& command)
456 {
457     command->setParent(this);
458     command->doApply();
459     if (command->isSimpleEditCommand()) {
460         command->setParent(nullptr);
461         ensureComposition().append(toSimpleEditCommand(command.ptr()));
462     }
463     m_commands.append(WTFMove(command));
464 }
465
466 void CompositeEditCommand::applyCommandToComposite(Ref<CompositeEditCommand>&& command, const VisibleSelection& selection)
467 {
468     command->setParent(this);
469     if (selection != command->endingSelection()) {
470         command->setStartingSelection(selection);
471         command->setEndingSelection(selection);
472     }
473     command->doApply();
474     m_commands.append(WTFMove(command));
475 }
476
477 void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction editingAction)
478 {
479     applyCommandToComposite(ApplyStyleCommand::create(document(), style, editingAction));
480 }
481
482 void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position& start, const Position& end, EditAction editingAction)
483 {
484     applyCommandToComposite(ApplyStyleCommand::create(document(), style, start, end, editingAction));
485 }
486
487 void CompositeEditCommand::applyStyledElement(Ref<Element>&& element)
488 {
489     applyCommandToComposite(ApplyStyleCommand::create(WTFMove(element), false));
490 }
491
492 void CompositeEditCommand::removeStyledElement(Ref<Element>&& element)
493 {
494     applyCommandToComposite(ApplyStyleCommand::create(WTFMove(element), true));
495 }
496
497 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea)
498 {
499     applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea, editingAction()));
500 }
501
502 void CompositeEditCommand::insertLineBreak()
503 {
504     applyCommandToComposite(InsertLineBreakCommand::create(document()));
505 }
506
507 bool CompositeEditCommand::isRemovableBlock(const Node* node)
508 {
509     ASSERT(node);
510     if (!is<HTMLDivElement>(*node))
511         return false;
512
513     Node* parentNode = node->parentNode();
514     if (parentNode && parentNode->firstChild() != parentNode->lastChild())
515         return false;
516
517     if (!downcast<HTMLDivElement>(*node).hasAttributes())
518         return true;
519
520     return false;
521 }
522
523 void CompositeEditCommand::insertNodeBefore(Ref<Node>&& insertChild, Node& refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
524 {
525     applyCommandToComposite(InsertNodeBeforeCommand::create(WTFMove(insertChild), refChild, shouldAssumeContentIsAlwaysEditable, editingAction()));
526 }
527
528 void CompositeEditCommand::insertNodeAfter(Ref<Node>&& insertChild, Node& refChild)
529 {
530     ContainerNode* parent = refChild.parentNode();
531     if (!parent)
532         return;
533
534     ASSERT(!parent->isShadowRoot());
535     if (parent->lastChild() == &refChild)
536         appendNode(WTFMove(insertChild), *parent);
537     else {
538         ASSERT(refChild.nextSibling());
539         insertNodeBefore(WTFMove(insertChild), *refChild.nextSibling());
540     }
541 }
542
543 void CompositeEditCommand::insertNodeAt(Ref<Node>&& insertChild, const Position& editingPosition)
544 {
545     ASSERT(isEditablePosition(editingPosition));
546     // For editing positions like [table, 0], insert before the table,
547     // likewise for replaced elements, brs, etc.
548     Position p = editingPosition.parentAnchoredEquivalent();
549     Node* refChild = p.deprecatedNode();
550     int offset = p.deprecatedEditingOffset();
551     
552     if (canHaveChildrenForEditing(*refChild)) {
553         Node* child = refChild->firstChild();
554         for (int i = 0; child && i < offset; i++)
555             child = child->nextSibling();
556         if (child)
557             insertNodeBefore(WTFMove(insertChild), *child);
558         else
559             appendNode(WTFMove(insertChild), downcast<ContainerNode>(*refChild));
560     } else if (caretMinOffset(*refChild) >= offset)
561         insertNodeBefore(WTFMove(insertChild), *refChild);
562     else if (is<Text>(*refChild) && caretMaxOffset(*refChild) > offset) {
563         splitTextNode(downcast<Text>(*refChild), offset);
564
565         // Mutation events (bug 22634) from the text node insertion may have removed the refChild
566         if (!refChild->isConnected())
567             return;
568         insertNodeBefore(WTFMove(insertChild), *refChild);
569     } else
570         insertNodeAfter(WTFMove(insertChild), *refChild);
571 }
572
573 void CompositeEditCommand::appendNode(Ref<Node>&& node, Ref<ContainerNode>&& parent)
574 {
575     ASSERT(canHaveChildrenForEditing(parent));
576     applyCommandToComposite(AppendNodeCommand::create(WTFMove(parent), WTFMove(node), editingAction()));
577 }
578
579 void CompositeEditCommand::removeChildrenInRange(Node& node, unsigned from, unsigned to)
580 {
581     Vector<Ref<Node>> children;
582     Node* child = node.traverseToChildAt(from);
583     for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
584         children.append(*child);
585
586     for (auto& child : children)
587         removeNode(child);
588 }
589
590 void CompositeEditCommand::removeNode(Node& node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
591 {
592     if (!node.nonShadowBoundaryParentNode())
593         return;
594     applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentIsAlwaysEditable, editingAction()));
595 }
596
597 void CompositeEditCommand::removeNodePreservingChildren(Node& node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
598 {
599     applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, shouldAssumeContentIsAlwaysEditable, editingAction()));
600 }
601
602 void CompositeEditCommand::removeNodeAndPruneAncestors(Node& node)
603 {
604     RefPtr<ContainerNode> parent = node.parentNode();
605     removeNode(node);
606     prune(parent.get());
607 }
608
609 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, Element& newParent)
610 {
611     NodeVector nodesToRemove;
612     Ref<Element> protectedNewParent = newParent;
613
614     for (; node && node != pastLastNodeToMove; node = node->nextSibling())
615         nodesToRemove.append(*node);
616
617     for (auto& nodeToRemove : nodesToRemove) {
618         removeNode(nodeToRemove);
619         appendNode(WTFMove(nodeToRemove), newParent);
620     }
621 }
622
623 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Position& position, Node& node)
624 {
625     int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ? position.offsetInContainerNode() : 0;
626     updatePositionForNodeRemoval(position, node);
627     if (offset)
628         position.moveToOffset(offset);    
629 }
630
631 HTMLElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes(HTMLElement& element)
632 {
633     // It would also be possible to implement all of ReplaceNodeWithSpanCommand
634     // as a series of existing smaller edit commands.  Someone who wanted to
635     // reduce the number of edit commands could do so here.
636     auto command = ReplaceNodeWithSpanCommand::create(element);
637     auto* commandPtr = command.ptr();
638     applyCommandToComposite(WTFMove(command));
639     // Returning a raw pointer here is OK because the command is retained by
640     // applyCommandToComposite (thus retaining the span), and the span is also
641     // in the DOM tree, and thus alive whie it has a parent.
642     ASSERT(commandPtr->spanElement()->isConnected());
643     return commandPtr->spanElement();
644 }
645
646 void CompositeEditCommand::prune(Node* node)
647 {
648     if (auto* highestNodeToRemove = highestNodeToRemoveInPruning(node))
649         removeNode(*highestNodeToRemove);
650 }
651
652 void CompositeEditCommand::splitTextNode(Text& node, unsigned offset)
653 {
654     applyCommandToComposite(SplitTextNodeCommand::create(node, offset));
655 }
656
657 void CompositeEditCommand::splitElement(Element& element, Node& atChild)
658 {
659     applyCommandToComposite(SplitElementCommand::create(element, atChild));
660 }
661
662 void CompositeEditCommand::mergeIdenticalElements(Element& first, Element& second)
663 {
664     Ref<Element> protectedFirst = first;
665     Ref<Element> protectedSecond = second;
666     ASSERT(!first.isDescendantOf(&second) && &second != &first);
667     if (first.nextSibling() != &second) {
668         removeNode(second);
669         insertNodeAfter(second, first);
670     }
671     applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
672 }
673
674 void CompositeEditCommand::wrapContentsInDummySpan(Element& element)
675 {
676     applyCommandToComposite(WrapContentsInDummySpanCommand::create(element));
677 }
678
679 void CompositeEditCommand::splitTextNodeContainingElement(Text& text, unsigned offset)
680 {
681     applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text, offset));
682 }
683
684 void CompositeEditCommand::inputText(const String& text, bool selectInsertedText)
685 {
686     unsigned offset = 0;
687     unsigned length = text.length();
688     
689     RefPtr<ContainerNode> scope;
690     unsigned startIndex = indexForVisiblePosition(endingSelection().visibleStart(), scope);
691     
692     size_t newline;
693     do {
694         newline = text.find('\n', offset);
695         if (newline != offset) {
696             int substringLength = newline == notFound ? length - offset : newline - offset;
697             applyCommandToComposite(InsertTextCommand::create(document(), text.substring(offset, substringLength), false));
698         }
699         if (newline != notFound) {
700             VisiblePosition caret(endingSelection().visibleStart());
701             if (enclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote)) {
702                 // FIXME: Breaking a blockquote when the caret is just after a space will collapse the 
703                 // space. Modify startIndex or length to compensate for this so that the ending selection 
704                 // will be positioned correctly.
705                 // <rdar://problem/9914462> breaking a Mail blockquote just after a space collapses the space
706                 if (caret.previous().characterAfter() == ' ') {
707                     if (!offset && !startIndex)
708                         startIndex--;
709                     else if (!length)
710                         length--;
711                 }
712                 applyCommandToComposite(BreakBlockquoteCommand::create(document()));
713             } else
714                 insertLineBreak();
715         }
716             
717         offset = newline + 1;
718     } while (newline != notFound && offset != length);
719     
720     if (selectInsertedText)
721         setEndingSelection(VisibleSelection(visiblePositionForIndex(startIndex, scope.get()), visiblePositionForIndex(startIndex + length, scope.get())));
722 }
723
724 void CompositeEditCommand::insertTextIntoNode(Text& node, unsigned offset, const String& text)
725 {
726     if (!text.isEmpty())
727         applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, text, editingAction()));
728 }
729
730 void CompositeEditCommand::deleteTextFromNode(Text& node, unsigned offset, unsigned count)
731 {
732     applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count, editingAction()));
733 }
734
735 void CompositeEditCommand::replaceTextInNode(Text& node, unsigned offset, unsigned count, const String& replacementText)
736 {
737     applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
738     if (!replacementText.isEmpty())
739         applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText, editingAction()));
740 }
741
742 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text)
743 {
744     Position start = endingSelection().start();
745     Position end = endingSelection().end();
746     if (start.containerNode() != end.containerNode() || !start.containerNode()->isTextNode() || isTabSpanTextNode(start.containerNode()))
747         return Position();
748
749     RefPtr<Text> textNode = start.containerText();
750     replaceTextInNode(*textNode, start.offsetInContainerNode(), end.offsetInContainerNode() - start.offsetInContainerNode(), text);
751
752     return Position(textNode.get(), start.offsetInContainerNode() + text.length());
753 }
754
755 static Vector<RenderedDocumentMarker> copyMarkers(const Vector<RenderedDocumentMarker*>& markerPointers)
756 {
757     Vector<RenderedDocumentMarker> markers;
758     markers.reserveInitialCapacity(markerPointers.size());
759     for (auto& markerPointer : markerPointers)
760         markers.uncheckedAppend(*markerPointer);
761
762     return markers;
763 }
764
765 void CompositeEditCommand::replaceTextInNodePreservingMarkers(Text& node, unsigned offset, unsigned count, const String& replacementText)
766 {
767     Ref<Text> protectedNode(node);
768     DocumentMarkerController& markerController = document().markers();
769     auto markers = copyMarkers(markerController.markersInRange(Range::create(document(), &node, offset, &node, offset + count), DocumentMarker::allMarkers()));
770     replaceTextInNode(node, offset, count, replacementText);
771     RefPtr<Range> newRange = Range::create(document(), &node, offset, &node, offset + replacementText.length());
772     for (const auto& marker : markers) {
773 #if PLATFORM(IOS)
774         if (marker.isDictation()) {
775             markerController.addMarker(newRange.get(), marker.type(), marker.description(), marker.alternatives(), marker.metadata());
776             continue;
777         }
778 #endif
779         markerController.addMarker(newRange.get(), marker.type(), marker.description());
780     }
781 }
782
783 Position CompositeEditCommand::positionOutsideTabSpan(const Position& position)
784 {
785     if (!isTabSpanTextNode(position.anchorNode()))
786         return position;
787
788     switch (position.anchorType()) {
789     case Position::PositionIsBeforeChildren:
790     case Position::PositionIsAfterChildren:
791         ASSERT_NOT_REACHED();
792         return position;
793     case Position::PositionIsOffsetInAnchor:
794         break;
795     case Position::PositionIsBeforeAnchor:
796         return positionInParentBeforeNode(position.anchorNode());
797     case Position::PositionIsAfterAnchor:
798         return positionInParentAfterNode(position.anchorNode());
799     }
800
801     auto* tabSpan = tabSpanNode(position.containerNode());
802
803     if (position.offsetInContainerNode() <= caretMinOffset(*position.containerNode()))
804         return positionInParentBeforeNode(tabSpan);
805
806     if (position.offsetInContainerNode() >= caretMaxOffset(*position.containerNode()))
807         return positionInParentAfterNode(tabSpan);
808
809     splitTextNodeContainingElement(downcast<Text>(*position.containerNode()), position.offsetInContainerNode());
810     return positionInParentBeforeNode(tabSpan);
811 }
812
813 void CompositeEditCommand::insertNodeAtTabSpanPosition(Ref<Node>&& node, const Position& pos)
814 {
815     // insert node before, after, or at split of tab span
816     insertNodeAt(WTFMove(node), positionOutsideTabSpan(pos));
817 }
818
819 static EditAction deleteSelectionEditingActionForEditingAction(EditAction editingAction)
820 {
821     switch (editingAction) {
822     case EditActionCut:
823         return EditActionCut;
824     default:
825         return EditActionDelete;
826     }
827 }
828
829 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
830 {
831     if (endingSelection().isRange())
832         applyCommandToComposite(DeleteSelectionCommand::create(document(), smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup, deleteSelectionEditingActionForEditingAction(editingAction())));
833 }
834
835 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
836 {
837     if (selection.isRange())
838         applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
839 }
840
841 void CompositeEditCommand::removeNodeAttribute(Element& element, const QualifiedName& attribute)
842 {
843     setNodeAttribute(element, attribute, nullAtom());
844 }
845
846 void CompositeEditCommand::setNodeAttribute(Element& element, const QualifiedName& attribute, const AtomicString& value)
847 {
848     applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute, value));
849 }
850
851 static inline bool containsOnlyDeprecatedEditingWhitespace(const String& text)
852 {
853     for (unsigned i = 0; i < text.length(); ++i) {
854         if (!deprecatedIsEditingWhitespace(text[i]))
855             return false;
856     }
857     return true;
858 }
859
860 bool CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor(const String& text) const
861 {
862     return containsOnlyDeprecatedEditingWhitespace(text);
863 }
864
865 bool CompositeEditCommand::canRebalance(const Position& position) const
866 {
867     Node* node = position.containerNode();
868     if (position.anchorType() != Position::PositionIsOffsetInAnchor || !is<Text>(node))
869         return false;
870
871     Text& textNode = downcast<Text>(*node);
872     if (!textNode.length())
873         return false;
874
875     node->document().updateStyleIfNeeded();
876
877     RenderObject* renderer = textNode.renderer();
878     if (renderer && !renderer->style().collapseWhiteSpace())
879         return false;
880
881     return true;
882 }
883
884 // FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
885 void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
886 {
887     Node* node = position.containerNode();
888     if (!canRebalance(position))
889         return;
890
891     // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
892     int offset = position.deprecatedEditingOffset();
893     String text = downcast<Text>(*node).data();
894     if (!deprecatedIsEditingWhitespace(text[offset])) {
895         offset--;
896         if (offset < 0 || !deprecatedIsEditingWhitespace(text[offset]))
897             return;
898     }
899
900     rebalanceWhitespaceOnTextSubstring(downcast<Text>(*node), position.offsetInContainerNode(), position.offsetInContainerNode());
901 }
902
903 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(Text& textNode, int startOffset, int endOffset)
904 {
905     String text = textNode.data();
906     ASSERT(!text.isEmpty());
907
908     // Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
909     int upstream = startOffset;
910     while (upstream > 0 && deprecatedIsEditingWhitespace(text[upstream - 1]))
911         upstream--;
912     
913     int downstream = endOffset;
914     while ((unsigned)downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
915         downstream++;
916     
917     int length = downstream - upstream;
918     if (!length)
919         return;
920
921     VisiblePosition visibleUpstreamPos(Position(&textNode, upstream));
922     VisiblePosition visibleDownstreamPos(Position(&textNode, downstream));
923     
924     String string = text.substring(upstream, length);
925     String rebalancedString = stringWithRebalancedWhitespace(string,
926     // FIXME: Because of the problem mentioned at the top of this function, we must also use nbsps at the start/end of the string because
927     // this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
928                                                              isStartOfParagraph(visibleUpstreamPos) || upstream == 0, 
929                                                              isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
930     
931     if (string != rebalancedString)
932         replaceTextInNodePreservingMarkers(textNode, upstream, length, rebalancedString);
933 }
934
935 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& position)
936 {
937     Node* node = position.deprecatedNode();
938     if (!is<Text>(node))
939         return;
940     Text& textNode = downcast<Text>(*node);
941     
942     if (!textNode.length())
943         return;
944     RenderObject* renderer = textNode.renderer();
945     if (renderer && !renderer->style().collapseWhiteSpace())
946         return;
947
948     // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
949     Position upstreamPos = position.upstream();
950     deleteInsignificantText(position.upstream(), position.downstream());
951     position = upstreamPos.downstream();
952
953     VisiblePosition visiblePos(position);
954     VisiblePosition previousVisiblePos(visiblePos.previous());
955     Position previous(previousVisiblePos.deepEquivalent());
956     
957     if (deprecatedIsCollapsibleWhitespace(previousVisiblePos.characterAfter()) && is<Text>(*previous.deprecatedNode()) && !is<HTMLBRElement>(*previous.deprecatedNode()))
958         replaceTextInNodePreservingMarkers(downcast<Text>(*previous.deprecatedNode()), previous.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
959     if (deprecatedIsCollapsibleWhitespace(visiblePos.characterAfter()) && is<Text>(*position.deprecatedNode()) && !is<HTMLBRElement>(*position.deprecatedNode()))
960         replaceTextInNodePreservingMarkers(downcast<Text>(*position.deprecatedNode()), position.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
961 }
962
963 void CompositeEditCommand::rebalanceWhitespace()
964 {
965     VisibleSelection selection = endingSelection();
966     if (selection.isNone())
967         return;
968         
969     rebalanceWhitespaceAt(selection.start());
970     if (selection.isRange())
971         rebalanceWhitespaceAt(selection.end());
972 }
973
974 void CompositeEditCommand::deleteInsignificantText(Text& textNode, unsigned start, unsigned end)
975 {
976     if (start >= end)
977         return;
978
979     document().updateLayout();
980
981     RenderText* textRenderer = textNode.renderer();
982     if (!textRenderer)
983         return;
984
985     Vector<InlineTextBox*> sortedTextBoxes;
986     size_t sortedTextBoxesPosition = 0;
987    
988     for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox())
989         sortedTextBoxes.append(textBox);
990     
991     // If there is mixed directionality text, the boxes can be out of order,
992     // (like Arabic with embedded LTR), so sort them first. 
993     if (textRenderer->containsReversedText())    
994         std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart);
995     InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedTextBoxesPosition];
996
997     if (!box) {
998         // whole text node is empty
999         removeNode(textNode);
1000         return;    
1001     }
1002     
1003     unsigned length = textNode.length();
1004     if (start >= length || end > length)
1005         return;
1006
1007     unsigned removed = 0;
1008     InlineTextBox* prevBox = nullptr;
1009     String str;
1010
1011     // This loop structure works to process all gaps preceding a box,
1012     // and also will look at the gap after the last box.
1013     while (prevBox || box) {
1014         unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0;
1015         if (end < gapStart)
1016             // No more chance for any intersections
1017             break;
1018
1019         unsigned gapEnd = box ? box->start() : length;
1020         bool indicesIntersect = start <= gapEnd && end >= gapStart;
1021         int gapLen = gapEnd - gapStart;
1022         if (indicesIntersect && gapLen > 0) {
1023             gapStart = std::max(gapStart, start);
1024             gapEnd = std::min(gapEnd, end);
1025             if (str.isNull())
1026                 str = textNode.data().substring(start, end - start);
1027             // remove text in the gap
1028             str.remove(gapStart - start - removed, gapLen);
1029             removed += gapLen;
1030         }
1031         
1032         prevBox = box;
1033         if (box) {
1034             if (++sortedTextBoxesPosition < sortedTextBoxes.size())
1035                 box = sortedTextBoxes[sortedTextBoxesPosition];
1036             else
1037                 box = nullptr;
1038         }
1039     }
1040
1041     if (!str.isNull()) {
1042         // Replace the text between start and end with our pruned version.
1043         if (!str.isEmpty())
1044             replaceTextInNode(textNode, start, end - start, str);
1045         else {
1046             // Assert that we are not going to delete all of the text in the node.
1047             // If we were, that should have been done above with the call to 
1048             // removeNode and return.
1049             ASSERT(start > 0 || end - start < textNode.length());
1050             deleteTextFromNode(textNode, start, end - start);
1051         }
1052     }
1053 }
1054
1055 void CompositeEditCommand::deleteInsignificantText(const Position& start, const Position& end)
1056 {
1057     if (start.isNull() || end.isNull())
1058         return;
1059
1060     if (comparePositions(start, end) >= 0)
1061         return;
1062
1063     Vector<Ref<Text>> nodes;
1064     for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(*node)) {
1065         if (is<Text>(*node))
1066             nodes.append(downcast<Text>(*node));
1067         if (node == end.deprecatedNode())
1068             break;
1069     }
1070
1071     for (auto& textNode : nodes) {
1072         int startOffset = textNode.ptr() == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0;
1073         int endOffset = textNode.ptr() == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length());
1074         deleteInsignificantText(textNode, startOffset, endOffset);
1075     }
1076 }
1077
1078 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos)
1079 {
1080     Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivalent().downstream();
1081     deleteInsignificantText(pos, end);
1082 }
1083
1084 Ref<Element> CompositeEditCommand::appendBlockPlaceholder(Ref<Element>&& container)
1085 {
1086     document().updateLayoutIgnorePendingStylesheets();
1087     
1088     // Should assert isBlockFlow || isInlineFlow when deletion improves. See 4244964.
1089     ASSERT(container->renderer());
1090
1091     auto placeholder = createBlockPlaceholderElement(document());
1092     appendNode(placeholder.copyRef(), WTFMove(container));
1093     return placeholder;
1094 }
1095
1096 RefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& pos)
1097 {
1098     if (pos.isNull())
1099         return nullptr;
1100
1101     // Should assert isBlockFlow || isInlineFlow when deletion improves.  See 4244964.
1102     ASSERT(pos.deprecatedNode()->renderer());
1103
1104     auto placeholder = createBlockPlaceholderElement(document());
1105     insertNodeAt(placeholder.copyRef(), pos);
1106     return WTFMove(placeholder);
1107 }
1108
1109 RefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
1110 {
1111     if (!container)
1112         return nullptr;
1113
1114     document().updateLayoutIgnorePendingStylesheets();
1115
1116     auto* renderer = container->renderer();
1117     if (!is<RenderBlockFlow>(renderer))
1118         return nullptr;
1119     
1120     // Append the placeholder to make sure it follows any unrendered blocks.
1121     auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
1122     if (!blockFlow.height() || (blockFlow.isListItem() && !blockFlow.firstChild()))
1123         return appendBlockPlaceholder(*container);
1124
1125     return nullptr;
1126 }
1127
1128 // Assumes that the position is at a placeholder and does the removal without much checking.
1129 void CompositeEditCommand::removePlaceholderAt(const Position& p)
1130 {
1131     ASSERT(lineBreakExistsAtPosition(p));
1132     
1133     // We are certain that the position is at a line break, but it may be a br or a preserved newline.
1134     if (is<HTMLBRElement>(*p.anchorNode())) {
1135         removeNode(*p.anchorNode());
1136         return;
1137     }
1138     
1139     deleteTextFromNode(downcast<Text>(*p.anchorNode()), p.offsetInContainerNode(), 1);
1140 }
1141
1142 Ref<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
1143 {
1144     auto paragraphElement = createDefaultParagraphElement(document());
1145     paragraphElement->appendChild(HTMLBRElement::create(document()));
1146     insertNodeAt(paragraphElement.copyRef(), position);
1147     return paragraphElement;
1148 }
1149
1150 // If the paragraph is not entirely within it's own block, create one and move the paragraph into 
1151 // it, and return that block.  Otherwise return 0.
1152 RefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Position& pos)
1153 {
1154     if (pos.isNull())
1155         return nullptr;
1156     
1157     document().updateLayoutIgnorePendingStylesheets();
1158     
1159     // It's strange that this function is responsible for verifying that pos has not been invalidated
1160     // by an earlier call to this function.  The caller, applyBlockStyle, should do this.
1161     VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
1162     VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos));
1163     VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos);
1164     VisiblePosition next = visibleParagraphEnd.next();
1165     VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd;
1166     
1167     Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream();
1168     Position upstreamEnd = visibleEnd.deepEquivalent().upstream();
1169
1170     // If there are no VisiblePositions in the same block as pos then 
1171     // upstreamStart will be outside the paragraph
1172     if (comparePositions(pos, upstreamStart) < 0)
1173         return nullptr;
1174
1175     // Perform some checks to see if we need to perform work in this function.
1176     if (isBlock(upstreamStart.deprecatedNode())) {
1177         // If the block is the root editable element, always move content to a new block,
1178         // since it is illegal to modify attributes on the root editable element for editing.
1179         if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamStart)) {
1180             // If the block is the root editable element and it contains no visible content, create a new
1181             // block but don't try and move content into it, since there's nothing for moveParagraphs to move.
1182             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(downcast<RenderElement>(*upstreamStart.deprecatedNode()->renderer())))
1183                 return insertNewDefaultParagraphElementAt(upstreamStart);
1184         } else if (isBlock(upstreamEnd.deprecatedNode())) {
1185             if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.deprecatedNode())) {
1186                 // If the paragraph end is a descendant of paragraph start, then we need to run
1187                 // the rest of this function. If not, we can bail here.
1188                 return nullptr;
1189             }
1190         } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart.deprecatedNode()) {
1191             // The visibleEnd. If it is an ancestor of the paragraph start, then
1192             // we can bail as we have a full block to work with.
1193             if (upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock(upstreamEnd.deprecatedNode())))
1194                 return nullptr;
1195         } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
1196             // At the end of the editable region. We can bail here as well.
1197             return nullptr;
1198         }
1199     }
1200
1201     // If upstreamStart is not editable, then we can bail here.
1202     if (!isEditablePosition(upstreamStart))
1203         return nullptr;
1204     auto newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
1205
1206     bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTagName(brTag);
1207
1208     moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(firstPositionInNode(newBlock.ptr())));
1209
1210     if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !endWasBr)
1211         removeNode(*newBlock->lastChild());
1212
1213     return WTFMove(newBlock);
1214 }
1215
1216 void CompositeEditCommand::pushAnchorElementDown(Element& anchorElement)
1217 {
1218     ASSERT(anchorElement.isLink());
1219     
1220     setEndingSelection(VisibleSelection::selectionFromContentsOfNode(&anchorElement));
1221     applyStyledElement(anchorElement);
1222     // Clones of anchorElement have been pushed down, now remove it.
1223     if (anchorElement.isConnected())
1224         removeNodePreservingChildren(anchorElement);
1225 }
1226
1227 // Clone the paragraph between start and end under blockElement,
1228 // preserving the hierarchy up to outerNode. 
1229
1230 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start, const Position& end, Node* passedOuterNode, Element* blockElement)
1231 {
1232     ASSERT(comparePositions(start, end) <= 0);
1233
1234     // First we clone the outerNode
1235     RefPtr<Node> lastNode;
1236     RefPtr<Node> outerNode = passedOuterNode;
1237
1238     if (outerNode->isRootEditableElement()) {
1239         lastNode = blockElement;
1240     } else {
1241         lastNode = outerNode->cloneNode(isRenderedTable(outerNode.get()));
1242         appendNode(*lastNode, *blockElement);
1243     }
1244
1245     if (start.deprecatedNode() != outerNode && lastNode->isElementNode() && start.anchorNode()->isDescendantOf(outerNode.get())) {
1246         Vector<RefPtr<Node>> ancestors;
1247         
1248         // Insert each node from innerNode to outerNode (excluded) in a list.
1249         for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->parentNode())
1250             ancestors.append(n);
1251
1252         // Clone every node between start.deprecatedNode() and outerBlock.
1253
1254         for (size_t i = ancestors.size(); i != 0; --i) {
1255             Node* item = ancestors[i - 1].get();
1256             auto child = item->cloneNode(isRenderedTable(item));
1257             appendNode(child.copyRef(), downcast<Element>(*lastNode));
1258             lastNode = WTFMove(child);
1259         }
1260     }
1261
1262     // Handle the case of paragraphs with more than one node,
1263     // cloning all the siblings until end.deprecatedNode() is reached.
1264     
1265     if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) {
1266         // If end is not a descendant of outerNode we need to
1267         // find the first common ancestor to increase the scope
1268         // of our nextSibling traversal.
1269         while (!end.deprecatedNode()->isDescendantOf(outerNode.get())) {
1270             outerNode = outerNode->parentNode();
1271         }
1272
1273         RefPtr<Node> startNode = start.deprecatedNode();
1274         for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outerNode.get())) {
1275             // Move lastNode up in the tree as much as node was moved up in the
1276             // tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
1277             // node and the original start node is maintained in the clone.
1278             while (startNode->parentNode() != node->parentNode()) {
1279                 startNode = startNode->parentNode();
1280                 lastNode = lastNode->parentNode();
1281             }
1282
1283             auto clonedNode = node->cloneNode(true);
1284             insertNodeAfter(clonedNode.copyRef(), *lastNode);
1285             lastNode = WTFMove(clonedNode);
1286             if (node == end.deprecatedNode() || end.deprecatedNode()->isDescendantOf(*node))
1287                 break;
1288         }
1289     }
1290 }
1291
1292     
1293 // There are bugs in deletion when it removes a fully selected table/list.
1294 // It expands and removes the entire table/list, but will let content
1295 // before and after the table/list collapse onto one line.   
1296 // Deleting a paragraph will leave a placeholder. Remove it (and prune
1297 // empty or unrendered parents).
1298
1299 void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination)
1300 {
1301     VisiblePosition caretAfterDelete = endingSelection().visibleStart();
1302     if (!caretAfterDelete.equals(destination) && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) {
1303         // Note: We want the rightmost candidate.
1304         Position position = caretAfterDelete.deepEquivalent().downstream();
1305         Node* node = position.deprecatedNode();
1306         ASSERT(node);
1307         // Normally deletion will leave a br as a placeholder.
1308         if (is<HTMLBRElement>(*node))
1309             removeNodeAndPruneAncestors(*node);
1310         // If the selection to move was empty and in an empty block that 
1311         // doesn't require a placeholder to prop itself open (like a bordered
1312         // div or an li), remove it during the move (the list removal code
1313         // expects this behavior).
1314         else if (isBlock(node)) {
1315             // If caret position after deletion and destination position coincides,
1316             // node should not be removed.
1317             if (!position.rendersInDifferentPosition(destination.deepEquivalent())) {
1318                 prune(node);
1319                 return;
1320             }
1321             removeNodeAndPruneAncestors(*node);
1322         }
1323         else if (lineBreakExistsAtPosition(position)) {
1324             // There is a preserved '\n' at caretAfterDelete.
1325             // We can safely assume this is a text node.
1326             Text& textNode = downcast<Text>(*node);
1327             if (textNode.length() == 1)
1328                 removeNodeAndPruneAncestors(textNode);
1329             else
1330                 deleteTextFromNode(textNode, position.deprecatedEditingOffset(), 1);
1331         }
1332     }
1333 }
1334     
1335 // This is a version of moveParagraph that preserves style by keeping the original markup
1336 // It is currently used only by IndentOutdentCommand but it is meant to be used in the
1337 // future by several other commands such as InsertList and the align commands.
1338 // The blockElement parameter is the element to move the paragraph to,
1339 // outerNode is the top element of the paragraph hierarchy. 
1340
1341 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, Element* blockElement, Node* outerNode)
1342 {
1343     if (startOfParagraphToMove.isNull() || endOfParagraphToMove.isNull())
1344         return;
1345     
1346     ASSERT(outerNode);
1347     ASSERT(blockElement);
1348
1349     VisiblePosition beforeParagraph = startOfParagraphToMove.previous();
1350     VisiblePosition afterParagraph(endOfParagraphToMove.next());
1351     
1352     // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
1353     // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
1354     Position start = startOfParagraphToMove.deepEquivalent().downstream();
1355     Position end = startOfParagraphToMove == endOfParagraphToMove ? start : endOfParagraphToMove.deepEquivalent().upstream();
1356
1357     cloneParagraphUnderNewElement(start, end, outerNode, blockElement);
1358       
1359     setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
1360     deleteSelection(false, false, false, false);
1361     
1362     // There are bugs in deletion when it removes a fully selected table/list.
1363     // It expands and removes the entire table/list, but will let content
1364     // before and after the table/list collapse onto one line.
1365        
1366     cleanupAfterDeletion();
1367     
1368     // Add a br if pruning an empty block level element caused a collapse.  For example:
1369     // foo^
1370     // <div>bar</div>
1371     // baz
1372     // Imagine moving 'bar' to ^.  'bar' will be deleted and its div pruned.  That would
1373     // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
1374     // Must recononicalize these two VisiblePositions after the pruning above.
1375     beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1376     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1377
1378     if (beforeParagraph.isNotNull() && !isRenderedTable(beforeParagraph.deepEquivalent().deprecatedNode())
1379         && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)
1380         && isEditablePosition(beforeParagraph.deepEquivalent())) {
1381         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
1382         insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEquivalent());
1383     }
1384 }
1385     
1386     
1387 // This moves a paragraph preserving its style.
1388 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle)
1389 {
1390     ASSERT(isStartOfParagraph(startOfParagraphToMove));
1391     ASSERT(isEndOfParagraph(endOfParagraphToMove));
1392     moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, preserveSelection, preserveStyle);
1393 }
1394
1395 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle)
1396 {
1397     if (startOfParagraphToMove == destination)
1398         return;
1399     
1400     int startIndex = -1;
1401     int endIndex = -1;
1402     int destinationIndex = -1;
1403     bool originalIsDirectional = endingSelection().isDirectional();
1404     if (preserveSelection && !endingSelection().isNone()) {
1405         VisiblePosition visibleStart = endingSelection().visibleStart();
1406         VisiblePosition visibleEnd = endingSelection().visibleEnd();
1407         
1408         bool startAfterParagraph = comparePositions(visibleStart, endOfParagraphToMove) > 0;
1409         bool endBeforeParagraph = comparePositions(visibleEnd, startOfParagraphToMove) < 0;
1410         
1411         if (!startAfterParagraph && !endBeforeParagraph) {
1412             bool startInParagraph = comparePositions(visibleStart, startOfParagraphToMove) >= 0;
1413             bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToMove) <= 0;
1414             
1415             startIndex = 0;
1416             if (startInParagraph) {
1417                 RefPtr<Range> startRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquivalent().parentAnchoredEquivalent());
1418                 startIndex = TextIterator::rangeLength(startRange.get(), true);
1419             }
1420
1421             endIndex = 0;
1422             if (endInParagraph) {
1423                 RefPtr<Range> endRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
1424                 endIndex = TextIterator::rangeLength(endRange.get(), true);
1425             }
1426         }
1427     }
1428     
1429     VisiblePosition beforeParagraph = startOfParagraphToMove.previous(CannotCrossEditingBoundary);
1430     VisiblePosition afterParagraph(endOfParagraphToMove.next(CannotCrossEditingBoundary));
1431
1432     // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
1433     // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
1434     Position start = startOfParagraphToMove.deepEquivalent().downstream();
1435     Position end = endOfParagraphToMove.deepEquivalent().upstream();
1436      
1437     // start and end can't be used directly to create a Range; they are "editing positions"
1438     Position startRangeCompliant = start.parentAnchoredEquivalent();
1439     Position endRangeCompliant = end.parentAnchoredEquivalent();
1440     RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset());
1441
1442     // FIXME: This is an inefficient way to preserve style on nodes in the paragraph to move. It
1443     // shouldn't matter though, since moved paragraphs will usually be quite small.
1444     RefPtr<DocumentFragment> fragment;
1445     // This used to use a ternary for initialization, but that confused some versions of GCC, see bug 37912
1446     if (startOfParagraphToMove != endOfParagraphToMove)
1447         fragment = createFragmentFromMarkup(document(), createMarkup(*range, 0, DoNotAnnotateForInterchange, true), emptyString());
1448
1449     // A non-empty paragraph's style is moved when we copy and move it.  We don't move 
1450     // anything if we're given an empty paragraph, but an empty paragraph can have style
1451     // too, <div><b><br></b></div> for example.  Save it so that we can preserve it later.
1452     RefPtr<EditingStyle> styleInEmptyParagraph;
1453 #if !PLATFORM(IOS)
1454     if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) {
1455 #else
1456     if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle && isRichlyEditablePosition(destination.deepEquivalent())) {
1457 #endif
1458         styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deepEquivalent());
1459         styleInEmptyParagraph->mergeTypingStyle(document());
1460         // The moved paragraph should assume the block style of the destination.
1461         styleInEmptyParagraph->removeBlockProperties();
1462     }
1463     
1464     // FIXME (5098931): We should add a new insert action "WebViewInsertActionMoved" and call shouldInsertFragment here.
1465     
1466     setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
1467     frame().editor().clearMisspellingsAndBadGrammar(endingSelection());
1468     deleteSelection(false, false, false, false);
1469
1470     ASSERT(destination.deepEquivalent().anchorNode()->isConnected());
1471     cleanupAfterDeletion(destination);
1472     ASSERT(destination.deepEquivalent().anchorNode()->isConnected());
1473
1474     // Add a br if pruning an empty block level element caused a collapse. For example:
1475     // foo^
1476     // <div>bar</div>
1477     // baz
1478     // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That would
1479     // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
1480     // Must recononicalize these two VisiblePositions after the pruning above.
1481     beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1482     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1483     if (beforeParagraph.isNotNull() && ((!isStartOfParagraph(beforeParagraph) && !isEndOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)) {
1484         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
1485         insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEquivalent());
1486         // Need an updateLayout here in case inserting the br has split a text node.
1487         document().updateLayoutIgnorePendingStylesheets();
1488     }
1489
1490     RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document().documentElement()), destination.deepEquivalent().parentAnchoredEquivalent()));
1491     destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
1492
1493     setEndingSelection(VisibleSelection(destination, originalIsDirectional));
1494     ASSERT(endingSelection().isCaretOrRange());
1495     OptionSet<ReplaceSelectionCommand::CommandOption> options { ReplaceSelectionCommand::SelectReplacement, ReplaceSelectionCommand::MovingParagraph };
1496     if (!preserveStyle)
1497         options.add(ReplaceSelectionCommand::MatchStyle);
1498     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), options));
1499
1500     frame().editor().markMisspellingsAndBadGrammar(endingSelection());
1501
1502     // If the selection is in an empty paragraph, restore styles from the old empty paragraph to the new empty paragraph.
1503     bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfParagraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().visibleStart());
1504     if (styleInEmptyParagraph && selectionIsEmptyParagraph)
1505         applyStyle(styleInEmptyParagraph.get());
1506
1507     if (preserveSelection && startIndex != -1) {
1508         // Fragment creation (using createMarkup) incorrectly uses regular
1509         // spaces instead of nbsps for some spaces that were rendered (11475), which
1510         // causes spaces to be collapsed during the move operation.  This results
1511         // in a call to rangeFromLocationAndLength with a location past the end
1512         // of the document (which will return null).
1513         RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + startIndex, 0, true);
1514         RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + endIndex, 0, true);
1515         if (start && end)
1516             setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
1517     }
1518 }
1519
1520 std::optional<VisibleSelection> CompositeEditCommand::shouldBreakOutOfEmptyListItem() const
1521 {
1522     auto emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
1523     if (!emptyListItem)
1524         return std::nullopt;
1525
1526     auto listNode = emptyListItem->parentNode();
1527     // FIXME: Can't we do something better when the immediate parent wasn't a list node?
1528     if (!listNode
1529         || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
1530         || !listNode->hasEditableStyle()
1531         || listNode == emptyListItem->rootEditableElement())
1532         return std::nullopt;
1533
1534     return VisibleSelection(endingSelection().start().previous(BackwardDeletion), endingSelection().end());
1535 }
1536
1537 // FIXME: Send an appropriate shouldDeleteRange call.
1538 bool CompositeEditCommand::breakOutOfEmptyListItem()
1539 {
1540     if (!shouldBreakOutOfEmptyListItem())
1541         return false;
1542
1543     auto emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
1544     auto listNode = emptyListItem->parentNode();
1545     auto style = EditingStyle::create(endingSelection().start());
1546     style->mergeTypingStyle(document());
1547
1548     RefPtr<Element> newBlock;
1549     if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
1550         if (is<HTMLLIElement>(*blockEnclosingList)) { // listNode is inside another list item
1551             if (visiblePositionAfterNode(*blockEnclosingList) == visiblePositionAfterNode(*listNode)) {
1552                 // If listNode appears at the end of the outer list item, then move listNode outside of this list item
1553                 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should become <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section
1554                 // If listNode does NOT appear at the end, then we should consider it as a regular paragraph.
1555                 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should become <ul><li> <div><br></div> hello</li></ul> at the end
1556                 splitElement(downcast<HTMLLIElement>(*blockEnclosingList), *listNode);
1557                 removeNodePreservingChildren(*listNode->parentNode());
1558                 newBlock = HTMLLIElement::create(document());
1559             }
1560             // If listNode does NOT appear at the end of the outer list item, then behave as if in a regular paragraph.
1561         } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->hasTagName(ulTag))
1562             newBlock = HTMLLIElement::create(document());
1563     }
1564     if (!newBlock)
1565         newBlock = createDefaultParagraphElement(document());
1566
1567     RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibling();
1568     RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling();
1569     if (isListItem(nextListNode.get()) || isListHTMLElement(nextListNode.get())) {
1570         // If emptyListItem follows another list item or nested list, split the list node.
1571         if (isListItem(previousListNode.get()) || isListHTMLElement(previousListNode.get()))
1572             splitElement(downcast<Element>(*listNode), *emptyListItem);
1573
1574         // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
1575         // Because we have splitted the element, emptyListItem is the first element in the list node.
1576         // i.e. insert newBlock before ul or ol whose first element is emptyListItem
1577         insertNodeBefore(*newBlock, *listNode);
1578         removeNode(*emptyListItem);
1579     } else {
1580         // When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
1581         // Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
1582         insertNodeAfter(*newBlock, *listNode);
1583         removeNode(isListItem(previousListNode.get()) || isListHTMLElement(previousListNode.get()) ? *emptyListItem : *listNode);
1584     }
1585
1586     appendBlockPlaceholder(*newBlock);
1587     setEndingSelection(VisibleSelection(firstPositionInNode(newBlock.get()), DOWNSTREAM, endingSelection().isDirectional()));
1588
1589     style->prepareToApplyAt(endingSelection().start());
1590     if (!style->isEmpty())
1591         applyStyle(style.ptr());
1592
1593     return true;
1594 }
1595
1596 // If the caret is in an empty quoted paragraph, and either there is nothing before that
1597 // paragraph, or what is before is unquoted, and the user presses delete, unquote that paragraph.
1598 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
1599 {
1600     if (!endingSelection().isCaret())
1601         return false;
1602         
1603     VisiblePosition caret(endingSelection().visibleStart());
1604     Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
1605     if (!highestBlockquote)
1606         return false;
1607
1608     if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret))
1609         return false;
1610
1611     VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
1612     // Only move forward if there's nothing before the caret, or if there's unquoted content before it.
1613     if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
1614         return false;
1615     
1616     auto br = HTMLBRElement::create(document());
1617     auto* brPtr = br.ptr();
1618     // We want to replace this quoted paragraph with an unquoted one, so insert a br
1619     // to hold the caret before the highest blockquote.
1620     insertNodeBefore(WTFMove(br), *highestBlockquote);
1621     VisiblePosition atBR(positionBeforeNode(brPtr));
1622     // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
1623     // a second one.
1624     if (!isStartOfParagraph(atBR))
1625         insertNodeBefore(HTMLBRElement::create(document()), *brPtr);
1626     setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
1627     
1628     // If this is an empty paragraph there must be a line break here.
1629     if (!lineBreakExistsAtVisiblePosition(caret))
1630         return false;
1631
1632     Position caretPos(caret.deepEquivalent().downstream());
1633     // A line break is either a br or a preserved newline.
1634     ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedNode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style().preserveNewline()));
1635     
1636     if (caretPos.deprecatedNode()->hasTagName(brTag))
1637         removeNodeAndPruneAncestors(*caretPos.deprecatedNode());
1638     else if (is<Text>(*caretPos.deprecatedNode())) {
1639         ASSERT(caretPos.deprecatedEditingOffset() == 0);
1640         Text& textNode = downcast<Text>(*caretPos.deprecatedNode());
1641         ContainerNode* parentNode = textNode.parentNode();
1642         // The preserved newline must be the first thing in the node, since otherwise the previous
1643         // paragraph would be quoted, and we verified that it wasn't above.
1644         deleteTextFromNode(textNode, 0, 1);
1645         prune(parentNode);
1646     }
1647
1648     return true;
1649 }
1650
1651 // Operations use this function to avoid inserting content into an anchor when at the start or the end of
1652 // that anchor, as in NSTextView.
1653 // FIXME: This is only an approximation of NSTextViews insertion behavior, which varies depending on how
1654 // the caret was made. 
1655 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Position& original)
1656 {
1657     if (original.isNull())
1658         return original;
1659         
1660     VisiblePosition visiblePos(original);
1661     Element* enclosingAnchor = enclosingAnchorElement(original);
1662     Position result = original;
1663
1664     if (!enclosingAnchor)
1665         return result;
1666
1667     // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
1668     if (enclosingAnchor && !isBlock(enclosingAnchor)) {
1669         VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
1670         VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
1671         // If visually just after the anchor, insert *inside* the anchor unless it's the last
1672         // VisiblePosition in the document, to match NSTextView.
1673         if (visiblePos == lastInAnchor) {
1674             // Make sure anchors are pushed down before avoiding them so that we don't
1675             // also avoid structural elements like lists and blocks (5142012).
1676             if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
1677                 pushAnchorElementDown(*enclosingAnchor);
1678                 enclosingAnchor = enclosingAnchorElement(original);
1679                 if (!enclosingAnchor)
1680                     return original;
1681             }
1682             // Don't insert outside an anchor if doing so would skip over a line break.  It would
1683             // probably be safe to move the line break so that we could still avoid the anchor here.
1684             Position downstream(visiblePos.deepEquivalent().downstream());
1685             if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
1686                 return original;
1687             
1688             result = positionInParentAfterNode(enclosingAnchor);
1689         }
1690         // If visually just before an anchor, insert *outside* the anchor unless it's the first
1691         // VisiblePosition in a paragraph, to match NSTextView.
1692         if (visiblePos == firstInAnchor) {
1693             // Make sure anchors are pushed down before avoiding them so that we don't
1694             // also avoid structural elements like lists and blocks (5142012).
1695             if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
1696                 pushAnchorElementDown(*enclosingAnchor);
1697                 enclosingAnchor = enclosingAnchorElement(original);
1698             }
1699             if (!enclosingAnchor)
1700                 return original;
1701
1702             result = positionInParentBeforeNode(enclosingAnchor);
1703         }
1704     }
1705         
1706     if (result.isNull() || !editableRootForPosition(result))
1707         result = original;
1708     
1709     return result;
1710 }
1711
1712 // Splits the tree parent by parent until we reach the specified ancestor. We use VisiblePositions
1713 // to determine if the split is necessary. Returns the last split node.
1714 RefPtr<Node> CompositeEditCommand::splitTreeToNode(Node& start, Node& end, bool shouldSplitAncestor)
1715 {
1716     ASSERT(&start != &end);
1717
1718     RefPtr<Node> adjustedEnd = &end;
1719     if (shouldSplitAncestor && adjustedEnd->parentNode())
1720         adjustedEnd = adjustedEnd->parentNode();
1721
1722     ASSERT(adjustedEnd);
1723     RefPtr<Node> node;
1724     for (node = &start; node && node->parentNode() != adjustedEnd; node = node->parentNode()) {
1725         if (!is<Element>(*node->parentNode()))
1726             break;
1727         // Do not split a node when doing so introduces an empty node.
1728         VisiblePosition positionInParent = firstPositionInNode(node->parentNode());
1729         VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get());
1730         if (positionInParent != positionInNode)
1731             splitElement(downcast<Element>(*node->parentNode()), *node);
1732     }
1733
1734     return node;
1735 }
1736
1737 Ref<Element> createBlockPlaceholderElement(Document& document)
1738 {
1739     return HTMLBRElement::create(document);
1740 }
1741
1742 } // namespace WebCore