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