15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/CompositeEditCommand.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h"
30df95704c49daea886ddad70775bda23618d6274dBen Murdoch#include "bindings/v8/ExceptionStatePlaceholder.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/DocumentFragment.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/DocumentMarkerController.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeTraversal.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Range.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ScopedEventQueue.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Text.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/AppendNodeCommand.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/ApplyStyleCommand.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/DeleteFromTextNodeCommand.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/DeleteSelectionCommand.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/Editor.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/InsertIntoTextNodeCommand.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/InsertLineBreakCommand.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/InsertNodeBeforeCommand.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/InsertParagraphSeparatorCommand.h"
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/MergeIdenticalElementsCommand.h"
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/RemoveCSSPropertyCommand.h"
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/RemoveNodeCommand.h"
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/RemoveNodePreservingChildrenCommand.h"
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/ReplaceNodeWithSpanCommand.h"
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/ReplaceSelectionCommand.h"
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/SetNodeAttributeCommand.h"
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/SplitElementCommand.h"
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/SplitTextNodeCommand.h"
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/SplitTextNodeContainingElementCommand.h"
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/TextIterator.h"
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisibleUnits.h"
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/WrapContentsInDummySpanCommand.h"
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/htmlediting.h"
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/markup.h"
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h"
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h"
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/InlineTextBox.h"
6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderBlock.h"
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderText.h"
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<EditCommandComposition> EditCommandComposition::create(Document* document,
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new EditCommandComposition(document, startingSelection, endingSelection, editAction));
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EditCommandComposition::EditCommandComposition(Document* document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction editAction)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_document(document)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_startingSelection(startingSelection)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_endingSelection(endingSelection)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_startingRootEditableElement(startingSelection.rootEditableElement())
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_endingRootEditableElement(endingSelection.rootEditableElement())
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_editAction(editAction)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::unapply()
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_document);
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    RefPtr<Frame> frame = m_document->frame();
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(frame);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if one is necessary (like for the creation of VisiblePositions).
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_document->updateLayoutIgnorePendingStylesheets();
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        size_t size = m_commands.size();
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (size_t i = size; i; --i)
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_commands[i - 1]->doUnapply();
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    frame->editor()->unappliedEditing(this);
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::reapply()
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_document);
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    RefPtr<Frame> frame = m_document->frame();
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(frame);
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if one is necessary (like for the creation of VisiblePositions).
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_document->updateLayoutIgnorePendingStylesheets();
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        size_t size = m_commands.size();
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (size_t i = 0; i != size; ++i)
124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_commands[i]->doReapply();
125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
12602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    frame->editor()->reappliedEditing(this);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::append(SimpleEditCommand* command)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_commands.append(command);
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::setStartingSelection(const VisibleSelection& selection)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startingSelection = selection;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startingRootEditableElement = selection.rootEditableElement();
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::setEndingSelection(const VisibleSelection& selection)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_endingSelection = selection;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_endingRootEditableElement = selection.rootEditableElement();
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EditCommandComposition::getNodesInCommand(HashSet<Node*>& nodes)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = m_commands.size();
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < size; ++i)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_commands[i]->getNodesInCommand(nodes);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void applyCommand(PassRefPtr<CompositeEditCommand> command)
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    command->apply();
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CompositeEditCommand::CompositeEditCommand(Document *document)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : EditCommand(document)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CompositeEditCommand::~CompositeEditCommand()
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isTopLevelCommand() || !m_composition);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::apply()
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!endingSelection().isContentRichlyEditable()) {
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (editingAction()) {
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionTyping:
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionPaste:
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionDrag:
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionSetWritingDirection:
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionCut:
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case EditActionUnspecified:
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT_NOT_REACHED();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ensureComposition();
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Changes to the document may have been made since the last editing operation that require a layout, as in <rdar://problem/5658603>.
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Low level operations, like RemoveNodeCommand, don't require a layout because the high level operations that use them perform one
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if one is necessary (like for the creation of VisiblePositions).
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(document());
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayoutIgnorePendingStylesheets();
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Frame* frame = document()->frame();
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(frame);
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EventQueueScope scope;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doApply();
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Only need to call appliedEditing for top-level commands,
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // and TypingCommands do it on their own (see TypingCommand::typingAddedToOpenCommand).
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isTypingCommand())
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        frame->editor()->appliedEditing(this);
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setShouldRetainAutocorrectionIndicator(false);
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EditCommandComposition* CompositeEditCommand::ensureComposition()
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CompositeEditCommand* command = this;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (command && command->parent())
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        command = command->parent();
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!command->m_composition)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        command->m_composition = EditCommandComposition::create(document(), startingSelection(), endingSelection(), editingAction());
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return command->m_composition.get();
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::isCreateLinkCommand() const
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::preservesTypingStyle() const
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::isTypingCommand() const
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::shouldRetainAutocorrectionIndicator() const
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::setShouldRetainAutocorrectionIndicator(bool)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// sugary-sweet convenience functions to help create and apply edit commands in composite commands
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::applyCommandToComposite(PassRefPtr<EditCommand> prpCommand)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<EditCommand> command = prpCommand;
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    command->setParent(this);
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    command->doApply();
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (command->isSimpleEditCommand()) {
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        command->setParent(0);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ensureComposition()->append(toSimpleEditCommand(command.get()));
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_commands.append(command.release());
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::applyCommandToComposite(PassRefPtr<CompositeEditCommand> command, const VisibleSelection& selection)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    command->setParent(this);
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selection != command->endingSelection()) {
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        command->setStartingSelection(selection);
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        command->setEndingSelection(selection);
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    command->doApply();
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_commands.append(command);
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::applyStyle(const EditingStyle* style, EditAction editingAction)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(ApplyStyleCommand::create(document(), style, editingAction));
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::applyStyle(const EditingStyle* style, const Position& start, const Position& end, EditAction editingAction)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(ApplyStyleCommand::create(document(), style, start, end, editingAction));
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::applyStyledElement(PassRefPtr<Element> element)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(ApplyStyleCommand::create(element, false));
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removeStyledElement(PassRefPtr<Element> element)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(ApplyStyleCommand::create(element, true));
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElement, bool pasteBlockqutoeIntoUnquotedArea)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea));
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertLineBreak()
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(InsertLineBreakCommand::create(document()));
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::isRemovableBlock(const Node* node)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node->hasTagName(divTag))
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* parentNode = node->parentNode();
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parentNode && parentNode->firstChild() != parentNode->lastChild())
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!toElement(node)->hasAttributes())
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!refChild->hasTagName(bodyTag));
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChild, shouldAssumeContentIsAlwaysEditable));
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRefPtr<Node> refChild)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(insertChild);
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(refChild);
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!refChild->hasTagName(bodyTag));
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ContainerNode* parent = refChild->parentNode();
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(parent);
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!parent->isShadowRoot());
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parent->lastChild() == refChild)
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        appendNode(insertChild, parent);
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(refChild->nextSibling());
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeBefore(insertChild, refChild->nextSibling());
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Position& editingPosition)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isEditablePosition(editingPosition));
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For editing positions like [table, 0], insert before the table,
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // likewise for replaced elements, brs, etc.
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position p = editingPosition.parentAnchoredEquivalent();
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* refChild = p.deprecatedNode();
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int offset = p.deprecatedEditingOffset();
34402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (canHaveChildrenForEditing(refChild)) {
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Node* child = refChild->firstChild();
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (int i = 0; child && i < offset; i++)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            child = child->nextSibling();
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            insertNodeBefore(insertChild, child);
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            appendNode(insertChild, toContainerNode(refChild));
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (caretMinOffset(refChild) >= offset)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeBefore(insertChild, refChild);
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) {
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        splitTextNode(toText(refChild), offset);
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Mutation events (bug 22634) from the text node insertion may have removed the refChild
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!refChild->inDocument())
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeBefore(insertChild, refChild);
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeAfter(insertChild, refChild);
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::appendNode(PassRefPtr<Node> node, PassRefPtr<ContainerNode> parent)
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(canHaveChildrenForEditing(parent.get()));
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(AppendNodeCommand::create(parent, node));
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removeChildrenInRange(PassRefPtr<Node> node, unsigned from, unsigned to)
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<RefPtr<Node> > children;
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* child = node->childNode(from);
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        children.append(child);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t size = children.size();
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < size; ++i)
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(children[i].release());
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node || !node->nonShadowBoundaryParentNode())
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentIsAlwaysEditable));
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, shouldAssumeContentIsAlwaysEditable));
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
396e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node, Node* excludeNode)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
398e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ASSERT(node.get() != excludeNode);
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<ContainerNode> parent = node->parentNode();
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    removeNode(node);
401e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    prune(parent.release(), excludeNode);
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtr<Element> prpNewParent)
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NodeVector nodesToRemove;
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> newParent = prpNewParent;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (; node && node != pastLastNodeToMove; node = node->nextSibling())
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nodesToRemove.append(node);
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < nodesToRemove.size(); i++) {
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(nodesToRemove[i]);
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        appendNode(nodesToRemove[i], newParent);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Position& position, Node* node)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ? position.offsetInContainerNode() : 0;
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updatePositionForNodeRemoval(position, node);
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (offset)
42302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        position.moveToOffset(offset);
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)HTMLElement* CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtr<HTMLElement> node)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // It would also be possible to implement all of ReplaceNodeWithSpanCommand
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // as a series of existing smaller edit commands.  Someone who wanted to
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // reduce the number of edit commands could do so here.
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::create(node);
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(command);
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Returning a raw pointer here is OK because the command is retained by
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // applyCommandToComposite (thus retaining the span), and the span is also
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // in the DOM tree, and thus alive whie it has a parent.
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(command->spanElement()->inDocument());
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return command->spanElement();
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
440e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid CompositeEditCommand::prune(PassRefPtr<Node> node, Node* excludeNode)
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
442e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (RefPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get(), excludeNode))
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(highestNodeToRemove.release());
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::splitTextNode(PassRefPtr<Text> node, unsigned offset)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(SplitTextNodeCommand::create(node, offset));
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<Node> atChild)
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(SplitElementCommand::create(element, atChild));
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::mergeIdenticalElements(PassRefPtr<Element> prpFirst, PassRefPtr<Element> prpSecond)
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> first = prpFirst;
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> second = prpSecond;
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!first->isDescendantOf(second.get()) && second != first);
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (first->nextSibling() != second) {
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(second);
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeAfter(second, first);
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtr<Element> element)
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(WrapContentsInDummySpanCommand::create(element));
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::splitTextNodeContainingElement(PassRefPtr<Text> text, unsigned offset)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(SplitTextNodeContainingElementCommand::create(text, offset));
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertTextIntoNode(PassRefPtr<Text> node, unsigned offset, const String& text)
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!text.isEmpty())
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, text));
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count)
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
48953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void CompositeEditCommand::replaceTextInNode(PassRefPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
49153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<Text> node(prpNode);
49253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, count));
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!replacementText.isEmpty())
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText));
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Position CompositeEditCommand::replaceSelectedTextInNode(const String& text)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position start = endingSelection().start();
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position end = endingSelection().end();
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start.containerNode() != end.containerNode() || !start.containerNode()->isTextNode() || isTabSpanTextNode(start.containerNode()))
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Position();
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Text> textNode = start.containerText();
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInContainerNode() - start.offsetInContainerNode(), text);
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Position(textNode.release(), start.offsetInContainerNode() + text.length());
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<DocumentMarker>& markers)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t arraySize = markerPointers.size();
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    markers.reserveCapacity(arraySize);
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < arraySize; ++i)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markers.append(*markerPointers[i]);
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::replaceTextInNodePreservingMarkers(PassRefPtr<Text> prpNode, unsigned offset, unsigned count, const String& replacementText)
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Text> node(prpNode);
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DocumentMarkerController* markerController = document()->markers();
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<DocumentMarker> markers;
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    copyMarkers(markerController->markersInRange(Range::create(document(), node, offset, node, offset + count).get(), DocumentMarker::AllMarkers()), markers);
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replaceTextInNode(node, offset, count, replacementText);
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Range> newRange = Range::create(document(), node, offset, node, offset + replacementText.length());
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < markers.size(); ++i)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markerController->addMarker(newRange.get(), markers[i].type(), markers[i].description());
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos)
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isTabSpanTextNode(pos.anchorNode()))
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return pos;
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (pos.anchorType()) {
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Position::PositionIsBeforeChildren:
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Position::PositionIsAfterChildren:
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return pos;
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Position::PositionIsOffsetInAnchor:
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Position::PositionIsBeforeAnchor:
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return positionInParentBeforeNode(pos.anchorNode());
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Position::PositionIsAfterAnchor:
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return positionInParentAfterNode(pos.anchorNode());
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* tabSpan = tabSpanNode(pos.containerNode());
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode()))
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return positionInParentBeforeNode(tabSpan);
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode()))
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return positionInParentAfterNode(tabSpan);
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInContainerNode());
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return positionInParentBeforeNode(tabSpan);
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::insertNodeAtTabSpanPosition(PassRefPtr<Node> node, const Position& pos)
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // insert node before, after, or at split of tab span
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    insertNodeAt(node, positionOutsideTabSpan(pos));
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (endingSelection().isRange())
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyCommandToComposite(DeleteSelectionCommand::create(document(), smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteSelection(const VisibleSelection &selection, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selection.isRange())
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyCommandToComposite(DeleteSelectionCommand::create(selection, smartDelete, mergeBlocksAfterDelete, replace, expandForSpecialElements, sanitizeMarkup));
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
578591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid CompositeEditCommand::removeCSSProperty(PassRefPtr<Element> element, CSSPropertyID property)
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(RemoveCSSPropertyCommand::create(document(), element, property));
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removeNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute)
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setNodeAttribute(element, attribute, AtomicString());
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::setNodeAttribute(PassRefPtr<Element> element, const QualifiedName& attribute, const AtomicString& value)
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(SetNodeAttributeCommand::create(element, attribute, value));
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool containsOnlyWhitespace(const String& text)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < text.length(); ++i) {
596591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!isWhitespace(text[i]))
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
59902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor(const String& text) const
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return containsOnlyWhitespace(text);
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::canRebalance(const Position& position) const
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* node = position.containerNode();
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (position.anchorType() != Position::PositionIsOffsetInAnchor || !node || !node->isTextNode())
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Text* textNode = toText(node);
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (textNode->length() == 0)
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = textNode->renderer();
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (renderer && !renderer->style()->collapseWhiteSpace())
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* node = position.containerNode();
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!canRebalance(position))
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int offset = position.deprecatedEditingOffset();
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String text = toText(node)->data();
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isWhitespace(text[offset])) {
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        offset--;
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (offset < 0 || !isWhitespace(text[offset]))
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerNode(), position.offsetInContainerNode());
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(PassRefPtr<Text> prpTextNode, int startOffset, int endOffset)
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Text> textNode = prpTextNode;
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String text = textNode->data();
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!text.isEmpty());
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int upstream = startOffset;
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (upstream > 0 && isWhitespace(text[upstream - 1]))
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        upstream--;
65502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int downstream = endOffset;
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]))
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        downstream++;
65902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int length = downstream - upstream;
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length)
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visibleUpstreamPos(Position(textNode, upstream));
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visibleDownstreamPos(Position(textNode, downstream));
66602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String string = text.substring(upstream, length);
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String rebalancedString = stringWithRebalancedWhitespace(string,
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 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
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
67102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                                                             isStartOfParagraph(visibleUpstreamPos) || upstream == 0,
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                             isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
67302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (string != rebalancedString)
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        replaceTextInNodePreservingMarkers(textNode.release(), upstream, length, rebalancedString);
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& position)
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* node = position.deprecatedNode();
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node || !node->isTextNode())
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
68302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    Text* textNode = toText(node);
68402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (textNode->length() == 0)
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = textNode->renderer();
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (renderer && !renderer->style()->collapseWhiteSpace())
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position upstreamPos = position.upstream();
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteInsignificantText(position.upstream(), position.downstream());
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    position = upstreamPos.downstream();
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visiblePos(position);
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition previousVisiblePos(visiblePos.previous());
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position previous(previousVisiblePos.deepEquivalent());
69902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isCollapsibleWhitespace(previousVisiblePos.characterAfter()) && previous.deprecatedNode()->isTextNode() && !previous.deprecatedNode()->hasTagName(brTag))
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        replaceTextInNodePreservingMarkers(toText(previous.deprecatedNode()), previous.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isCollapsibleWhitespace(visiblePos.characterAfter()) && position.deprecatedNode()->isTextNode() && !position.deprecatedNode()->hasTagName(brTag))
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        replaceTextInNodePreservingMarkers(toText(position.deprecatedNode()), position.deprecatedEditingOffset(), 1, nonBreakingSpaceString());
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::rebalanceWhitespace()
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisibleSelection selection = endingSelection();
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selection.isNone())
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
71102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rebalanceWhitespaceAt(selection.start());
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selection.isRange())
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rebalanceWhitespaceAt(selection.end());
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, unsigned start, unsigned end)
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!textNode || start >= end)
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayout();
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderText* textRenderer = toRenderText(textNode->renderer());
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!textRenderer)
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<InlineTextBox*> sortedTextBoxes;
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t sortedTextBoxesPosition = 0;
73002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox())
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sortedTextBoxes.append(textBox);
73302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If there is mixed directionality text, the boxes can be out of order,
73502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // (like Arabic with embedded LTR), so sort them first.
73602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    if (textRenderer->containsReversedText())
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart);
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedTextBoxesPosition];
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!box) {
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // whole text node is empty
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(textNode);
74302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        return;
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
74502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = textNode->length();
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start >= length || end > length)
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned removed = 0;
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineTextBox* prevBox = 0;
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String str;
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This loop structure works to process all gaps preceding a box,
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // and also will look at the gap after the last box.
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (prevBox || box) {
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0;
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (end < gapStart)
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // No more chance for any intersections
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned gapEnd = box ? box->start() : length;
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool indicesIntersect = start <= gapEnd && end >= gapStart;
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int gapLen = gapEnd - gapStart;
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (indicesIntersect && gapLen > 0) {
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gapStart = max(gapStart, start);
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gapEnd = min(gapEnd, end);
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (str.isNull())
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                str = textNode->data().substring(start, end - start);
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // remove text in the gap
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            str.remove(gapStart - start - removed, gapLen);
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            removed += gapLen;
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
77402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        prevBox = box;
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (box) {
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (++sortedTextBoxesPosition < sortedTextBoxes.size())
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                box = sortedTextBoxes[sortedTextBoxesPosition];
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                box = 0;
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!str.isNull()) {
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Replace the text between start and end with our pruned version.
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!str.isEmpty())
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            replaceTextInNode(textNode, start, end - start, str);
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Assert that we are not going to delete all of the text in the node.
79002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch            // If we were, that should have been done above with the call to
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // removeNode and return.
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(start > 0 || end - start < textNode->length());
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            deleteTextFromNode(textNode, start, end - start);
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteInsignificantText(const Position& start, const Position& end)
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start.isNull() || end.isNull())
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (comparePositions(start, end) >= 0)
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<RefPtr<Text> > nodes;
807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (Node* node = start.deprecatedNode(); node; node = NodeTraversal::next(node)) {
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (node->isTextNode())
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            nodes.append(toText(node));
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (node == end.deprecatedNode())
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < nodes.size(); ++i) {
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Text* textNode = nodes[i].get();
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int startOffset = textNode == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0;
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int endOffset = textNode == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length());
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        deleteInsignificantText(textNode, startOffset, endOffset);
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos)
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivalent().downstream();
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteInsignificantText(pos, end);
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element> container)
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!container)
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayoutIgnorePendingStylesheets();
83402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Should assert isBlockFlow || isInlineFlow when deletion improves. See 4244964.
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(container->renderer());
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    appendNode(placeholder, container);
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return placeholder.release();
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& pos)
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos.isNull())
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Should assert isBlockFlow || isInlineFlow when deletion improves.  See 4244964.
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(pos.deprecatedNode()->renderer());
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> placeholder = createBlockPlaceholderElement(document());
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    insertNodeAt(placeholder, pos);
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return placeholder.release();
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* container)
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!container)
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayoutIgnorePendingStylesheets();
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = container->renderer();
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer || !renderer->isBlockFlow())
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
86602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // append the placeholder to make sure it follows
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // any unrendered blocks
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderBlock* block = toRenderBlock(renderer);
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (block->height() == 0 || (block->isListItem() && block->isEmpty()))
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return appendBlockPlaceholder(container);
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Assumes that the position is at a placeholder and does the removal without much checking.
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::removePlaceholderAt(const Position& p)
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(lineBreakExistsAtPosition(p));
88002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We are certain that the position is at a line break, but it may be a br or a preserved newline.
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (p.anchorNode()->hasTagName(brTag)) {
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(p.anchorNode());
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
88602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1);
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> paragraphElement = createDefaultParagraphElement(document());
8931fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    paragraphElement->appendChild(createBreakElement(document()), IGNORE_EXCEPTION);
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    insertNodeAt(paragraphElement, position);
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return paragraphElement.release();
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
89802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// If the paragraph is not entirely within it's own block, create one and move the paragraph into
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// it, and return that block.  Otherwise return 0.
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessary(const Position& pos)
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pos.isNull())
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
90402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->updateLayoutIgnorePendingStylesheets();
90602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // It's strange that this function is responsible for verifying that pos has not been invalidated
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // by an earlier call to this function.  The caller, applyBlockStyle, should do this.
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY);
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos));
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos);
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition next = visibleParagraphEnd.next();
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd;
91402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream();
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position upstreamEnd = visibleEnd.deepEquivalent().upstream();
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // If there are no VisiblePositions in the same block as pos then
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // upstreamStart will be outside the paragraph
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (comparePositions(pos, upstreamStart) < 0)
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Perform some checks to see if we need to perform work in this function.
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isBlock(upstreamStart.deprecatedNode())) {
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the block is the root editable element, always move content to a new block,
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // since it is illegal to modify attributes on the root editable element for editing.
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamStart)) {
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // If the block is the root editable element and it contains no visible content, create a new
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // block but don't try and move content into it, since there's nothing for moveParagraphs to move.
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstreamStart.deprecatedNode()->renderer()))
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return insertNewDefaultParagraphElementAt(upstreamStart);
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (isBlock(upstreamEnd.deprecatedNode())) {
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.deprecatedNode())) {
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // If the paragraph end is a descendant of paragraph start, then we need to run
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // the rest of this function. If not, we can bail here.
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return 0;
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart.deprecatedNode()) {
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // The visibleEnd.  It must be an ancestor of the paragraph start.
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We can bail as we have a full block to work with.
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock(upstreamEnd.deprecatedNode())));
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // At the end of the editable region. We can bail here as well.
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTagName(brTag);
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(firstPositionInNode(newBlock.get())));
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !endWasBr)
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(newBlock->lastChild());
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newBlock.release();
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::pushAnchorElementDown(Node* anchorNode)
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!anchorNode)
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
96502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(anchorNode->isLink());
96702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection::selectionFromContentsOfNode(anchorNode));
969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    applyStyledElement(toElement(anchorNode));
9705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Clones of anchorNode have been pushed down, now remove it.
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (anchorNode->inDocument())
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNodePreservingChildren(anchorNode);
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Clone the paragraph between start and end under blockElement,
97602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// preserving the hierarchy up to outerNode.
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Position& end, Node* passedOuterNode, Element* blockElement)
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // First we clone the outerNode
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> lastNode;
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> outerNode = passedOuterNode;
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (outerNode->isRootEditableElement()) {
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastNode = blockElement;
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastNode = outerNode->cloneNode(isTableElement(outerNode.get()));
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        appendNode(lastNode, blockElement);
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) {
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Vector<RefPtr<Node> > ancestors;
99302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Insert each node from innerNode to outerNode (excluded) in a list.
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (Node* n = start.deprecatedNode(); n && n != outerNode; n = n->parentNode())
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ancestors.append(n);
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Clone every node between start.deprecatedNode() and outerBlock.
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (size_t i = ancestors.size(); i != 0; --i) {
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            Node* item = ancestors[i - 1].get();
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RefPtr<Node> child = item->cloneNode(isTableElement(item));
1003591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            appendNode(child, toElement(lastNode.get()));
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            lastNode = child.release();
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Handle the case of paragraphs with more than one node,
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // cloning all the siblings until end.deprecatedNode() is reached.
101002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) {
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If end is not a descendant of outerNode we need to
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // find the first common ancestor to increase the scope
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // of our nextSibling traversal.
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (!end.deprecatedNode()->isDescendantOf(outerNode.get())) {
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            outerNode = outerNode->parentNode();
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
101953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        RefPtr<Node> startNode = start.deprecatedNode();
102053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for (RefPtr<Node> node = NodeTraversal::nextSkippingChildren(startNode.get(), outerNode.get()); node; node = NodeTraversal::nextSkippingChildren(node.get(), outerNode.get())) {
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Move lastNode up in the tree as much as node was moved up in the
1022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            // tree by NodeTraversal::nextSkippingChildren, so that the relative depth between
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // node and the original start node is maintained in the clone.
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (startNode->parentNode() != node->parentNode()) {
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                startNode = startNode->parentNode();
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                lastNode = lastNode->parentNode();
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RefPtr<Node> clonedNode = node->cloneNode(true);
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            insertNodeAfter(clonedNode, lastNode);
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            lastNode = clonedNode.release();
103253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (node == end.deprecatedNode() || end.deprecatedNode()->isDescendantOf(node.get()))
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
103802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// There are bugs in deletion when it removes a fully selected table/list.
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// It expands and removes the entire table/list, but will let content
104102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// before and after the table/list collapse onto one line.
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Deleting a paragraph will leave a placeholder. Remove it (and prune
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// empty or unrendered parents).
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination)
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition caretAfterDelete = endingSelection().visibleStart();
1048e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    Node* destinationNode = destination.deepEquivalent().anchorNode();
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) {
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Note: We want the rightmost candidate.
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Position position = caretAfterDelete.deepEquivalent().downstream();
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Node* node = position.deprecatedNode();
10530019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch
10540019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        // Bail if we'd remove an ancestor of our destination.
10550019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        if (destinationNode->isDescendantOf(node))
10560019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            return;
10570019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Normally deletion will leave a br as a placeholder.
10590019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        if (node->hasTagName(brTag)) {
1060e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            removeNodeAndPruneAncestors(node, destinationNode);
10610019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch
10620019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            // If the selection to move was empty and in an empty block that
10630019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            // doesn't require a placeholder to prop itself open (like a bordered
10640019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            // div or an li), remove it during the move (the list removal code
10650019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            // expects this behavior).
10660019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        } else if (isBlock(node)) {
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // If caret position after deletion and destination position coincides,
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // node should not be removed.
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!position.rendersInDifferentPosition(destination.deepEquivalent())) {
1070e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                prune(node, destinationNode);
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1073e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            removeNodeAndPruneAncestors(node, destinationNode);
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (lineBreakExistsAtPosition(position)) {
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // There is a preserved '\n' at caretAfterDelete.
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We can safely assume this is a text node.
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            Text* textNode = toText(node);
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (textNode->length() == 1)
1080e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                removeNodeAndPruneAncestors(node, destinationNode);
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                deleteTextFromNode(textNode, position.deprecatedEditingOffset(), 1);
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
108602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This is a version of moveParagraph that preserves style by keeping the original markup
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// It is currently used only by IndentOutdentCommand but it is meant to be used in the
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// future by several other commands such as InsertList and the align commands.
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The blockElement parameter is the element to move the paragraph to,
109102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// outerNode is the top element of the paragraph hierarchy.
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CompositeEditCommand::moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, Element* blockElement, Node* outerNode)
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(outerNode);
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(blockElement);
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition beforeParagraph = startOfParagraphToMove.previous();
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition afterParagraph(endOfParagraphToMove.next());
110002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position start = startOfParagraphToMove.deepEquivalent().downstream();
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position end = endOfParagraphToMove.deepEquivalent().upstream();
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cloneParagraphUnderNewElement(start, end, outerNode, blockElement);
110702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteSelection(false, false, false, false);
111002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are bugs in deletion when it removes a fully selected table/list.
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // It expands and removes the entire table/list, but will let content
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // before and after the table/list collapse onto one line.
111402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cleanupAfterDeletion();
111602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Add a br if pruning an empty block level element caused a collapse.  For example:
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // foo^
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // <div>bar</div>
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // baz
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Imagine moving 'bar' to ^.  'bar' will be deleted and its div pruned.  That would
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Must recononicalize these two VisiblePositions after the pruning above.
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquivalent().deprecatedNode())
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforeParagraph)) || beforeParagraph == afterParagraph)) {
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
113353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
113453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor)
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isStartOfParagraph(startOfParagraphToMove));
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isEndOfParagraph(endOfParagraphToMove));
113853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, preserveSelection, preserveStyle, constrainingAncestor);
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
114153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& destination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor)
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startOfParagraphToMove == destination)
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
114502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int startIndex = -1;
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int endIndex = -1;
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int destinationIndex = -1;
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool originalIsDirectional = endingSelection().isDirectional();
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (preserveSelection && !endingSelection().isNone()) {
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition visibleStart = endingSelection().visibleStart();
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition visibleEnd = endingSelection().visibleEnd();
115302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool startAfterParagraph = comparePositions(visibleStart, endOfParagraphToMove) > 0;
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool endBeforeParagraph = comparePositions(visibleEnd, startOfParagraphToMove) < 0;
115602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!startAfterParagraph && !endBeforeParagraph) {
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bool startInParagraph = comparePositions(visibleStart, startOfParagraphToMove) >= 0;
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bool endInParagraph = comparePositions(visibleEnd, endOfParagraphToMove) <= 0;
116002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            startIndex = 0;
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (startInParagraph) {
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RefPtr<Range> startRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquivalent().parentAnchoredEquivalent());
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                startIndex = TextIterator::rangeLength(startRange.get(), true);
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            endIndex = 0;
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (endInParagraph) {
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RefPtr<Range> endRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                endIndex = TextIterator::rangeLength(endRange.get(), true);
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
117402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition beforeParagraph = startOfParagraphToMove.previous(CannotCrossEditingBoundary);
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition afterParagraph(endOfParagraphToMove.next(CannotCrossEditingBoundary));
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We upstream() the end and downstream() the start so that we don't include collapsed whitespace in the move.
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // When we paste a fragment, spaces after the end and before the start are treated as though they were rendered.
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position start = startOfParagraphToMove.deepEquivalent().downstream();
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position end = endOfParagraphToMove.deepEquivalent().upstream();
118202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // start and end can't be used directly to create a Range; they are "editing positions"
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position startRangeCompliant = start.parentAnchoredEquivalent();
11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position endRangeCompliant = end.parentAnchoredEquivalent();
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecatedNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.deprecatedNode(), endRangeCompliant.deprecatedEditingOffset());
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: This is an inefficient way to preserve style on nodes in the paragraph to move. It
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // shouldn't matter though, since moved paragraphs will usually be quite small.
119053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraphToMove ?
119153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotAnnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : 0;
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
119302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // A non-empty paragraph's style is moved when we copy and move it.  We don't move
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // anything if we're given an empty paragraph, but an empty paragraph can have style
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // too, <div><b><br></b></div> for example.  Save it so that we can preserve it later.
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<EditingStyle> styleInEmptyParagraph;
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) {
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deepEquivalent());
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        styleInEmptyParagraph->mergeTypingStyle(document());
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The moved paragraph should assume the block style of the destination.
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        styleInEmptyParagraph->removeBlockProperties();
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
120302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME (5098931): We should add a new insert action "WebViewInsertActionMoved" and call shouldInsertFragment here.
120502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection(start, end, DOWNSTREAM));
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->frame()->editor()->clearMisspellingsAndBadGrammar(endingSelection());
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    deleteSelection(false, false, false, false);
12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(destination.deepEquivalent().anchorNode()->inDocument());
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cleanupAfterDeletion(destination);
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(destination.deepEquivalent().anchorNode()->inDocument());
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Add a br if pruning an empty block level element caused a collapse. For example:
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // foo^
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // <div>bar</div>
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // baz
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That would
12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br.
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Must recononicalize these two VisiblePositions after the pruning above.
12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || beforeParagraph == afterParagraph)) {
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Trim text between beforeParagraph and afterParagraph if they aren't equal.
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquivalent());
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Need an updateLayout here in case inserting the br has split a text node.
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        document()->updateLayoutIgnorePendingStylesheets();
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document()->documentElement()), destination.deepEquivalent().parentAnchoredEquivalent()));
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection(destination, originalIsDirectional));
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(endingSelection().isCaretOrRange());
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MovingParagraph;
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!preserveStyle)
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        options |= ReplaceSelectionCommand::MatchStyle;
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyCommandToComposite(ReplaceSelectionCommand::create(document(), fragment, options));
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document()->frame()->editor()->markMisspellingsAndBadGrammar(endingSelection());
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the selection is in an empty paragraph, restore styles from the old empty paragraph to the new empty paragraph.
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool selectionIsEmptyParagraph = endingSelection().isCaret() && isStartOfParagraph(endingSelection().visibleStart()) && isEndOfParagraph(endingSelection().visibleStart());
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (styleInEmptyParagraph && selectionIsEmptyParagraph)
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyStyle(styleInEmptyParagraph.get());
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (preserveSelection && startIndex != -1) {
12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Fragment creation (using createMarkup) incorrectly uses regular
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // spaces instead of nbsps for some spaces that were rendered (11475), which
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // causes spaces to be collapsed during the move operation.  This results
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // in a call to rangeFromLocationAndLength with a location past the end
12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // of the document (which will return null).
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<Range> start = TextIterator::rangeFromLocationAndLength(document()->documentElement(), destinationIndex + startIndex, 0, true);
12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<Range> end = TextIterator::rangeFromLocationAndLength(document()->documentElement(), destinationIndex + endIndex, 0, true);
12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (start && end)
12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setEndingSelection(VisibleSelection(start->startPosition(), end->startPosition(), DOWNSTREAM, originalIsDirectional));
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Send an appropriate shouldDeleteRange call.
12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::breakOutOfEmptyListItem()
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!emptyListItem)
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start());
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    style->mergeTypingStyle(document());
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<ContainerNode> listNode = emptyListItem->parentNode();
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Can't we do something better when the immediate parent wasn't a list node?
12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!listNode
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
12745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || !listNode->rendererIsEditable()
12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || listNode == emptyListItem->rootEditableElement())
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> newBlock = 0;
12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside another list item
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionAfterNode(listNode.get())) {
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // If listNode appears at the end of the outer list item, then move listNode outside of this list item
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // 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
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // If listNode does NOT appear at the end, then we should consider it as a regular paragraph.
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // 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
1286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                splitElement(toElement(blockEnclosingList), listNode);
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                removeNodePreservingChildren(listNode->parentNode());
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                newBlock = createListItemElement(document());
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // If listNode does NOT appear at the end of the outer list item, then behave as if in a regular paragraph.
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->hasTagName(ulTag))
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            newBlock = createListItemElement(document());
12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!newBlock)
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newBlock = createDefaultParagraphElement(document());
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(emptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling();
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(emptyListItem.get())->nextElementSibling(): emptyListItem->nextSibling();
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) {
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If emptyListItem follows another list item or nested list, split the list node.
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isListItem(previousListNode.get()) || isListElement(previousListNode.get()))
1302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            splitElement(toElement(listNode.get()), emptyListItem);
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Because we have splitted the element, emptyListItem is the first element in the list node.
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // i.e. insert newBlock before ul or ol whose first element is emptyListItem
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeBefore(newBlock, listNode);
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(emptyListItem);
13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeAfter(newBlock, listNode);
13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNode(isListItem(previousListNode.get()) || isListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get());
13145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    appendBlockPlaceholder(newBlock);
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection(firstPositionInNode(newBlock.get()), DOWNSTREAM, endingSelection().isDirectional()));
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    style->prepareToApplyAt(endingSelection().start());
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!style->isEmpty())
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        applyStyle(style.get());
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// If the caret is in an empty quoted paragraph, and either there is nothing before that
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// paragraph, or what is before is unquoted, and the user presses delete, unquote that paragraph.
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!endingSelection().isCaret())
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
133202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition caret(endingSelection().visibleStart());
13345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!highestBlockquote)
13365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
133702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret))
13395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
134002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
13425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Only move forward if there's nothing before the caret, or if there's unquoted content before it.
13435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
13445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
134502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> br = createBreakElement(document());
13475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to replace this quoted paragraph with an unquoted one, so insert a br
13485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // to hold the caret before the highest blockquote.
13495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    insertNodeBefore(br, highestBlockquote);
13505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition atBR(positionBeforeNode(br.get()));
13515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
13525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // a second one.
13535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isStartOfParagraph(atBR))
13545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        insertNodeBefore(createBreakElement(document()), br);
13555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
135602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If this is an empty paragraph there must be a line break here.
13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lineBreakExistsAtVisiblePosition(caret))
13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position caretPos(caret.deepEquivalent().downstream());
13625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // A line break is either a br or a preserved newline.
13635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedNode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveNewline()));
136402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (caretPos.deprecatedNode()->hasTagName(brTag))
13665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeNodeAndPruneAncestors(caretPos.deprecatedNode());
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (caretPos.deprecatedNode()->isTextNode()) {
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(caretPos.deprecatedEditingOffset() == 0);
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Text* textNode = toText(caretPos.deprecatedNode());
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ContainerNode* parentNode = textNode->parentNode();
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The preserved newline must be the first thing in the node, since otherwise the previous
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // paragraph would be quoted, and we verified that it wasn't above.
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        deleteTextFromNode(textNode, 0, 1);
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        prune(parentNode);
13755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
13785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Operations use this function to avoid inserting content into an anchor when at the start or the end of
13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// that anchor, as in NSTextView.
13825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: This is only an approximation of NSTextViews insertion behavior, which varies depending on how
138302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// the caret was made.
13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Position& original)
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (original.isNull())
13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return original;
138802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VisiblePosition visiblePos(original);
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* enclosingAnchor = enclosingAnchorElement(original);
13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Position result = original;
13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!enclosingAnchor)
13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (enclosingAnchor && !isBlock(enclosingAnchor)) {
13985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If visually just after the anchor, insert *inside* the anchor unless it's the last
14015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // VisiblePosition in the document, to match NSTextView.
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (visiblePos == lastInAnchor) {
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Make sure anchors are pushed down before avoiding them so that we don't
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // also avoid structural elements like lists and blocks (5142012).
14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                pushAnchorElementDown(enclosingAnchor);
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                enclosingAnchor = enclosingAnchorElement(original);
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!enclosingAnchor)
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return original;
14105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Don't insert outside an anchor if doing so would skip over a line break.  It would
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // probably be safe to move the line break so that we could still avoid the anchor here.
14135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            Position downstream(visiblePos.deepEquivalent().downstream());
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return original;
141602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result = positionInParentAfterNode(enclosingAnchor);
14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If visually just before an anchor, insert *outside* the anchor unless it's the first
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // VisiblePosition in a paragraph, to match NSTextView.
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (visiblePos == firstInAnchor) {
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Make sure anchors are pushed down before avoiding them so that we don't
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // also avoid structural elements like lists and blocks (5142012).
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (original.deprecatedNode() != enclosingAnchor && original.deprecatedNode()->parentNode() != enclosingAnchor) {
14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                pushAnchorElementDown(enclosingAnchor);
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                enclosingAnchor = enclosingAnchorElement(original);
14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!enclosingAnchor)
14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return original;
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result = positionInParentBeforeNode(enclosingAnchor);
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
143402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result.isNull() || !editableRootForPosition(result))
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = original;
143702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Splits the tree parent by parent until we reach the specified ancestor. We use VisiblePositions
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// to determine if the split is necessary. Returns the last split node.
14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Node> CompositeEditCommand::splitTreeToNode(Node* start, Node* end, bool shouldSplitAncestor)
14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(start);
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(end);
14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(start != end);
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> node;
14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (shouldSplitAncestor && end->parentNode())
14515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        end = end->parentNode();
14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Node> endNode = end;
14545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (node = start; node && node->parentNode() != endNode; node = node->parentNode()) {
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!node->parentNode()->isElementNode())
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do not split a node when doing so introduces an empty node.
14585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition positionInParent = firstPositionInNode(node->parentNode());
14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get());
14605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (positionInParent != positionInNode)
1461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            splitElement(toElement(node->parentNode()), node);
14625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return node.release();
14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Element> createBlockPlaceholderElement(Document* document)
14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
14695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Element> breakNode = document->createElement(brTag, false);
14705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return breakNode.release();
14715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
1474