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