18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "InsertParagraphSeparatorCommand.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSPropertyNames.h" 305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "Document.h" 3128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "EditingStyle.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLElement.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "InsertLineBreakCommand.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderObject.h" 365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "Text.h" 375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "htmlediting.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h" 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block// When inserting a new line, we want to avoid nesting empty divs if we can. Otherwise, when 458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block// pasting, it's easy to have each new line be a div deeper than the previous. E.g., in the case 468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block// below, we want to insert at ^ instead of |. 478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block// <div>foo<div>bar</div>|</div>^ 486c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic Element* highestVisuallyEquivalentDivBelowRoot(Element* startBlock) 498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{ 508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Element* curBlock = startBlock; 516c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // 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 526c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // siblings for us to append to. 536c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen while (!curBlock->nextSibling() && curBlock->parentElement()->hasTagName(divTag) && curBlock->parentElement()->parentElement()) { 548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block NamedNodeMap* attributes = curBlock->parentElement()->attributes(true); 558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (attributes && !attributes->isEmpty()) 568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block break; 578a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block curBlock = curBlock->parentElement(); 588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return curBlock; 608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block} 618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectInsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand(Document *document, bool mustUseDefaultParagraphElement) 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : CompositeEditCommand(document) 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_mustUseDefaultParagraphElement(mustUseDefaultParagraphElement) 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool InsertParagraphSeparatorCommand::preservesTypingStyle() const 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Position &pos) 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It is only important to set a style to apply later if we're at the boundaries of 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // a paragraph. Otherwise, content that is moved as part of the work of the command 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will lend their styles to the new paragraph without any extra work needed. 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isStartOfParagraph(visiblePos) && !isEndOfParagraph(visiblePos)) 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 8181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 8281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(pos.isNotNull()); 8381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_style = EditingStyle::create(pos); 8481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_style->mergeTypingStyle(pos.anchorNode()->document()); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Node* originalEnclosingBlock) 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Not only do we break out of header tags, but we also do not preserve the typing style, 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // in order to match other browsers. 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (originalEnclosingBlock->hasTagName(h1Tag) || 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalEnclosingBlock->hasTagName(h2Tag) || 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalEnclosingBlock->hasTagName(h3Tag) || 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalEnclosingBlock->hasTagName(h4Tag) || 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project originalEnclosingBlock->hasTagName(h5Tag)) 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 9728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_style) 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu m_style->prepareToApplyAt(endingSelection().start()); 10228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if (!m_style->isEmpty()) 103f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch applyStyle(m_style.get()); 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool InsertParagraphSeparatorCommand::shouldUseDefaultParagraphElement(Node* enclosingBlock) const 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_mustUseDefaultParagraphElement) 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Assumes that if there was a range selection, it was already deleted. 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isEndOfBlock(endingSelection().visibleStart())) 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return enclosingBlock->hasTagName(h1Tag) || 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project enclosingBlock->hasTagName(h2Tag) || 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project enclosingBlock->hasTagName(h3Tag) || 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project enclosingBlock->hasTagName(h4Tag) || 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project enclosingBlock->hasTagName(h5Tag); 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid InsertParagraphSeparatorCommand::getAncestorsInsideBlock(const Node* insertionNode, Element* outerBlock, Vector<Element*>& ancestors) 123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ancestors.clear(); 125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Build up list of ancestors elements between the insertion node and the outer block. 127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (insertionNode != outerBlock) { 128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block for (Element* n = insertionNode->parentElement(); n && n != outerBlock; n = n->parentElement()) 129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ancestors.append(n); 130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockPassRefPtr<Element> InsertParagraphSeparatorCommand::cloneHierarchyUnderNewBlock(const Vector<Element*>& ancestors, PassRefPtr<Element> blockToInsert) 134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Make clones of ancestors in between the start node and the start block. 136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RefPtr<Element> parent = blockToInsert; 137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block for (size_t i = ancestors.size(); i != 0; --i) { 138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RefPtr<Element> child = ancestors[i - 1]->cloneElementWithoutChildren(); 139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block appendNode(child, parent); 140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block parent = child.release(); 141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return parent.release(); 144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid InsertParagraphSeparatorCommand::doApply() 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool splitText = false; 149e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (!endingSelection().isNonOrphanedCaretOrRange()) 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Position insertionPosition = endingSelection().start(); 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project EAffinity affinity = endingSelection().affinity(); 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Delete the current selection. 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (endingSelection().isRange()) { 1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian calculateStyleBeforeInsertion(insertionPosition); 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deleteSelection(false, true); 1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = endingSelection().start(); 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project affinity = endingSelection().affinity(); 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 164ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch // FIXME: The parentAnchoredEquivalent conversion needs to be moved into enclosingBlock. 165ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch Node* startBlockNode = enclosingBlock(insertionPosition.parentAnchoredEquivalent().containerNode()); 1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Position canonicalPos = VisiblePosition(insertionPosition).deepEquivalent(); 167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Element* startBlock = static_cast<Element*>(startBlockNode); 168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!startBlockNode 169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project || !startBlockNode->isElementNode() 170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project || !startBlock->parentNode() 171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project || isTableCell(startBlock) 172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project || startBlock->hasTagName(formTag) 173e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke // 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 17481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch || (!canonicalPos.isNull() && canonicalPos.deprecatedNode()->renderer() && canonicalPos.deprecatedNode()->renderer()->isTable()) 17581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch || (!canonicalPos.isNull() && canonicalPos.deprecatedNode()->hasTagName(hrTag))) { 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project applyCommandToComposite(InsertLineBreakCommand::create(document())); 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Use the leftmost candidate. 1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = insertionPosition.upstream(); 1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!insertionPosition.isCandidate()) 1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = insertionPosition.downstream(); 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Adjust the insertion position after the delete 1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = positionAvoidingSpecialElementBoundary(insertionPosition); 1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian VisiblePosition visiblePos(insertionPosition, affinity); 1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian calculateStyleBeforeInsertion(insertionPosition); 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project //--------------------------------------------------------------------- 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle special case of typing return on an empty list item 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (breakOutOfEmptyListItem()) 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project //--------------------------------------------------------------------- 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Prepare for more general cases. 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isFirstInBlock = isStartOfBlock(visiblePos); 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isLastInBlock = isEndOfBlock(visiblePos); 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool nestNewBlock = false; 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Create block to be inserted. 203635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Element> blockToInsert; 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startBlock == startBlock->rootEditableElement()) { 205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project blockToInsert = createDefaultParagraphElement(document()); 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nestNewBlock = true; 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (shouldUseDefaultParagraphElement(startBlock)) 208635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project blockToInsert = createDefaultParagraphElement(document()); 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian blockToInsert = startBlock->cloneElementWithoutChildren(); 2115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project //--------------------------------------------------------------------- 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle case when position is in the last visible position in its block, 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // including when the block is empty. 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isLastInBlock) { 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nestNewBlock) { 2175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isFirstInBlock && !lineBreakExistsAtVisiblePosition(visiblePos)) { 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The block is empty. Create an empty block to 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // represent the paragraph that we're leaving. 220635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<Element> extraBlock = createDefaultParagraphElement(document()); 221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendNode(extraBlock, startBlock); 222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendBlockPlaceholder(extraBlock); 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project appendNode(blockToInsert, startBlock); 2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } else { 2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // 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 2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // into an unquoted area. We then don't want the newline within the blockquote or else it will also be quoted. 2285af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if (Node* highestBlockquote = highestEnclosingNodeOfType(canonicalPos, &isMailBlockquote)) 2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch startBlock = static_cast<Element*>(highestBlockquote); 2308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 2318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // Most of the time we want to stay at the nesting level of the startBlock (e.g., when nesting within lists). However, 2328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block // for div nodes, this can result in nested div tags that are hard to break out of. 2338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Element* siblingNode = startBlock; 2348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (blockToInsert->hasTagName(divTag)) 2356c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen siblingNode = highestVisuallyEquivalentDivBelowRoot(startBlock); 2368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block insertNodeAfter(blockToInsert, siblingNode); 2375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 239231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Recreate the same structure in the new paragraph. 240231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 241231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Vector<Element*> ancestors; 2422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch getAncestorsInsideBlock(positionOutsideTabSpan(insertionPosition).deprecatedNode(), startBlock, ancestors); 243231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RefPtr<Element> parent = cloneHierarchyUnderNewBlock(ancestors, blockToInsert); 244231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 245231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block appendBlockPlaceholder(parent); 246231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 247ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch setEndingSelection(VisibleSelection(firstPositionInNode(parent.get()), DOWNSTREAM)); 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 250231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project //--------------------------------------------------------------------- 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle case when position is in the first visible position in its block, and 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // similar case where previous position is in another, presumeably nested, block. 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isFirstInBlock || !inSameBlock(visiblePos, visiblePos.previous())) { 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *refNode; 2572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch insertionPosition = positionOutsideTabSpan(insertionPosition); 2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isFirstInBlock && !nestNewBlock) 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project refNode = startBlock; 26281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch else if (insertionPosition.deprecatedNode() == startBlock && nestNewBlock) { 2635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian refNode = startBlock->childNode(insertionPosition.deprecatedEditingOffset()); 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(refNode); // must be true or we'd be in the end of block case 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 26681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch refNode = insertionPosition.deprecatedNode(); 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // find ending selection position easily before inserting the paragraph 2698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = insertionPosition.downstream(); 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 271635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project insertNodeBefore(blockToInsert, refNode); 272231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 273231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Recreate the same structure in the new paragraph. 274231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 275231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Vector<Element*> ancestors; 2762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch getAncestorsInsideBlock(positionAvoidingSpecialElementBoundary(positionOutsideTabSpan(insertionPosition)).deprecatedNode(), startBlock, ancestors); 277231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block appendBlockPlaceholder(cloneHierarchyUnderNewBlock(ancestors, blockToInsert)); 279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // In this case, we need to set the new ending selection. 2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian setEndingSelection(VisibleSelection(insertionPosition, DOWNSTREAM)); 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project //--------------------------------------------------------------------- 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle the (more complicated) general case, 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // All of the content in the current block after visiblePos is 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // about to be wrapped in a new paragraph element. Add a br before 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // it if visiblePos is at the start of a paragraph so that the 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // content will move down a line. 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isStartOfParagraph(visiblePos)) { 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Element> br = createBreakElement(document()); 2948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertNodeAt(br.get(), insertionPosition); 295231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block insertionPosition = positionInParentAfterNode(br.get()); 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Move downstream. Typing style code will take care of carrying along the 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // style of the upstream position. 3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian insertionPosition = insertionPosition.downstream(); 3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // At this point, the insertionPosition's node could be a container, and we want to make sure we include 3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // all of the correct nodes when building the ancestor list. So this needs to be the deepest representation of the position 3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // before we walk the DOM tree. 3052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch insertionPosition = positionOutsideTabSpan(VisiblePosition(insertionPosition).deepEquivalent()); 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Make sure we do not cause a rendered space to become unrendered. 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: We need the affinity for pos, but pos.downstream() does not give it 3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Position leadingWhitespace = insertionPosition.leadingWhitespacePosition(VP_DEFAULT_AFFINITY); 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: leadingWhitespacePosition is returning the position before preserved newlines for positions 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // after the preserved newline, causing the newline to be turned into a nbsp. 31281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (leadingWhitespace.isNotNull() && leadingWhitespace.deprecatedNode()->isTextNode()) { 31381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch Text* textNode = static_cast<Text*>(leadingWhitespace.deprecatedNode()); 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace()); 3155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian replaceTextInNode(textNode, leadingWhitespace.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Split at pos if in the middle of a text node. 31981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (insertionPosition.deprecatedNode()->isTextNode()) { 32081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch Text* textNode = static_cast<Text*>(insertionPosition.deprecatedNode()); 3215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian bool atEnd = (unsigned)insertionPosition.deprecatedEditingOffset() >= textNode->length(); 3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (insertionPosition.deprecatedEditingOffset() > 0 && !atEnd) { 3235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian splitTextNode(textNode, insertionPosition.deprecatedEditingOffset()); 3245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian insertionPosition.moveToOffset(0); 3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian visiblePos = VisiblePosition(insertionPosition); 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project splitText = true; 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Put the added block in the tree. 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nestNewBlock) 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendNode(blockToInsert.get(), startBlock); 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project insertNodeAfter(blockToInsert.get(), startBlock); 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project updateLayout(); 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If the paragraph separator was inserted at the end of a paragraph, an empty line must be 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // created. All of the nodes, starting at visiblePos, are about to be added to the new paragraph 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // element. If the first node to be inserted won't be one that will hold an empty line open, add a br. 3415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isEndOfParagraph(visiblePos) && !lineBreakExistsAtVisiblePosition(visiblePos)) 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendNode(createBreakElement(document()).get(), blockToInsert.get()); 3432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Move the start node and the siblings of the start node. 3452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (VisiblePosition(insertionPosition) != VisiblePosition(positionBeforeNode(blockToInsert.get()))) { 3462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Node* n; 3472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (insertionPosition.containerNode() == startBlock) 3482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch n = insertionPosition.computeNodeAfterPosition(); 3492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch else { 3502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch splitTreeToNode(insertionPosition.containerNode(), startBlock); 3512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 3522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch for (n = startBlock->firstChild(); n; n = n->nextSibling()) { 3532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (comparePositions(VisiblePosition(insertionPosition), positionBeforeNode(n)) <= 0) 3542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch break; 3552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (n && n != blockToInsert) { 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node *next = n->nextSibling(); 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project removeNode(n); 3612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch appendNode(n, blockToInsert); 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project n = next; 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle whitespace that occurs after the split 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (splitText) { 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project updateLayout(); 369ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch if (insertionPosition.anchorType() == Position::PositionIsOffsetInAnchor) 370ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch insertionPosition.moveToOffset(0); 3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!insertionPosition.isRenderedCharacter()) { 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Clear out all whitespace and insert one non-breaking space 37381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(!insertionPosition.deprecatedNode()->renderer() || insertionPosition.deprecatedNode()->renderer()->style()->collapseWhiteSpace()); 3748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian deleteInsignificantTextDownstream(insertionPosition); 37581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (insertionPosition.deprecatedNode()->isTextNode()) 37681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch insertTextIntoNode(static_cast<Text*>(insertionPosition.deprecatedNode()), 0, nonBreakingSpaceString()); 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 380ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch setEndingSelection(VisibleSelection(firstPositionInNode(blockToInsert.get()), DOWNSTREAM)); 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project applyStyleAfterInsertion(startBlock); 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore 385