15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2006 Apple Computer, 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 2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * 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/InsertParagraphSeparatorCommand.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeTraversal.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Text.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/EditingStyle.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/InsertLineBreakCommand.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisibleUnits.h" 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/htmlediting.h" 37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/html/HTMLBRElement.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h" 39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/html/HTMLQuoteElement.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderObject.h" 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/rendering/RenderText.h" 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// When inserting a new line, we want to avoid nesting empty divs if we can. Otherwise, when 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// pasting, it's easy to have each new line be a div deeper than the previous. E.g., in the case 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// below, we want to insert at ^ instead of |. 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// <div>foo<div>bar</div>|</div>^ 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static Element* highestVisuallyEquivalentDivBelowRoot(Element* startBlock) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Element* curBlock = startBlock; 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We don't want to return a root node (if it happens to be a div, e.g., in a document fragment) because there are no 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // siblings for us to append to. 56d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) while (!curBlock->nextSibling() && isHTMLDivElement(*curBlock->parentElement()) && curBlock->parentElement()->parentElement()) { 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curBlock->parentElement()->hasAttributes()) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) curBlock = curBlock->parentElement(); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return curBlock; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 64c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand(Document& document, bool mustUseDefaultParagraphElement, bool pasteBlockquoteIntoUnquotedArea) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : CompositeEditCommand(document) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_mustUseDefaultParagraphElement(mustUseDefaultParagraphElement) 67c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_pasteBlockquoteIntoUnquotedArea(pasteBlockquoteIntoUnquotedArea) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool InsertParagraphSeparatorCommand::preservesTypingStyle() const 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Position &pos) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // It is only important to set a style to apply later if we're at the boundaries of 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // a paragraph. Otherwise, content that is moved as part of the work of the command 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will lend their styles to the new paragraph without any extra work needed. 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isStartOfParagraph(visiblePos) && !isEndOfParagraph(visiblePos)) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(pos.isNotNull()); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_style = EditingStyle::create(pos); 878abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) m_style->mergeTypingStyle(pos.document()); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 90c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Element* originalEnclosingBlock) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Not only do we break out of header tags, but we also do not preserve the typing style, 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // in order to match other browsers. 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (originalEnclosingBlock->hasTagName(h1Tag) || 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) originalEnclosingBlock->hasTagName(h2Tag) || 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) originalEnclosingBlock->hasTagName(h3Tag) || 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) originalEnclosingBlock->hasTagName(h4Tag) || 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) originalEnclosingBlock->hasTagName(h5Tag)) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_style) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_style->prepareToApplyAt(endingSelection().start()); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_style->isEmpty()) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) applyStyle(m_style.get()); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool InsertParagraphSeparatorCommand::shouldUseDefaultParagraphElement(Element* enclosingBlock) const 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_mustUseDefaultParagraphElement) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 11302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Assumes that if there was a range selection, it was already deleted. 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isEndOfBlock(endingSelection().visibleStart())) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return enclosingBlock->hasTagName(h1Tag) || 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enclosingBlock->hasTagName(h2Tag) || 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enclosingBlock->hasTagName(h3Tag) || 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enclosingBlock->hasTagName(h4Tag) || 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enclosingBlock->hasTagName(h5Tag); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 125f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void InsertParagraphSeparatorCommand::getAncestorsInsideBlock(const Node* insertionNode, Element* outerBlock, WillBeHeapVector<RefPtrWillBeMember<Element> >& ancestors) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ancestors.clear(); 12802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Build up list of ancestors elements between the insertion node and the outer block. 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (insertionNode != outerBlock) { 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Element* n = insertionNode->parentElement(); n && n != outerBlock; n = n->parentElement()) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ancestors.append(n); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 136f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)PassRefPtrWillBeRawPtr<Element> InsertParagraphSeparatorCommand::cloneHierarchyUnderNewBlock(const WillBeHeapVector<RefPtrWillBeMember<Element> >& ancestors, PassRefPtrWillBeRawPtr<Element> blockToInsert) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make clones of ancestors in between the start node and the start block. 139f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> parent = blockToInsert; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t i = ancestors.size(); i != 0; --i) { 141f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> child = ancestors[i - 1]->cloneElementWithoutChildren(); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // It should always be okay to remove id from the cloned elements, since the originals are not deleted. 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) child->removeAttribute(idAttr); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(child, parent); 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) parent = child.release(); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return parent.release(); 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void InsertParagraphSeparatorCommand::doApply() 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!endingSelection().isNonOrphanedCaretOrRange()) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 15502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position insertionPosition = endingSelection().start(); 15702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EAffinity affinity = endingSelection().affinity(); 15902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Delete the current selection. 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (endingSelection().isRange()) { 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) calculateStyleBeforeInsertion(insertionPosition); 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deleteSelection(false, true); 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = endingSelection().start(); 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) affinity = endingSelection().affinity(); 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: The parentAnchoredEquivalent conversion needs to be moved into enclosingBlock. 169f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> startBlock = enclosingBlock(insertionPosition.parentAnchoredEquivalent().containerNode()); 17006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) Node* listChildNode = enclosingListChild(insertionPosition.parentAnchoredEquivalent().containerNode()); 171c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) RefPtrWillBeRawPtr<HTMLElement> listChild = listChildNode && listChildNode->isHTMLElement() ? toHTMLElement(listChildNode) : 0; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position canonicalPos = VisiblePosition(insertionPosition).deepEquivalent(); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!startBlock 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || !startBlock->nonShadowBoundaryParentNode() 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || isTableCell(startBlock.get()) 176d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) || isHTMLFormElement(*startBlock) 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: If the node is hidden, we don't have a canonical position so we will do the wrong thing for tables and <hr>. https://bugs.webkit.org/show_bug.cgi?id=40342 178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) || (!canonicalPos.isNull() && isRenderedTableElement(canonicalPos.deprecatedNode())) 179d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) || (!canonicalPos.isNull() && isHTMLHRElement(*canonicalPos.deprecatedNode()))) { 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) applyCommandToComposite(InsertLineBreakCommand::create(document())); 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Use the leftmost candidate. 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = insertionPosition.upstream(); 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!insertionPosition.isCandidate()) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = insertionPosition.downstream(); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Adjust the insertion position after the delete 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = positionAvoidingSpecialElementBoundary(insertionPosition); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition visiblePos(insertionPosition, affinity); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) calculateStyleBeforeInsertion(insertionPosition); 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //--------------------------------------------------------------------- 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle special case of typing return on an empty list item 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (breakOutOfEmptyListItem()) 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //--------------------------------------------------------------------- 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Prepare for more general cases. 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isFirstInBlock = isStartOfBlock(visiblePos); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isLastInBlock = isEndOfBlock(visiblePos); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool nestNewBlock = false; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Create block to be inserted. 207f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> blockToInsert = nullptr; 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (startBlock->isRootEditableElement()) { 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blockToInsert = createDefaultParagraphElement(document()); 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) nestNewBlock = true; 2118abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) } else if (shouldUseDefaultParagraphElement(startBlock.get())) { 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blockToInsert = createDefaultParagraphElement(document()); 2138abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) } else { 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blockToInsert = startBlock->cloneElementWithoutChildren(); 2158abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) } 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //--------------------------------------------------------------------- 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle case when position is in the last visible position in its block, 21902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // including when the block is empty. 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isLastInBlock) { 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (nestNewBlock) { 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isFirstInBlock && !lineBreakExistsAtVisiblePosition(visiblePos)) { 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The block is empty. Create an empty block to 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // represent the paragraph that we're leaving. 225c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) RefPtrWillBeRawPtr<HTMLElement> extraBlock = createDefaultParagraphElement(document()); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(extraBlock, startBlock); 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendBlockPlaceholder(extraBlock); 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(blockToInsert, startBlock); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can get here if we pasted a copied portion of a blockquote with a newline at the end and are trying to paste it 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // into an unquoted area. We then don't want the newline within the blockquote or else it will also be quoted. 233c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_pasteBlockquoteIntoUnquotedArea) { 234c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (HTMLQuoteElement* highestBlockquote = toHTMLQuoteElement(highestEnclosingNodeOfType(canonicalPos, &isMailHTMLBlockquoteElement))) 235c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) startBlock = highestBlockquote; 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (listChild && listChild != startBlock) { 239f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> listChildToInsert = listChild->cloneElementWithoutChildren(); 24006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) appendNode(blockToInsert, listChildToInsert.get()); 24106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) insertNodeAfter(listChildToInsert.get(), listChild); 24206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else { 24306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // Most of the time we want to stay at the nesting level of the startBlock (e.g., when nesting within lists). However, 24406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // for div nodes, this can result in nested div tags that are hard to break out of. 245c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) Element* siblingElement = startBlock.get(); 246d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (isHTMLDivElement(*blockToInsert)) 247c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) siblingElement = highestVisuallyEquivalentDivBelowRoot(startBlock.get()); 248c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) insertNodeAfter(blockToInsert, siblingElement); 24906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Recreate the same structure in the new paragraph. 25302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 254f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) WillBeHeapVector<RefPtrWillBeMember<Element> > ancestors; 25502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch getAncestorsInsideBlock(positionOutsideTabSpan(insertionPosition).deprecatedNode(), startBlock.get(), ancestors); 256f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> parent = cloneHierarchyUnderNewBlock(ancestors, blockToInsert); 25702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendBlockPlaceholder(parent); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(firstPositionInNode(parent.get()), DOWNSTREAM, endingSelection().isDirectional())); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //--------------------------------------------------------------------- 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle case when position is in the first visible position in its block, and 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // similar case where previous position is in another, presumeably nested, block. 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isFirstInBlock || !inSameBlock(visiblePos, visiblePos.previous())) { 26906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) Node* refNode = 0; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = positionOutsideTabSpan(insertionPosition); 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (isFirstInBlock && !nestNewBlock) { 27306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (listChild && listChild != startBlock) { 274f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> listChildToInsert = listChild->cloneElementWithoutChildren(); 27506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) appendNode(blockToInsert, listChildToInsert.get()); 27606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) insertNodeBefore(listChildToInsert.get(), listChild); 27706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else { 27806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) refNode = startBlock.get(); 27906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } 28006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else if (isFirstInBlock && nestNewBlock) { 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // startBlock should always have children, otherwise isLastInBlock would be true and it's handled above. 282c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(startBlock->hasChildren()); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) refNode = startBlock->firstChild(); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (insertionPosition.deprecatedNode() == startBlock && nestNewBlock) { 286c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) refNode = NodeTraversal::childAt(*startBlock, insertionPosition.deprecatedEditingOffset()); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(refNode); // must be true or we'd be in the end of block case 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) refNode = insertionPosition.deprecatedNode(); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // find ending selection position easily before inserting the paragraph 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = insertionPosition.downstream(); 29302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 29406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (refNode) 29506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) insertNodeBefore(blockToInsert, refNode); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Recreate the same structure in the new paragraph. 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 299f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) WillBeHeapVector<RefPtrWillBeMember<Element> > ancestors; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getAncestorsInsideBlock(positionAvoidingSpecialElementBoundary(positionOutsideTabSpan(insertionPosition)).deprecatedNode(), startBlock.get(), ancestors); 30102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendBlockPlaceholder(cloneHierarchyUnderNewBlock(ancestors, blockToInsert)); 30302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // In this case, we need to set the new ending selection. 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(insertionPosition, DOWNSTREAM, endingSelection().isDirectional())); 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //--------------------------------------------------------------------- 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle the (more complicated) general case, 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // All of the content in the current block after visiblePos is 31302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // about to be wrapped in a new paragraph element. Add a br before 31402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // it if visiblePos is at the start of a paragraph so that the 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // content will move down a line. 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isStartOfParagraph(visiblePos)) { 317c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) RefPtrWillBeRawPtr<HTMLBRElement> br = createBreakElement(document()); 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertNodeAt(br.get(), insertionPosition); 319d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) insertionPosition = positionInParentAfterNode(*br); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the insertion point is a break element, there is nothing else 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // we need to do. 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (visiblePos.deepEquivalent().anchorNode()->renderer()->isBR()) { 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(insertionPosition, DOWNSTREAM, endingSelection().isDirectional())); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 32702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 32802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // Move downstream. Typing style code will take care of carrying along the 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // style of the upstream position. 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = insertionPosition.downstream(); 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // At this point, the insertionPosition's node could be a container, and we want to make sure we include 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // all of the correct nodes when building the ancestor list. So this needs to be the deepest representation of the position 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // before we walk the DOM tree. 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition = positionOutsideTabSpan(VisiblePosition(insertionPosition).deepEquivalent()); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 337e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch // If the returned position lies either at the end or at the start of an element that is ignored by editing 338e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch // we should move to its upstream or downstream position. 339e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (editingIgnoresContent(insertionPosition.deprecatedNode())) { 340e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (insertionPosition.atLastEditingPositionForNode()) 341e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch insertionPosition = insertionPosition.downstream(); 342e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch else if (insertionPosition.atFirstEditingPositionForNode()) 343e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch insertionPosition = insertionPosition.upstream(); 344e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch } 345e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make sure we do not cause a rendered space to become unrendered. 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We need the affinity for pos, but pos.downstream() does not give it 348197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Position leadingWhitespace = leadingWhitespacePosition(insertionPosition, VP_DEFAULT_AFFINITY); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: leadingWhitespacePosition is returning the position before preserved newlines for positions 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // after the preserved newline, causing the newline to be turned into a nbsp. 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (leadingWhitespace.isNotNull() && leadingWhitespace.deprecatedNode()->isTextNode()) { 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Text* textNode = toText(leadingWhitespace.deprecatedNode()); 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace()); 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) replaceTextInNodePreservingMarkers(textNode, leadingWhitespace.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 35602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Split at pos if in the middle of a text node. 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position positionAfterSplit; 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (insertionPosition.anchorType() == Position::PositionIsOffsetInAnchor && insertionPosition.containerNode()->isTextNode()) { 360d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) RefPtrWillBeRawPtr<Text> textNode = toText(insertionPosition.containerNode()); 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atEnd = static_cast<unsigned>(insertionPosition.offsetInContainerNode()) >= textNode->length(); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (insertionPosition.deprecatedEditingOffset() > 0 && !atEnd) { 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) splitTextNode(textNode, insertionPosition.offsetInContainerNode()); 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) positionAfterSplit = firstPositionInNode(textNode.get()); 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertionPosition.moveToPosition(textNode->previousSibling(), insertionPosition.offsetInContainerNode()); 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) visiblePos = VisiblePosition(insertionPosition); 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If we got detached due to mutation events, just bail out. 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!startBlock->parentNode()) 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Put the added block in the tree. 37506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) if (nestNewBlock) { 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(blockToInsert.get(), startBlock); 37706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else if (listChild && listChild != startBlock) { 378f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeRawPtr<Element> listChildToInsert = listChild->cloneElementWithoutChildren(); 37906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) appendNode(blockToInsert.get(), listChildToInsert.get()); 38006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) insertNodeAfter(listChildToInsert.get(), listChild); 38106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } else { 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertNodeAfter(blockToInsert.get(), startBlock); 38306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) } 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3858abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document().updateLayoutIgnorePendingStylesheets(); 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the paragraph separator was inserted at the end of a paragraph, an empty line must be 38802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // created. All of the nodes, starting at visiblePos, are about to be added to the new paragraph 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // element. If the first node to be inserted won't be one that will hold an empty line open, add a br. 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isEndOfParagraph(visiblePos) && !lineBreakExistsAtVisiblePosition(visiblePos)) 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(createBreakElement(document()).get(), blockToInsert.get()); 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Move the start node and the siblings of the start node. 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (VisiblePosition(insertionPosition) != VisiblePosition(positionBeforeNode(blockToInsert.get()))) { 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* n; 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (insertionPosition.containerNode() == startBlock) 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) n = insertionPosition.computeNodeAfterPosition(); 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* splitTo = insertionPosition.containerNode(); 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (splitTo->isTextNode() && insertionPosition.offsetInContainerNode() >= caretMaxOffset(splitTo)) 40151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) splitTo = NodeTraversal::next(*splitTo, startBlock.get()); 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(splitTo); 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) splitTreeToNode(splitTo, startBlock.get()); 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (n = startBlock->firstChild(); n; n = n->nextSibling()) { 406d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) VisiblePosition beforeNodePosition(positionBeforeNode(n)); 40753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!beforeNodePosition.isNull() && comparePositions(VisiblePosition(insertionPosition), beforeNodePosition) <= 0) 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert); 41302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch } 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Handle whitespace that occurs after the split 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (positionAfterSplit.isNotNull()) { 4178abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document().updateLayoutIgnorePendingStylesheets(); 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!positionAfterSplit.isRenderedCharacter()) { 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clear out all whitespace and insert one non-breaking space 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!positionAfterSplit.containerNode()->renderer() || positionAfterSplit.containerNode()->renderer()->style()->collapseWhiteSpace()); 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deleteInsignificantTextDownstream(positionAfterSplit); 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (positionAfterSplit.deprecatedNode()->isTextNode()) 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertTextIntoNode(toText(positionAfterSplit.containerNode()), 0, nonBreakingSpaceString()); 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(firstPositionInNode(blockToInsert.get()), DOWNSTREAM, endingSelection().isDirectional())); 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) applyStyleAfterInsertion(startBlock.get()); 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 431f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void InsertParagraphSeparatorCommand::trace(Visitor *visitor) 432f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){ 433f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) visitor->trace(m_style); 434f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) CompositeEditCommand::trace(visitor); 435f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)} 436f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 437f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 438c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 439