htmlediting.cpp revision 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2
18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2005, 2006, 2007 Apple 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 "htmlediting.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CharacterNames.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EditingText.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLElement.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLInterchange.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PositionIterator.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderObject.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RegularExpression.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Range.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Selection.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "VisiblePosition.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Atomic means that the node has no children, or has children which are ignored for the
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// purposes of editing.
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isAtomicNode(const Node *node)
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && (!node->hasChildNodes() || editingIgnoresContent(node));
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns true for nodes that either have no content, or have content that is ignored (skipped
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// over) while editing.  There are no VisiblePositions inside these nodes.
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool editingIgnoresContent(const Node* node)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !canHaveChildrenForEditing(node) && !node->isTextNode();
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool canHaveChildrenForEditing(const Node* node)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !node->hasTagName(hrTag) &&
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(brTag) &&
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(imgTag) &&
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(buttonTag) &&
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(inputTag) &&
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(textareaTag) &&
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(objectTag) &&
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(iframeTag) &&
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(embedTag) &&
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(appletTag) &&
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(selectTag) &&
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->isTextNode();
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Compare two positions, taking into account the possibility that one or both
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// could be inside a shadow tree. Only works for non-null values.
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint comparePositions(const Position& a, const Position& b)
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nodeA = a.node();
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(nodeA);
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nodeB = b.node();
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(nodeB);
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int offsetA = a.offset();
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int offsetB = b.offset();
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* shadowAncestorA = nodeA->shadowAncestorNode();
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorA == nodeA)
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shadowAncestorA = 0;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* shadowAncestorB = nodeB->shadowAncestorNode();
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorB == nodeB)
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shadowAncestorB = 0;
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int bias = 0;
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorA != shadowAncestorB) {
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestorA) {
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            nodeA = shadowAncestorA;
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offsetA = 0;
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bias = 1;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestorB) {
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            nodeB = shadowAncestorB;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offsetB = 0;
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bias = -1;
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result ? result : bias;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* highestEditableRoot(const Position& position)
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = position.node();
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = editableRootForPosition(position);
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node = highestRoot;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node) {
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->isContentEditable())
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            highestRoot = node;
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->hasTagName(bodyTag))
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return highestRoot;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* lowestEditableAncestor(Node* node)
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *lowestRoot = 0;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node) {
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->isContentEditable())
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return node->rootEditableElement();
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->hasTagName(bodyTag))
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lowestRoot;
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEditablePosition(const Position& p)
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->isContentEditable();
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isRichlyEditablePosition(const Position& p)
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->isContentRichlyEditable();
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement* editableRootForPosition(const Position& p)
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->rootEditableElement();
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isContentEditable(const Node* node)
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->isContentEditable();
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition nextCandidate(const Position& position)
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator p = position;
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atEnd()) {
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.increment();
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate())
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition nextVisuallyDistinctCandidate(const Position& position)
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atEnd()) {
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = p.next(UsingComposedCharacters);
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate() && p.downstream() != downstreamStart)
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition previousCandidate(const Position& position)
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator p = position;
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atStart()) {
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.decrement();
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate())
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition previousVisuallyDistinctCandidate(const Position& position)
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atStart()) {
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = p.previous(UsingComposedCharacters);
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate() && p.downstream() != downstreamStart)
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition firstEditablePositionAfterPositionInRoot(const Position& position, Node* highestRoot)
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // position falls before highestRoot.
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (comparePositions(position, Position(highestRoot, 0)) == -1 && highestRoot->isContentEditable())
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition(Position(highestRoot, 0));
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestor != p.node())
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = isAtomicNode(p.node()) ? positionAfterNode(p.node()) : nextVisuallyDistinctCandidate(p);
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.node() && !p.node()->isDescendantOf(highestRoot))
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(p);
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition lastEditablePositionBeforePositionInRoot(const Position& position, Node* highestRoot)
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // When position falls after highestRoot, the result is easy to compute.
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (comparePositions(position, Position(highestRoot, maxDeepOffset(highestRoot))) == 1)
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition(Position(highestRoot, maxDeepOffset(highestRoot)));
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestor != p.node())
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            p = Position(shadowAncestor, 0);
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p = isAtomicNode(p.node()) ? positionBeforeNode(p.node()) : previousVisuallyDistinctCandidate(p);
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.node() && !p.node()->isDescendantOf(highestRoot))
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(p);
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Whether or not content before and after this node will collapse onto the same line as it.
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isBlock(const Node* node)
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->renderer() && !node->renderer()->isInline();
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Pass a position to this function.  The enclosing block of [table, x] for example, should be the
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// block that contains the table and not the table, and this function should be the only one responsible for
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// knowing about these kinds of special cases.
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingBlock(Node* node)
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return enclosingNodeOfType(Position(node, 0), &isBlock);
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition rangeCompliantEquivalent(const Position& pos)
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.isNull())
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *node = pos.node();
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.offset() <= 0) {
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->parentNode() && (editingIgnoresContent(node) || isTableElement(node)))
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return positionBeforeNode(node);
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position(node, 0);
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->offsetInCharacters())
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position(node, min(node->maxCharacterOffset(), pos.offset()));
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int maxCompliantOffset = node->childNodeCount();
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.offset() > maxCompliantOffset) {
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->parentNode())
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return positionAfterNode(node);
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // there is no other option at this point than to
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // use the highest allowed position in the node
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position(node, maxCompliantOffset);
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Editing should never generate positions like this.
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ((pos.offset() < maxCompliantOffset) && editingIgnoresContent(node)) {
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT_NOT_REACHED();
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->parentNode() ? positionBeforeNode(node) : Position(node, 0);
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.offset() == maxCompliantOffset && (editingIgnoresContent(node) || isTableElement(node)))
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return positionAfterNode(node);
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(pos);
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition rangeCompliantEquivalent(const VisiblePosition& vpos)
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return rangeCompliantEquivalent(vpos.deepEquivalent());
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This method is used to create positions in the DOM. It returns the maximum valid offset
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in a node.  It returns 1 for some elements even though they do not have children, which
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// creates technically invalid DOM Positions.  Be sure to call rangeCompliantEquivalent
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// on a Position before using it to create a DOM Range, or an exception will be thrown.
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint maxDeepOffset(const Node *node)
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(node);
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->offsetInCharacters())
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->maxCharacterOffset();
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->hasChildNodes())
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->childNodeCount();
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // NOTE: This should preempt the childNodeCount for, e.g., select nodes
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (editingIgnoresContent(node))
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 1;
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph)
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static String twoSpaces("  ");
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static String nbsp("\xa0");
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static String pattern(" \xa0");
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String rebalancedString = string;
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace(noBreakSpace, ' ');
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace('\n', ' ');
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace('\t', ' ');
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace(twoSpaces, pattern);
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (startIsStartOfParagraph && rebalancedString[0] == ' ')
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        rebalancedString.replace(0, 1, nbsp);
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int end = rebalancedString.length() - 1;
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (endIsEndOfParagraph && rebalancedString[end] == ' ')
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        rebalancedString.replace(end, 1, nbsp);
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return rebalancedString;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableStructureNode(const Node *node)
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *r = node->renderer();
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (r && (r->isTableCell() || r->isTableRow() || r->isTableSection() || r->isTableCol()));
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst String& nonBreakingSpaceString()
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static String nonBreakingSpaceString = String(&noBreakSpace, 1);
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nonBreakingSpaceString;
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: need to dump this
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isSpecialElement(const Node *n)
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n->isHTMLElement())
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (n->isLink())
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = n->renderer();
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE)
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->isFloating())
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->position() != StaticPosition)
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Checks if a string is a valid tag for the FormatBlockCommand function of execCommand. Expects lower case strings.
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool validBlockTag(const String& blockTag)
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (blockTag == "address" ||
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "blockquote" ||
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "dd" ||
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "div" ||
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "dl" ||
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "dt" ||
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h1" ||
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h2" ||
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h3" ||
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h4" ||
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h5" ||
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "h6" ||
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "p" ||
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        blockTag == "pre")
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* firstInSpecialElement(const Position& pos)
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* rootEditableElement = pos.node()->rootEditableElement();
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isSpecialElement(n)) {
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition firstInElement = VisiblePosition(n, 0, DOWNSTREAM);
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isTableElement(n) && vPos == firstInElement.next())
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (vPos == firstInElement)
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* lastInSpecialElement(const Position& pos)
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* rootEditableElement = pos.node()->rootEditableElement();
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isSpecialElement(n)) {
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition lastInElement = VisiblePosition(n, n->childNodeCount(), DOWNSTREAM);
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isTableElement(n) && vPos == lastInElement.previous())
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (vPos == lastInElement)
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isFirstVisiblePositionInSpecialElement(const Position& pos)
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return firstInSpecialElement(pos);
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionBeforeContainingSpecialElement(const Position& pos, Node** containingSpecialElement)
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = firstInSpecialElement(pos);
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position result = positionBeforeNode(n);
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement())
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (containingSpecialElement)
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *containingSpecialElement = n;
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isLastVisiblePositionInSpecialElement(const Position& pos)
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastInSpecialElement(pos);
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionAfterContainingSpecialElement(const Position& pos, Node **containingSpecialElement)
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = lastInSpecialElement(pos);
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position result = positionAfterNode(n);
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement())
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (containingSpecialElement)
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *containingSpecialElement = n;
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionOutsideContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isFirstVisiblePositionInSpecialElement(pos))
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return positionBeforeContainingSpecialElement(pos, containingSpecialElement);
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isLastVisiblePositionInSpecialElement(pos))
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return positionAfterContainingSpecialElement(pos, containingSpecialElement);
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return pos;
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position upstream(visiblePosition.deepEquivalent().upstream());
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (upstream.node() && upstream.node()->renderer() && upstream.node()->renderer()->isTable() && upstream.offset() == maxDeepOffset(upstream.node()))
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return upstream.node();
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstream(visiblePosition.deepEquivalent().downstream());
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (downstream.node() && downstream.node()->renderer() && downstream.node()->renderer()->isTable() && downstream.offset() == 0)
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return downstream.node();
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionBeforeNode(const Node *node)
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(node->parentNode(), node->nodeIndex());
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionAfterNode(const Node *node)
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(node->parentNode(), node->nodeIndex() + 1);
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isListElement(Node *n)
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(dlTag)));
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName)
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(p);
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode()) {
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (root && !isContentEditable(n))
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(tagName))
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), bool onlyReturnEditableNodes)
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(p);
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode()) {
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Don't return a non-editable node if the input position was editable, since
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // the callers from editing will no doubt want to perform editing inside the returned node.
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (root && !isContentEditable(n) && onlyReturnEditableNodes)
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if ((*nodeIsOfType)(n))
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingTableCell(const Position& p)
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return enclosingNodeOfType(p, &isTableCell);
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingAnchorElement(const Position& p)
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node && !(node->isElementNode() && node->isLink()))
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node;
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingList(Node* node)
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(Position(node, 0));
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = node->parentNode(); n; n = n->parentNode()) {
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(ulTag) || n->hasTagName(olTag))
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingListChild(Node *node)
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check for a list item element, or for a node whose parent is a list element.  Such a node
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // will appear visually as a list item (but without a list marker)
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(Position(node, 0));
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(liTag) || isListElement(n->parentNode()))
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root || isTableCell(n))
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* embeddedSublist(Node* listItem)
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the DOM so that we'll find collapsed sublists without renderers.
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isListElement(n))
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* appendedSublist(Node* listItem)
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the DOM so that we'll find collapsed sublists without renderers.
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isListElement(n))
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->renderer() && n->renderer()->isListItem())
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingEmptyListItem(const VisiblePosition& visiblePos)
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check that position is on a line by itself inside a list item
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().node());
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(visiblePos))
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition firstInListChild(Position(listChildNode, 0));
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition lastInListChild(Position(listChildNode, maxDeepOffset(listChildNode)));
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (firstInListChild != visiblePos || lastInListChild != visiblePos)
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return listChildNode;
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* outermostEnclosingListChild(Node* node)
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* listNode = 0;
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nextNode = node;
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((nextNode = enclosingListChild(nextNode)))
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        listNode = nextNode;
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return listNode;
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* outermostEnclosingList(Node* node)
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* listNode = 0;
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nextNode = node;
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((nextNode = enclosingList(nextNode)))
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        listNode = nextNode;
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return listNode;
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* highestAncestor(Node* node)
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(node);
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* parent = node;
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((node = node->parentNode()))
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        parent = node;
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return parent;
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: do not require renderer, so that this can be used within fragments, or rename to isRenderedTable()
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableElement(Node* n)
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n || !n->isElementNode())
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* renderer = n->renderer();
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (renderer && (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE));
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableCell(const Node* node)
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = node->renderer();
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!r)
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->hasTagName(tdTag) || node->hasTagName(thTag);
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return r->isTableCell();
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createDefaultParagraphElement(Document *document)
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "div", ec);
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return element.release();
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createBreakElement(Document *document)
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "br", ec);
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return breakNode.release();
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createOrderedListElement(Document *document)
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "ol", ec);
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return element.release();
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createUnorderedListElement(Document *document)
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> element = document->createElementNS(xhtmlNamespaceURI, "ul", ec);
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return element.release();
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createListItemElement(Document *document)
7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, "li", ec);
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return breakNode.release();
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createElement(Document* document, const String& tagName)
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> breakNode = document->createElementNS(xhtmlNamespaceURI, tagName, ec);
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return breakNode.release();
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTabSpanNode(const Node *node)
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->hasTagName(spanTag) && node->isElementNode() && static_cast<const Element *>(node)->getAttribute(classAttr) == AppleTabSpanClass;
7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTabSpanTextNode(const Node *node)
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->isTextNode() && node->parentNode() && isTabSpanNode(node->parentNode());
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode *tabSpanNode(const Node *node)
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return isTabSpanTextNode(node) ? node->parentNode() : 0;
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionBeforeTabSpan(const Position& pos)
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *node = pos.node();
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isTabSpanTextNode(node))
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = tabSpanNode(node);
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (!isTabSpanNode(node))
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return positionBeforeNode(node);
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document, PassRefPtr<Node> tabTextNode)
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // make the span to hold the tab
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> spanElement = document->createElementNS(xhtmlNamespaceURI, "span", ec);
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->setAttribute(classAttr, AppleTabSpanClass);
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->setAttribute(styleAttr, "white-space:pre");
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // add tab text to that span
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!tabTextNode)
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        tabTextNode = document->createEditingTextNode("\t");
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->appendChild(tabTextNode, ec);
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return spanElement.release();
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document, const String& tabText)
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return createTabSpanElement(document, document->createTextNode(tabText));
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document)
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return createTabSpanElement(document, PassRefPtr<Node>());
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isNodeRendered(const Node *node)
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = node->renderer();
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return renderer->style()->visibility() == VISIBLE;
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode *nearestMailBlockquote(const Node *node)
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node *n = const_cast<Node *>(node); n; n = n->parentNode()) {
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isMailBlockquote(n))
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isMailBlockquote(const Node *node)
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node || !node->isElementNode() && !node->hasTagName(blockquoteTag))
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return static_cast<const Element *>(node)->getAttribute("type") == "cite";
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint caretMinOffset(const Node* n)
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = n->renderer();
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!n->isCharacterDataNode() || !r || r->isText()); // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return r ? r->caretMinOffset() : 0;
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint caretMaxOffset(const Node* n)
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = n->renderer();
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!n->isCharacterDataNode() || !r || r->isText()); // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (r)
8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return r->caretMaxOffset();
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (n->isCharacterDataNode()) {
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const CharacterData* c = static_cast<const CharacterData*>(n);
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return static_cast<int>(c->length());
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 1;
8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool lineBreakExistsAtPosition(const VisiblePosition& visiblePosition)
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstream(visiblePosition.deepEquivalent().downstream());
8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return downstream.node()->hasTagName(brTag) ||
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           downstream.node()->isTextNode() && downstream.node()->renderer()->style()->preserveNewline() && visiblePosition.characterAfter() == '\n';
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Modifies selections that have an end point at the edge of a table
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// that contains the other endpoint so that they don't confuse
9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// code that iterates over selected paragraphs.
9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSelection selectionForParagraphIteration(const Selection& original)
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Selection newSelection(original);
9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition startOfSelection(newSelection.visibleStart());
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition endOfSelection(newSelection.visibleEnd());
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the end of the selection to modify is just after a table, and
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if the start of the selection is inside that table, then the last paragraph
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // that we'll want modify is the last one inside the table, not the table itself
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // (a table is itself a paragraph).
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* table = isFirstPositionAfterTable(endOfSelection))
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (startOfSelection.deepEquivalent().node()->isDescendantOf(table))
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newSelection = Selection(startOfSelection, endOfSelection.previous(true));
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the start of the selection to modify is just before a table,
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and if the end of the selection is inside that table, then the first paragraph
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we'll want to modify is the first one inside the table, not the paragraph
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // containing the table itself.
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* table = isLastPositionBeforeTable(startOfSelection))
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endOfSelection.deepEquivalent().node()->isDescendantOf(table))
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newSelection = Selection(startOfSelection.next(true), endOfSelection);
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return newSelection;
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint indexForVisiblePosition(VisiblePosition& visiblePosition)
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p(visiblePosition.deepEquivalent());
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Range> range = Range::create(p.node()->document(), Position(p.node()->document(), 0), rangeCompliantEquivalent(p));
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return TextIterator::rangeLength(range.get(), true);
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> avoidIntersectionWithNode(const Range* range, Node* node)
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!range)
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Document* document = range->ownerDocument();
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* startContainer = range->startContainer();
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int startOffset = range->startOffset();
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* endContainer = range->endContainer();
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int endOffset = range->endOffset();
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!startContainer)
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(endContainer);
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (startContainer == node || startContainer->isDescendantOf(node)) {
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startContainer = node->parentNode();
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startOffset = node->nodeIndex();
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (endContainer == node || endContainer->isDescendantOf(node)) {
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endContainer = node->parentNode();
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endOffset = node->nodeIndex();
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Range::create(document, startContainer, startOffset, endContainer, endOffset);
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSelection avoidIntersectionWithNode(const Selection& selection, Node* node)
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (selection.isNone())
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Selection(selection);
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Selection updatedSelection(selection);
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* base = selection.base().node();
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* extent = selection.extent().node();
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(base);
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(extent);
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (base == node || base->isDescendantOf(node)) {
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updatedSelection.setBase(Position(node->parentNode(), node->nodeIndex()));
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (extent == node || extent->isDescendantOf(node)) {
9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updatedSelection.setExtent(Position(node->parentNode(), node->nodeIndex()));
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return updatedSelection;
9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
992