[WTF] Clean up StringStatics.cpp by using LazyNeverDestroyed<> for Atoms
[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         markerController.addMarker(newRange.get(), marker.type(), marker.description(), marker.alternatives(), marker.metadata());
775 #else
776         markerController.addMarker(newRange.get(), marker.type(), marker.description());
777 #endif // PLATFORM(IOS)
778 }
779
780 Position CompositeEditCommand::positionOutsideTabSpan(const Position& position)
781 {
782     if (!isTabSpanTextNode(position.anchorNode()))
783         return position;
784
785     switch (position.anchorType()) {
786     case Position::PositionIsBeforeChildren:
787     case Position::PositionIsAfterChildren:
788         ASSERT_NOT_REACHED();
789         return position;
790     case Position::PositionIsOffsetInAnchor:
791         break;
792     case Position::PositionIsBeforeAnchor:
793         return positionInParentBeforeNode(position.anchorNode());
794     case Position::PositionIsAfterAnchor:
795         return positionInParentAfterNode(position.anchorNode());
796     }
797
798     auto* tabSpan = tabSpanNode(position.containerNode());
799
800     if (position.offsetInContainerNode() <= caretMinOffset(*position.containerNode()))
801         return positionInParentBeforeNode(tabSpan);
802
803     if (position.offsetInContainerNode() >= caretMaxOffset(*position.containerNode()))
804         return positionInParentAfterNode(tabSpan);
805
806     splitTextNodeContainingElement(downcast<Text>(*position.containerNode()), position.offsetInContainerNode());
807     return positionInParentBeforeNode(tabSpan);
808 }
809
810 void CompositeEditCommand::insertNodeAtTabSpanPosition(Ref<Node>&& node, const Position& pos)
811 {
812     // insert node before, after, or at split of tab span
813     insertNodeAt(WTFMove(node), positionOutsideTabSpan(pos));
814 }
815
816 static EditAction deleteSelectionEditingActionForEditingAction(EditAction editingAction)
817 {
818     switch (editingAction) {
819     case EditActionCut:
820         return EditActionCut;
821     default:
822         return EditActionDelete;
823     }
824 }
825
826 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
827 {
828     if (endingSelection().isRange())
829         applyCommandToComposite(DeleteSelectionCommand::create(document(), smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup, deleteSelectionEditingActionForEditingAction(editingAction())));
830 }
831
832 void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
833 {
834     if (selection.isRange())
835         applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
836 }
837
838 void CompositeEditCommand::removeNodeAttribute(Element& element, const QualifiedName& attribute)
839 {
840     setNodeAttribute(element, attribute, nullAtom());
841 }
842
843 void CompositeEditCommand::setNodeAttribute(Element& element, const QualifiedName& attribute, const AtomicString& value)
844 {
845     applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute, value));
846 }
847
848 static inline bool containsOnlyDeprecatedEditingWhitespace(const String& text)
849 {
850     for (unsigned i = 0; i < text.length(); ++i) {
851         if (!deprecatedIsEditingWhitespace(text[i]))
852             return false;
853     }
854     return true;
855 }
856
857 bool CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor(const String& text) const
858 {
859     return containsOnlyDeprecatedEditingWhitespace(text);
860 }
861
862 bool CompositeEditCommand::canRebalance(const Position& position) const
863 {
864     Node* node = position.containerNode();
865     if (position.anchorType() != Position::PositionIsOffsetInAnchor || !is<Text>(node))
866         return false;
867
868     Text& textNode = downcast<Text>(*node);
869     if (!textNode.length())
870         return false;
871
872     node->document().updateStyleIfNeeded();
873
874     RenderObject* renderer = textNode.renderer();
875     if (renderer && !renderer->style().collapseWhiteSpace())
876         return false;
877
878     return true;
879 }
880
881 // FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
882 void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
883 {
884     Node* node = position.containerNode();
885     if (!canRebalance(position))
886         return;
887
888     // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
889     int offset = position.deprecatedEditingOffset();
890     String text = downcast<Text>(*node).data();
891     if (!deprecatedIsEditingWhitespace(text[offset])) {
892         offset--;
893         if (offset < 0 || !deprecatedIsEditingWhitespace(text[offset]))
894             return;
895     }
896
897     rebalanceWhitespaceOnTextSubstring(downcast<Text>(*node), position.offsetInContainerNode(), position.offsetInContainerNode());
898 }
899
900 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(Text& textNode, int startOffset, int endOffset)
901 {
902     String text = textNode.data();
903     ASSERT(!text.isEmpty());
904
905     // Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
906     int upstream = startOffset;
907     while (upstream > 0 && deprecatedIsEditingWhitespace(text[upstream - 1]))
908         upstream--;
909     
910     int downstream = endOffset;
911     while ((unsigned)downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
912         downstream++;
913     
914     int length = downstream - upstream;
915     if (!length)
916         return;
917
918     VisiblePosition visibleUpstreamPos(Position(&textNode, upstream));
919     VisiblePosition visibleDownstreamPos(Position(&textNode, downstream));
920     
921     String string = text.substring(upstream, length);
922     String rebalancedString = stringWithRebalancedWhitespace(string,
923     // 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
924     // this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
925                                                              isStartOfParagraph(visibleUpstreamPos) || upstream == 0, 
926                                                              isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
927     
928     if (string != rebalancedString)
929         replaceTextInNodePreservingMarkers(textNode, upstream, length, rebalancedString);
930 }
931
932 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& position)
933 {
934     Node* node = position.deprecatedNode();
935     if (!is<Text>(node))
936         return;
937     Text& textNode = downcast<Text>(*node);
938     
939     if (!textNode.length())
940         return;
941     RenderObject* renderer = textNode.renderer();
942     if (renderer && !renderer->style().collapseWhiteSpace())
943         return;
944
945     // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
946     Position upstreamPos = position.upstream();
947     deleteInsignificantText(position.upstream(), position.downstream());
948     position = upstreamPos.downstream();
949
950     VisiblePosition visiblePos(position);
951     VisiblePosition previousVisiblePos(visiblePos.previous());
952     Position previous(previousVisiblePos.deepEquivalent());
953     
954     if (deprecatedIsCollapsibleWhitespace(previousVisiblePos.characterAfter()) && is<Text>(*previous.deprecatedNode()) && !is<HTMLBRElement>(*previous.deprecatedNode()))
955         replaceTextInNodePreservingMarkers(downcast<Text>(*previous.deprecatedNode()), previous.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
956     if (deprecatedIsCollapsibleWhitespace(visiblePos.characterAfter()) && is<Text>(*position.deprecatedNode()) && !is<HTMLBRElement>(*position.deprecatedNode()))
957         replaceTextInNodePreservingMarkers(downcast<Text>(*position.deprecatedNode()), position.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
958 }
959
960 void CompositeEditCommand::rebalanceWhitespace()
961 {
962     VisibleSelection selection = endingSelection();
963     if (selection.isNone())
964         return;
965         
966     rebalanceWhitespaceAt(selection.start());
967     if (selection.isRange())
968         rebalanceWhitespaceAt(selection.end());
969 }
970
971 void CompositeEditCommand::deleteInsignificantText(Text& textNode, unsigned start, unsigned end)
972 {
973     if (start >= end)
974         return;
975
976     document().updateLayout();
977
978     RenderText* textRenderer = textNode.renderer();
979     if (!textRenderer)
980         return;
981
982     Vector<InlineTextBox*> sortedTextBoxes;
983     size_t sortedTextBoxesPosition = 0;
984    
985     for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox())
986         sortedTextBoxes.append(textBox);
987     
988     // If there is mixed directionality text, the boxes can be out of order,
989     // (like Arabic with embedded LTR), so sort them first. 
990     if (textRenderer->containsReversedText())    
991         std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart);
992     InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedTextBoxesPosition];
993
994     if (!box) {
995         // whole text node is empty
996         removeNode(textNode);
997         return;    
998     }
999     
1000     unsigned length = textNode.length();
1001     if (start >= length || end > length)
1002         return;
1003
1004     unsigned removed = 0;
1005     InlineTextBox* prevBox = nullptr;
1006     String str;
1007
1008     // This loop structure works to process all gaps preceding a box,
1009     // and also will look at the gap after the last box.
1010     while (prevBox || box) {
1011         unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0;
1012         if (end < gapStart)
1013             // No more chance for any intersections
1014             break;
1015
1016         unsigned gapEnd = box ? box->start() : length;
1017         bool indicesIntersect = start <= gapEnd && end >= gapStart;
1018         int gapLen = gapEnd - gapStart;
1019         if (indicesIntersect && gapLen > 0) {
1020             gapStart = std::max(gapStart, start);
1021             gapEnd = std::min(gapEnd, end);
1022             if (str.isNull())
1023                 str = textNode.data().substring(start, end - start);
1024             // remove text in the gap
1025             str.remove(gapStart - start - removed, gapLen);
1026             removed += gapLen;
1027         }
1028         
1029         prevBox = box;
1030         if (box) {
1031             if (++sortedTextBoxesPosition < sortedTextBoxes.size())
1032                 box = sortedTextBoxes[sortedTextBoxesPosition];
1033             else
1034                 box = nullptr;
1035         }
1036     }
1037
1038     if (!str.isNull()) {
1039         // Replace the text between start and end with our pruned version.
1040         if (!str.isEmpty())
1041             replaceTextInNode(textNode, start, end - start, str);
1042         else {
1043             // Assert that we are not going to delete all of the text in the node.
1044             // If we were, that should have been done above with the call to 
1045             // removeNode and return.
1046             ASSERT(start > 0 || end - start < textNode.length());
1047             deleteTextFromNode(textNode, start, end - start);
1048         }
1049     }
1050 }
1051
1052 void CompositeEditCommand::deleteInsignificantText(const Position& start, const Position& end)
1053 {
1054     if (start.isNull() || end.isNull())
1055         return;
1056
1057     if (comparePositions(start, end) >= 0)
1058         return;
1059
1060     Vector<Ref<Text>> nodes;
1061     for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(*node)) {
1062         if (is<Text>(*node))
1063             nodes.append(downcast<Text>(*node));
1064         if (node == end.deprecatedNode())
1065             break;
1066     }
1067
1068     for (auto& textNode : nodes) {
1069         int startOffset = textNode.ptr() == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0;
1070         int endOffset = textNode.ptr() == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length());
1071         deleteInsignificantText(textNode, startOffset, endOffset);
1072     }
1073 }
1074
1075 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos)
1076 {
1077     Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivalent().downstream();
1078     deleteInsignificantText(pos, end);
1079 }
1080
1081 Ref<Element> CompositeEditCommand::appendBlockPlaceholder(Ref<Element>&& container)
1082 {
1083     document().updateLayoutIgnorePendingStylesheets();
1084     
1085     // Should assert isBlockFlow || isInlineFlow when deletion improves. See 4244964.
1086     ASSERT(container->renderer());
1087
1088     auto placeholder = createBlockPlaceholderElement(document());
1089     appendNode(placeholder.copyRef(), WTFMove(container));
1090     return placeholder;
1091 }
1092
1093 RefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& pos)
1094 {
1095     if (pos.isNull())
1096         return nullptr;
1097
1098     // Should assert isBlockFlow || isInlineFlow when deletion improves.  See 4244964.
1099     ASSERT(pos.deprecatedNode()->renderer());
1100
1101     auto placeholder = createBlockPlaceholderElement(document());
1102     insertNodeAt(placeholder.copyRef(), pos);
1103     return WTFMove(placeholder);
1104 }
1105
1106 RefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
1107 {
1108     if (!container)
1109         return nullptr;
1110
1111     document().updateLayoutIgnorePendingStylesheets();
1112
1113     auto* renderer = container->renderer();
1114     if (!is<RenderBlockFlow>(renderer))
1115         return nullptr;
1116     
1117     // Append the placeholder to make sure it follows any unrendered blocks.
1118     auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
1119     if (!blockFlow.height() || (blockFlow.isListItem() && !blockFlow.firstChild()))
1120         return appendBlockPlaceholder(*container);
1121
1122     return nullptr;
1123 }
1124
1125 // Assumes that the position is at a placeholder and does the removal without much checking.
1126 void CompositeEditCommand::removePlaceholderAt(const Position& p)
1127 {
1128     ASSERT(lineBreakExistsAtPosition(p));
1129     
1130     // We are certain that the position is at a line break, but it may be a br or a preserved newline.
1131     if (is<HTMLBRElement>(*p.anchorNode())) {
1132         removeNode(*p.anchorNode());
1133         return;
1134     }
1135     
1136     deleteTextFromNode(downcast<Text>(*p.anchorNode()), p.offsetInContainerNode(), 1);
1137 }
1138
1139 Ref<HTMLElement> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
1140 {
1141     auto paragraphElement = createDefaultParagraphElement(document());
1142     paragraphElement->appendChild(HTMLBRElement::create(document()));
1143     insertNodeAt(paragraphElement.copyRef(), position);
1144     return paragraphElement;
1145 }
1146
1147 // If the paragraph is not entirely within it's own block, create one and move the paragraph into 
1148 // it, and return that block.  Otherwise return 0.
1149 RefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Position& pos)
1150 {
1151     if (pos.isNull())
1152         return nullptr;
1153     
1154     document().updateLayoutIgnorePendingStylesheets();
1155     
1156     // It's strange that this function is responsible for verifying that pos has not been invalidated
1157     // by an earlier call to this function.  The caller, applyBlockStyle, should do this.
1158     VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
1159     VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos));
1160     VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos);
1161     VisiblePosition next = visibleParagraphEnd.next();
1162     VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd;
1163     
1164     Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream();
1165     Position upstreamEnd = visibleEnd.deepEquivalent().upstream();
1166
1167     // If there are no VisiblePositions in the same block as pos then 
1168     // upstreamStart will be outside the paragraph
1169     if (comparePositions(pos, upstreamStart) < 0)
1170         return nullptr;
1171
1172     // Perform some checks to see if we need to perform work in this function.
1173     if (isBlock(upstreamStart.deprecatedNode())) {
1174         // If the block is the root editable element, always move content to a new block,
1175         // since it is illegal to modify attributes on the root editable element for editing.
1176         if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamStart)) {
1177             // If the block is the root editable element and it contains no visible content, create a new
1178             // block but don't try and move content into it, since there's nothing for moveParagraphs to move.
1179             if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(downcast<RenderElement>(*upstreamStart.deprecatedNode()->renderer())))
1180                 return insertNewDefaultParagraphElementAt(upstreamStart);
1181         } else if (isBlock(upstreamEnd.deprecatedNode())) {
1182             if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.deprecatedNode())) {
1183                 // If the paragraph end is a descendant of paragraph start, then we need to run
1184                 // the rest of this function. If not, we can bail here.
1185                 return nullptr;
1186             }
1187         } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart.deprecatedNode()) {
1188             // The visibleEnd. If it is an ancestor of the paragraph start, then
1189             // we can bail as we have a full block to work with.
1190             if (upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock(upstreamEnd.deprecatedNode())))
1191                 return nullptr;
1192         } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
1193             // At the end of the editable region. We can bail here as well.
1194             return nullptr;
1195         }
1196     }
1197
1198     // If upstreamStart is not editable, then we can bail here.
1199     if (!isEditablePosition(upstreamStart))
1200         return nullptr;
1201     auto newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
1202
1203     bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTagName(brTag);
1204
1205     moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(firstPositionInNode(newBlock.ptr())));
1206
1207     if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !endWasBr)
1208         removeNode(*newBlock->lastChild());
1209
1210     return WTFMove(newBlock);
1211 }
1212
1213 void CompositeEditCommand::pushAnchorElementDown(Element& anchorElement)
1214 {
1215     ASSERT(anchorElement.isLink());
1216     
1217     setEndingSelection(VisibleSelection::selectionFromContentsOfNode(&anchorElement));
1218     applyStyledElement(anchorElement);
1219     // Clones of anchorElement have been pushed down, now remove it.
1220     if (anchorElement.isConnected())
1221         removeNodePreservingChildren(anchorElement);
1222 }
1223
1224 // Clone the paragraph between start and end under blockElement,
1225 // preserving the hierarchy up to outerNode. 
1226
1227 void CompositeEditCommand::cloneParagraphUnderNewElement(const Position& start, const Position& end, Node* passedOuterNode, Element* blockElement)
1228 {
1229     ASSERT(comparePositions(start, end) <= 0);
1230
1231     // First we clone the outerNode
1232     RefPtr<Node> lastNode;
1233     RefPtr<Node> outerNode = passedOuterNode;
1234
1235     if (outerNode->isRootEditableElement()) {
1236         lastNode = blockElement;
1237     } else {
1238         lastNode = outerNode->cloneNode(isRenderedTable(outerNode.get()));
1239         appendNode(*lastNode, *blockElement);
1240     }
1241
1242     if (start.deprecatedNode() != outerNode && lastNode->isElementNode() && start.anchorNode()->isDescendantOf(outerNode.get())) {
1243         Vector<RefPtr<Node>> ancestors;
1244         
1245         // Insert each node from innerNode to outerNode (excluded) in a list.
1246         for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->parentNode())
1247             ancestors.append(n);
1248
1249         // Clone every node between start.deprecatedNode() and outerBlock.
1250
1251         for (size_t i = ancestors.size(); i != 0; --i) {
1252             Node* item = ancestors[i - 1].get();
1253             auto child = item->cloneNode(isRenderedTable(item));
1254             appendNode(child.copyRef(), downcast<Element>(*lastNode));
1255             lastNode = WTFMove(child);
1256         }
1257     }
1258
1259     // Handle the case of paragraphs with more than one node,
1260     // cloning all the siblings until end.deprecatedNode() is reached.
1261     
1262     if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) {
1263         // If end is not a descendant of outerNode we need to
1264         // find the first common ancestor to increase the scope
1265         // of our nextSibling traversal.
1266         while (!end.deprecatedNode()->isDescendantOf(outerNode.get())) {
1267             outerNode = outerNode->parentNode();
1268         }
1269
1270         RefPtr<Node> startNode = start.deprecatedNode();
1271         for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(*startNode, outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(*node, outerNode.get())) {
1272             // Move lastNode up in the tree as much as node was moved up in the
1273             // tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
1274             // node and the original start node is maintained in the clone.
1275             while (startNode->parentNode() != node->parentNode()) {
1276                 startNode = startNode->parentNode();
1277                 lastNode = lastNode->parentNode();
1278             }
1279
1280             auto clonedNode = node->cloneNode(true);
1281             insertNodeAfter(clonedNode.copyRef(), *lastNode);
1282             lastNode = WTFMove(clonedNode);
1283             if (node == end.deprecatedNode() || end.deprecatedNode()->isDescendantOf(*node))
1284                 break;
1285         }
1286     }
1287 }
1288
1289     
1290 // There are bugs in deletion when it removes a fully selected table/list.
1291 // It expands and removes the entire table/list, but will let content
1292 // before and after the table/list collapse onto one line.   
1293 // Deleting a paragraph will leave a placeholder. Remove it (and prune
1294 // empty or unrendered parents).
1295
1296 void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination)
1297 {
1298     VisiblePosition caretAfterDelete = endingSelection().visibleStart();
1299     if (!caretAfterDelete.equals(destination) && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) {
1300         // Note: We want the rightmost candidate.
1301         Position position = caretAfterDelete.deepEquivalent().downstream();
1302         Node* node = position.deprecatedNode();
1303         ASSERT(node);
1304         // Normally deletion will leave a br as a placeholder.
1305         if (is<HTMLBRElement>(*node))
1306             removeNodeAndPruneAncestors(*node);
1307         // If the selection to move was empty and in an empty block that 
1308         // doesn't require a placeholder to prop itself open (like a bordered
1309         // div or an li), remove it during the move (the list removal code
1310         // expects this behavior).
1311         else if (isBlock(node)) {
1312             // If caret position after deletion and destination position coincides,
1313             // node should not be removed.
1314             if (!position.rendersInDifferentPosition(destination.deepEquivalent())) {
1315                 prune(node);
1316                 return;
1317             }
1318             removeNodeAndPruneAncestors(*node);
1319         }
1320         else if (lineBreakExistsAtPosition(position)) {
1321             // There is a preserved '\n' at caretAfterDelete.
1322             // We can safely assume this is a text node.
1323             Text& textNode = downcast<Text>(*node);
1324             if (textNode.length() == 1)
1325                 removeNodeAndPruneAncestors(textNode);
1326             else
1327                 deleteTextFromNode(textNode, position.deprecatedEditingOffset(), 1);
1328         }
1329     }
1330 }
1331     
1332 // This is a version of moveParagraph that preserves style by keeping the original markup
1333 // It is currently used only by IndentOutdentCommand but it is meant to be used in the
1334 // future by several other commands such as InsertList and the align commands.
1335 // The blockElement parameter is the element to move the paragraph to,
1336 // outerNode is the top element of the paragraph hierarchy. 
1337
1338 void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, Element* blockElement, Node* outerNode)
1339 {
1340     if (startOfParagraphToMove.isNull() || endOfParagraphToMove.isNull())
1341         return;
1342     
1343     ASSERT(outerNode);
1344     ASSERT(blockElement);
1345
1346     VisiblePosition beforeParagraph = startOfParagraphToMove.previous();
1347     VisiblePosition afterParagraph(endOfParagraphToMove.next());
1348     
1349     // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
1350     // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
1351     Position start = startOfParagraphToMove.deepEquivalent().downstream();
1352     Position end = startOfParagraphToMove == endOfParagraphToMove ? start : endOfParagraphToMove.deepEquivalent().upstream();
1353
1354     cloneParagraphUnderNewElement(start, end, outerNode, blockElement);
1355       
1356     setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
1357     deleteSelection(false, false, false, false);
1358     
1359     // There are bugs in deletion when it removes a fully selected table/list.
1360     // It expands and removes the entire table/list, but will let content
1361     // before and after the table/list collapse onto one line.
1362        
1363     cleanupAfterDeletion();
1364     
1365     // Add a br if pruning an empty block level element caused a collapse.  For example:
1366     // foo^
1367     // <div>bar</div>
1368     // baz
1369     // Imagine moving 'bar' to ^.  'bar' will be deleted and its div pruned.  That would
1370     // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
1371     // Must recononicalize these two VisiblePositions after the pruning above.
1372     beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1373     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1374
1375     if (beforeParagraph.isNotNull() && !isRenderedTable(beforeParagraph.deepEquivalent().deprecatedNode())
1376         && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)
1377         && isEditablePosition(beforeParagraph.deepEquivalent())) {
1378         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
1379         insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEquivalent());
1380     }
1381 }
1382     
1383     
1384 // This moves a paragraph preserving its style.
1385 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle)
1386 {
1387     ASSERT(isStartOfParagraph(startOfParagraphToMove));
1388     ASSERT(isEndOfParagraph(endOfParagraphToMove));
1389     moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, preserveSelection, preserveStyle);
1390 }
1391
1392 void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle)
1393 {
1394     if (startOfParagraphToMove == destination)
1395         return;
1396     
1397     int startIndex = -1;
1398     int endIndex = -1;
1399     int destinationIndex = -1;
1400     bool originalIsDirectional = endingSelection().isDirectional();
1401     if (preserveSelection && !endingSelection().isNone()) {
1402         VisiblePosition visibleStart = endingSelection().visibleStart();
1403         VisiblePosition visibleEnd = endingSelection().visibleEnd();
1404         
1405         bool startAfterParagraph = comparePositions(visibleStart, endOfParagraphToMove) > 0;
1406         bool endBeforeParagraph = comparePositions(visibleEnd, startOfParagraphToMove) < 0;
1407         
1408         if (!startAfterParagraph && !endBeforeParagraph) {
1409             bool startInParagraph = comparePositions(visibleStart, startOfParagraphToMove) >= 0;
1410             bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToMove) <= 0;
1411             
1412             startIndex = 0;
1413             if (startInParagraph) {
1414                 RefPtr<Range> startRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquivalent().parentAnchoredEquivalent());
1415                 startIndex = TextIterator::rangeLength(startRange.get(), true);
1416             }
1417
1418             endIndex = 0;
1419             if (endInParagraph) {
1420                 RefPtr<Range> endRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
1421                 endIndex = TextIterator::rangeLength(endRange.get(), true);
1422             }
1423         }
1424     }
1425     
1426     VisiblePosition beforeParagraph = startOfParagraphToMove.previous(CannotCrossEditingBoundary);
1427     VisiblePosition afterParagraph(endOfParagraphToMove.next(CannotCrossEditingBoundary));
1428
1429     // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
1430     // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
1431     Position start = startOfParagraphToMove.deepEquivalent().downstream();
1432     Position end = endOfParagraphToMove.deepEquivalent().upstream();
1433      
1434     // start and end can't be used directly to create a Range; they are "editing positions"
1435     Position startRangeCompliant = start.parentAnchoredEquivalent();
1436     Position endRangeCompliant = end.parentAnchoredEquivalent();
1437     RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset());
1438
1439     // FIXME: This is an inefficient way to preserve style on nodes in the paragraph to move. It
1440     // shouldn't matter though, since moved paragraphs will usually be quite small.
1441     RefPtr<DocumentFragment> fragment;
1442     // This used to use a ternary for initialization, but that confused some versions of GCC, see bug 37912
1443     if (startOfParagraphToMove != endOfParagraphToMove)
1444         fragment = createFragmentFromMarkup(document(), createMarkup(*range, 0, DoNotAnnotateForInterchange, true), emptyString());
1445
1446     // A non-empty paragraph's style is moved when we copy and move it.  We don't move 
1447     // anything if we're given an empty paragraph, but an empty paragraph can have style
1448     // too, <div><b><br></b></div> for example.  Save it so that we can preserve it later.
1449     RefPtr<EditingStyle> styleInEmptyParagraph;
1450 #if !PLATFORM(IOS)
1451     if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) {
1452 #else
1453     if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle && isRichlyEditablePosition(destination.deepEquivalent())) {
1454 #endif
1455         styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deepEquivalent());
1456         styleInEmptyParagraph->mergeTypingStyle(document());
1457         // The moved paragraph should assume the block style of the destination.
1458         styleInEmptyParagraph->removeBlockProperties();
1459     }
1460     
1461     // FIXME (5098931): We should add a new insert action "WebViewInsertActionMoved" and call shouldInsertFragment here.
1462     
1463     setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
1464     frame().editor().clearMisspellingsAndBadGrammar(endingSelection());
1465     deleteSelection(false, false, false, false);
1466
1467     ASSERT(destination.deepEquivalent().anchorNode()->isConnected());
1468     cleanupAfterDeletion(destination);
1469     ASSERT(destination.deepEquivalent().anchorNode()->isConnected());
1470
1471     // Add a br if pruning an empty block level element caused a collapse. For example:
1472     // foo^
1473     // <div>bar</div>
1474     // baz
1475     // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That would
1476     // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
1477     // Must recononicalize these two VisiblePositions after the pruning above.
1478     beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1479     afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1480     if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || beforeParagraph == afterParagraph)) {
1481         // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
1482         insertNodeAt(HTMLBRElement::create(document()), beforeParagraph.deepEquivalent());
1483         // Need an updateLayout here in case inserting the br has split a text node.
1484         document().updateLayoutIgnorePendingStylesheets();
1485     }
1486
1487     RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document().documentElement()), destination.deepEquivalent().parentAnchoredEquivalent()));
1488     destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
1489
1490     setEndingSelection(VisibleSelection(destination, originalIsDirectional));
1491     ASSERT(endingSelection().isCaretOrRange());
1492     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MovingParagraph;
1493     if (!preserveStyle)
1494         options |= ReplaceSelectionCommand::MatchStyle;
1495     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), options));
1496
1497     frame().editor().markMisspellingsAndBadGrammar(endingSelection());
1498
1499     // If the selection is in an empty paragraph, restore styles from the old empty paragraph to the new empty paragraph.
1500     bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfParagraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().visibleStart());
1501     if (styleInEmptyParagraph && selectionIsEmptyParagraph)
1502         applyStyle(styleInEmptyParagraph.get());
1503
1504     if (preserveSelection && startIndex != -1) {
1505         // Fragment creation (using createMarkup) incorrectly uses regular
1506         // spaces instead of nbsps for some spaces that were rendered (11475), which
1507         // causes spaces to be collapsed during the move operation.  This results
1508         // in a call to rangeFromLocationAndLength with a location past the end
1509         // of the document (which will return null).
1510         RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + startIndex, 0, true);
1511         RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document().documentElement(), destinationIndex + endIndex, 0, true);
1512         if (start && end)
1513             setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
1514     }
1515 }
1516
1517 std::optional<VisibleSelection> CompositeEditCommand::shouldBreakOutOfEmptyListItem() const
1518 {
1519     auto emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
1520     if (!emptyListItem)
1521         return std::nullopt;
1522
1523     auto listNode = emptyListItem->parentNode();
1524     // FIXME: Can't we do something better when the immediate parent wasn't a list node?
1525     if (!listNode
1526         || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
1527         || !listNode->hasEditableStyle()
1528         || listNode == emptyListItem->rootEditableElement())
1529         return std::nullopt;
1530
1531     return VisibleSelection(endingSelection().start().previous(BackwardDeletion), endingSelection().end());
1532 }
1533
1534 // FIXME: Send an appropriate shouldDeleteRange call.
1535 bool CompositeEditCommand::breakOutOfEmptyListItem()
1536 {
1537     if (!shouldBreakOutOfEmptyListItem())
1538         return false;
1539
1540     auto emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
1541     auto listNode = emptyListItem->parentNode();
1542     auto style = EditingStyle::create(endingSelection().start());
1543     style->mergeTypingStyle(document());
1544
1545     RefPtr<Element> newBlock;
1546     if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
1547         if (is<HTMLLIElement>(*blockEnclosingList)) { // listNode is inside another list item
1548             if (visiblePositionAfterNode(*blockEnclosingList) == visiblePositionAfterNode(*listNode)) {
1549                 // If listNode appears at the end of the outer list item, then move listNode outside of this list item
1550                 // 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
1551                 // If listNode does NOT appear at the end, then we should consider it as a regular paragraph.
1552                 // 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
1553                 splitElement(downcast<HTMLLIElement>(*blockEnclosingList), *listNode);
1554                 removeNodePreservingChildren(*listNode->parentNode());
1555                 newBlock = HTMLLIElement::create(document());
1556             }
1557             // If listNode does NOT appear at the end of the outer list item, then behave as if in a regular paragraph.
1558         } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->hasTagName(ulTag))
1559             newBlock = HTMLLIElement::create(document());
1560     }
1561     if (!newBlock)
1562         newBlock = createDefaultParagraphElement(document());
1563
1564     RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTraversal::previousSibling(*emptyListItem): emptyListItem->previousSibling();
1565     RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversal::nextSibling(*emptyListItem): emptyListItem->nextSibling();
1566     if (isListItem(nextListNode.get()) || isListHTMLElement(nextListNode.get())) {
1567         // If emptyListItem follows another list item or nested list, split the list node.
1568         if (isListItem(previousListNode.get()) || isListHTMLElement(previousListNode.get()))
1569             splitElement(downcast<Element>(*listNode), *emptyListItem);
1570
1571         // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
1572         // Because we have splitted the element, emptyListItem is the first element in the list node.
1573         // i.e. insert newBlock before ul or ol whose first element is emptyListItem
1574         insertNodeBefore(*newBlock, *listNode);
1575         removeNode(*emptyListItem);
1576     } else {
1577         // When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
1578         // Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
1579         insertNodeAfter(*newBlock, *listNode);
1580         removeNode(isListItem(previousListNode.get()) || isListHTMLElement(previousListNode.get()) ? *emptyListItem : *listNode);
1581     }
1582
1583     appendBlockPlaceholder(*newBlock);
1584     setEndingSelection(VisibleSelection(firstPositionInNode(newBlock.get()), DOWNSTREAM, endingSelection().isDirectional()));
1585
1586     style->prepareToApplyAt(endingSelection().start());
1587     if (!style->isEmpty())
1588         applyStyle(style.ptr());
1589
1590     return true;
1591 }
1592
1593 // If the caret is in an empty quoted paragraph, and either there is nothing before that
1594 // paragraph, or what is before is unquoted, and the user presses delete, unquote that paragraph.
1595 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
1596 {
1597     if (!endingSelection().isCaret())
1598         return false;
1599         
1600     VisiblePosition caret(endingSelection().visibleStart());
1601     Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
1602     if (!highestBlockquote)
1603         return false;
1604
1605     if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret))
1606         return false;
1607
1608     VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
1609     // Only move forward if there's nothing before the caret, or if there's unquoted content before it.
1610     if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
1611         return false;
1612     
1613     auto br = HTMLBRElement::create(document());
1614     auto* brPtr = br.ptr();
1615     // We want to replace this quoted paragraph with an unquoted one, so insert a br
1616     // to hold the caret before the highest blockquote.
1617     insertNodeBefore(WTFMove(br), *highestBlockquote);
1618     VisiblePosition atBR(positionBeforeNode(brPtr));
1619     // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
1620     // a second one.
1621     if (!isStartOfParagraph(atBR))
1622         insertNodeBefore(HTMLBRElement::create(document()), *brPtr);
1623     setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
1624     
1625     // If this is an empty paragraph there must be a line break here.
1626     if (!lineBreakExistsAtVisiblePosition(caret))
1627         return false;
1628
1629     Position caretPos(caret.deepEquivalent().downstream());
1630     // A line break is either a br or a preserved newline.
1631     ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedNode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style().preserveNewline()));
1632     
1633     if (caretPos.deprecatedNode()->hasTagName(brTag))
1634         removeNodeAndPruneAncestors(*caretPos.deprecatedNode());
1635     else if (is<Text>(*caretPos.deprecatedNode())) {
1636         ASSERT(caretPos.deprecatedEditingOffset() == 0);
1637         Text& textNode = downcast<Text>(*caretPos.deprecatedNode());
1638         ContainerNode* parentNode = textNode.parentNode();
1639         // The preserved newline must be the first thing in the node, since otherwise the previous
1640         // paragraph would be quoted, and we verified that it wasn't above.
1641         deleteTextFromNode(textNode, 0, 1);
1642         prune(parentNode);
1643     }
1644
1645     return true;
1646 }
1647
1648 // Operations use this function to avoid inserting content into an anchor when at the start or the end of
1649 // that anchor, as in NSTextView.
1650 // FIXME: This is only an approximation of NSTextViews insertion behavior, which varies depending on how
1651 // the caret was made. 
1652 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Position& original)
1653 {
1654     if (original.isNull())
1655         return original;
1656         
1657     VisiblePosition visiblePos(original);
1658     Element* enclosingAnchor = enclosingAnchorElement(original);
1659     Position result = original;
1660
1661     if (!enclosingAnchor)
1662         return result;
1663
1664     // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
1665     if (enclosingAnchor && !isBlock(enclosingAnchor)) {
1666         VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
1667         VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
1668         // If visually just after the anchor, insert *inside* the anchor unless it's the last
1669         // VisiblePosition in the document, to match NSTextView.
1670         if (visiblePos == lastInAnchor) {
1671             // Make sure anchors are pushed down before avoiding them so that we don't
1672             // also avoid structural elements like lists and blocks (5142012).
1673             if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
1674                 pushAnchorElementDown(*enclosingAnchor);
1675                 enclosingAnchor = enclosingAnchorElement(original);
1676                 if (!enclosingAnchor)
1677                     return original;
1678             }
1679             // Don't insert outside an anchor if doing so would skip over a line break.  It would
1680             // probably be safe to move the line break so that we could still avoid the anchor here.
1681             Position downstream(visiblePos.deepEquivalent().downstream());
1682             if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
1683                 return original;
1684             
1685             result = positionInParentAfterNode(enclosingAnchor);
1686         }
1687         // If visually just before an anchor, insert *outside* the anchor unless it's the first
1688         // VisiblePosition in a paragraph, to match NSTextView.
1689         if (visiblePos == firstInAnchor) {
1690             // Make sure anchors are pushed down before avoiding them so that we don't
1691             // also avoid structural elements like lists and blocks (5142012).
1692             if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
1693                 pushAnchorElementDown(*enclosingAnchor);
1694                 enclosingAnchor = enclosingAnchorElement(original);
1695             }
1696             if (!enclosingAnchor)
1697                 return original;
1698
1699             result = positionInParentBeforeNode(enclosingAnchor);
1700         }
1701     }
1702         
1703     if (result.isNull() || !editableRootForPosition(result))
1704         result = original;
1705     
1706     return result;
1707 }
1708
1709 // Splits the tree parent by parent until we reach the specified ancestor. We use VisiblePositions
1710 // to determine if the split is necessary. Returns the last split node.
1711 RefPtr<Node> CompositeEditCommand::splitTreeToNode(Node& start, Node& end, bool shouldSplitAncestor)
1712 {
1713     ASSERT(&start != &end);
1714
1715     RefPtr<Node> adjustedEnd = &end;
1716     if (shouldSplitAncestor && adjustedEnd->parentNode())
1717         adjustedEnd = adjustedEnd->parentNode();
1718
1719     ASSERT(adjustedEnd);
1720     RefPtr<Node> node;
1721     for (node = &start; node && node->parentNode() != adjustedEnd; node = node->parentNode()) {
1722         if (!is<Element>(*node->parentNode()))
1723             break;
1724         // Do not split a node when doing so introduces an empty node.
1725         VisiblePosition positionInParent = firstPositionInNode(node->parentNode());
1726         VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get());
1727         if (positionInParent != positionInNode)
1728             splitElement(downcast<Element>(*node->parentNode()), *node);
1729     }
1730
1731     return node;
1732 }
1733
1734 Ref<Element> createBlockPlaceholderElement(Document& document)
1735 {
1736     return HTMLBRElement::create(document);
1737 }
1738
1739 } // namespace WebCore