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