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"
32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLBRElement.h"
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLDivElement.h"
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLElementFactory.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLInterchange.h"
36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLLIElement.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLOListElement.h"
39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLUListElement.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PositionIterator.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderObject.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Range.h"
438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "VisibleSelection.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "VisiblePosition.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h"
48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h>
49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if ENABLE(WML)
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "WMLNames.h"
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Atomic means that the node has no children, or has children which are ignored for the
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// purposes of editing.
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isAtomicNode(const Node *node)
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && (!node->hasChildNodes() || editingIgnoresContent(node));
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns true for nodes that either have no content, or have content that is ignored (skipped
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// over) while editing.  There are no VisiblePositions inside these nodes.
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool editingIgnoresContent(const Node* node)
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !canHaveChildrenForEditing(node) && !node->isTextNode();
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool canHaveChildrenForEditing(const Node* node)
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !node->hasTagName(hrTag) &&
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(brTag) &&
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(imgTag) &&
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(buttonTag) &&
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(inputTag) &&
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(textareaTag) &&
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(objectTag) &&
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(iframeTag) &&
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(embedTag) &&
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(appletTag) &&
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->hasTagName(selectTag) &&
870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch           !node->hasTagName(datagridTag) &&
88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if ENABLE(WML)
89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project           !node->hasTagName(WMLNames::doTag) &&
90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           !node->isTextNode();
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Compare two positions, taking into account the possibility that one or both
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// could be inside a shadow tree. Only works for non-null values.
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint comparePositions(const Position& a, const Position& b)
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nodeA = a.node();
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(nodeA);
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* nodeB = b.node();
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(nodeB);
1025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int offsetA = a.deprecatedEditingOffset();
1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int offsetB = b.deprecatedEditingOffset();
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* shadowAncestorA = nodeA->shadowAncestorNode();
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorA == nodeA)
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shadowAncestorA = 0;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* shadowAncestorB = nodeB->shadowAncestorNode();
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorB == nodeB)
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shadowAncestorB = 0;
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int bias = 0;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (shadowAncestorA != shadowAncestorB) {
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestorA) {
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            nodeA = shadowAncestorA;
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offsetA = 0;
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bias = 1;
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestorB) {
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            nodeB = shadowAncestorB;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            offsetB = 0;
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bias = -1;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result ? result : bias;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianint comparePositions(const VisiblePosition& a, const VisiblePosition& b)
1315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return comparePositions(a.deepEquivalent(), b.deepEquivalent());
1335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* highestEditableRoot(const Position& position)
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = position.node();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* highestRoot = editableRootForPosition(position);
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!highestRoot)
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    node = highestRoot;
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node) {
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->isContentEditable())
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            highestRoot = node;
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->hasTagName(bodyTag))
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return highestRoot;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* lowestEditableAncestor(Node* node)
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *lowestRoot = 0;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node) {
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->isContentEditable())
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return node->rootEditableElement();
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->hasTagName(bodyTag))
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lowestRoot;
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isEditablePosition(const Position& p)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->isContentEditable();
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool isAtUnsplittableElement(const Position& pos)
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Node* node = pos.node();
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(pos, &isTableCell));
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isRichlyEditablePosition(const Position& p)
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->isContentRichlyEditable();
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectElement* editableRootForPosition(const Position& p)
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->renderer() && node->renderer()->isTable())
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node->rootEditableElement();
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Finds the enclosing element until which the tree can be split.
2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// When a user hits ENTER, he/she won't expect this element to be split into two.
2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// You may pass it as the second argument of splitTreeToNode.
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochElement* unsplittableElementForPosition(const Position& p)
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Since enclosingNodeOfType won't search beyond the highest root editable node,
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // this code works even if the closest table cell was outside of the root editable node.
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Element* enclosingCell = static_cast<Element*>(enclosingNodeOfType(p, &isTableCell, true));
2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (enclosingCell)
2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return enclosingCell;
2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return editableRootForPosition(p);
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition nextCandidate(const Position& position)
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator p = position;
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atEnd()) {
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.increment();
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate())
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition nextVisuallyDistinctCandidate(const Position& position)
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    while (!p.atEndOfTree()) {
2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        p = p.next(Character);
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate() && p.downstream() != downstreamStart)
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition previousCandidate(const Position& position)
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PositionIterator p = position;
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!p.atStart()) {
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        p.decrement();
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate())
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition previousVisuallyDistinctCandidate(const Position& position)
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstreamStart = p.downstream();
2698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    while (!p.atStartOfTree()) {
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        p = p.previous(Character);
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (p.isCandidate() && p.downstream() != downstreamStart)
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return p;
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position();
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition firstEditablePositionAfterPositionInRoot(const Position& position, Node* highestRoot)
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // position falls before highestRoot.
2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (comparePositions(position, firstDeepEditingPositionForNode(highestRoot)) == -1 && highestRoot->isContentEditable())
2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return firstDeepEditingPositionForNode(highestRoot);
2828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestor != p.node())
2878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            p = lastDeepEditingPositionForNode(shadowAncestor);
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
290231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        p = isAtomicNode(p.node()) ? positionInParentAfterNode(p.node()) : nextVisuallyDistinctCandidate(p);
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
292643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (p.node() && p.node() != highestRoot && !p.node()->isDescendantOf(highestRoot))
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(p);
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition lastEditablePositionBeforePositionInRoot(const Position& position, Node* highestRoot)
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // When position falls after highestRoot, the result is easy to compute.
3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (comparePositions(position, lastDeepEditingPositionForNode(highestRoot)) == 1)
3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return lastDeepEditingPositionForNode(highestRoot);
3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p = position;
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (shadowAncestor != p.node())
3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            p = firstDeepEditingPositionForNode(shadowAncestor);
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        p = isAtomicNode(p.node()) ? positionInParentBeforeNode(p.node()) : previousVisuallyDistinctCandidate(p);
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (p.node() && p.node() != highestRoot && !p.node()->isDescendantOf(highestRoot))
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return VisiblePosition();
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return VisiblePosition(p);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// FIXME: The method name, comment, and code say three different things here!
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Whether or not content before and after this node will collapse onto the same line as it.
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isBlock(const Node* node)
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->renderer() && !node->renderer()->isInline();
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: Pass a position to this function.  The enclosing block of [table, x] for example, should be the
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// block that contains the table and not the table, and this function should be the only one responsible for
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// knowing about these kinds of special cases.
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingBlock(Node* node)
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return static_cast<Element*>(enclosingNodeOfType(Position(node, 0), isBlock));
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Internally editing uses "invalid" positions for historical reasons.  For
3368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// example, in <div><img /></div>, Editing might use (img, 1) for the position
3378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// after <img>, but we have to convert that to (div, 1) before handing the
3388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// position to a Range object.  Ideally all internal positions should
3398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// be "range compliant" for simplicity.
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition rangeCompliantEquivalent(const Position& pos)
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (pos.isNull())
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position();
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Node* node = pos.node();
3468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (pos.deprecatedEditingOffset() <= 0) {
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->parentNode() && (editingIgnoresContent(node) || isTableElement(node)))
349231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return positionInParentBeforeNode(node);
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position(node, 0);
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->offsetInCharacters())
3545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return Position(node, min(node->maxCharacterOffset(), pos.deprecatedEditingOffset()));
3558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int maxCompliantOffset = node->childNodeCount();
3575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (pos.deprecatedEditingOffset() > maxCompliantOffset) {
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (node->parentNode())
359231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return positionInParentAfterNode(node);
3608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // there is no other option at this point than to
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // use the highest allowed position in the node
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return Position(node, maxCompliantOffset);
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Editing should never generate positions like this.
3675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if ((pos.deprecatedEditingOffset() < maxCompliantOffset) && editingIgnoresContent(node)) {
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT_NOT_REACHED();
369231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return node->parentNode() ? positionInParentBeforeNode(node) : Position(node, 0);
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (pos.deprecatedEditingOffset() == maxCompliantOffset && (editingIgnoresContent(node) || isTableElement(node)))
373231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return positionInParentAfterNode(node);
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Position(pos);
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition rangeCompliantEquivalent(const VisiblePosition& vpos)
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return rangeCompliantEquivalent(vpos.deepEquivalent());
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This method is used to create positions in the DOM. It returns the maximum valid offset
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in a node.  It returns 1 for some elements even though they do not have children, which
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// creates technically invalid DOM Positions.  Be sure to call rangeCompliantEquivalent
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// on a Position before using it to create a DOM Range, or an exception will be thrown.
3878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianint lastOffsetForEditing(const Node* node)
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(node);
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->offsetInCharacters())
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->maxCharacterOffset();
394231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (node->hasChildNodes())
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->childNodeCount();
397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // NOTE: This should preempt the childNodeCount for, e.g., select nodes
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (editingIgnoresContent(node))
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 1;
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph)
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(String, twoSpaces, ("  "));
408635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(String, nbsp, ("\xa0"));
409635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(String, pattern, (" \xa0"));
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String rebalancedString = string;
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace(noBreakSpace, ' ');
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace('\n', ' ');
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace('\t', ' ');
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rebalancedString.replace(twoSpaces, pattern);
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (startIsStartOfParagraph && rebalancedString[0] == ' ')
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        rebalancedString.replace(0, 1, nbsp);
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int end = rebalancedString.length() - 1;
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (endIsEndOfParagraph && rebalancedString[end] == ' ')
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        rebalancedString.replace(end, 1, nbsp);
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return rebalancedString;
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableStructureNode(const Node *node)
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *r = node->renderer();
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (r && (r->isTableCell() || r->isTableRow() || r->isTableSection() || r->isTableCol()));
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst String& nonBreakingSpaceString()
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
436635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1));
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nonBreakingSpaceString;
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: need to dump this
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isSpecialElement(const Node *n)
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n->isHTMLElement())
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (n->isLink())
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = n->renderer();
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE)
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->isFloating())
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (renderer->style()->position() != StaticPosition)
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Checks if a string is a valid tag for the FormatBlockCommand function of execCommand. Expects lower case strings.
469231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool validBlockTag(const AtomicString& blockTag)
470231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
471231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (blockTag.isEmpty())
472231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
473231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
474231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, blockTags, ());
475231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (blockTags.isEmpty()) {
476231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(addressTag.localName());
477d0825bca7fe65beaee391d30da42e937db621564Steve Block        blockTags.add(articleTag.localName());
478d0825bca7fe65beaee391d30da42e937db621564Steve Block        blockTags.add(asideTag.localName());
479231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(blockquoteTag.localName());
480231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(ddTag.localName());
481231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(divTag.localName());
482231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(dlTag.localName());
483231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(dtTag.localName());
484d0825bca7fe65beaee391d30da42e937db621564Steve Block        blockTags.add(footerTag.localName());
485231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h1Tag.localName());
486231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h2Tag.localName());
487231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h3Tag.localName());
488231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h4Tag.localName());
489231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h5Tag.localName());
490231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(h6Tag.localName());
491d0825bca7fe65beaee391d30da42e937db621564Steve Block        blockTags.add(headerTag.localName());
492231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(navTag.localName());
493231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(pTag.localName());
494231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        blockTags.add(preTag.localName());
495d0825bca7fe65beaee391d30da42e937db621564Steve Block        blockTags.add(sectionTag.localName());
496231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
497231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return blockTags.contains(blockTag);
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* firstInSpecialElement(const Position& pos)
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
502643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // FIXME: This begins at pos.node(), which doesn't necessarily contain pos (suppose pos was [img, 0]).  See <rdar://problem/5027702>.
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* rootEditableElement = pos.node()->rootEditableElement();
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isSpecialElement(n)) {
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition firstInElement = VisiblePosition(n, 0, DOWNSTREAM);
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isTableElement(n) && vPos == firstInElement.next())
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (vPos == firstInElement)
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* lastInSpecialElement(const Position& pos)
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
518643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // FIXME: This begins at pos.node(), which doesn't necessarily contain pos (suppose pos was [img, 0]).  See <rdar://problem/5027702>.
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* rootEditableElement = pos.node()->rootEditableElement();
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isSpecialElement(n)) {
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            VisiblePosition lastInElement = VisiblePosition(n, n->childNodeCount(), DOWNSTREAM);
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (isTableElement(n) && vPos == lastInElement.previous())
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (vPos == lastInElement)
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return n;
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isFirstVisiblePositionInSpecialElement(const Position& pos)
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return firstInSpecialElement(pos);
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionBeforeContainingSpecialElement(const Position& pos, Node** containingSpecialElement)
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = firstInSpecialElement(pos);
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
542231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Position result = positionInParentBeforeNode(n);
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement())
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (containingSpecialElement)
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *containingSpecialElement = n;
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isLastVisiblePositionInSpecialElement(const Position& pos)
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastInSpecialElement(pos);
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionAfterContainingSpecialElement(const Position& pos, Node **containingSpecialElement)
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* n = lastInSpecialElement(pos);
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n)
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
560231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Position result = positionInParentAfterNode(n);
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement())
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (containingSpecialElement)
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *containingSpecialElement = n;
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionOutsideContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isFirstVisiblePositionInSpecialElement(pos))
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return positionBeforeContainingSpecialElement(pos, containingSpecialElement);
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isLastVisiblePositionInSpecialElement(pos))
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return positionAfterContainingSpecialElement(pos, containingSpecialElement);
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return pos;
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position upstream(visiblePosition.deepEquivalent().upstream());
5808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (upstream.node() && upstream.node()->renderer() && upstream.node()->renderer()->isTable() && upstream.atLastEditingPositionForNode())
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return upstream.node();
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position downstream(visiblePosition.deepEquivalent().downstream());
5898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (downstream.node() && downstream.node()->renderer() && downstream.node()->renderer()->isTable() && downstream.atFirstEditingPositionForNode())
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return downstream.node();
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Returns the visible position at the beginning of a node
5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochVisiblePosition visiblePositionBeforeNode(Node* node)
5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(node);
5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (node->childNodeCount())
6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition(node, 0, DOWNSTREAM);
6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(node->parentNode());
602231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return positionInParentBeforeNode(node);
6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Returns the visible position at the ending of a node
6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochVisiblePosition visiblePositionAfterNode(Node* node)
6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(node);
6090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (node->childNodeCount())
6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition(node, node->childNodeCount(), DOWNSTREAM);
6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(node->parentNode());
612231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return positionInParentAfterNode(node);
6130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Create a range object with two visible positions, start and end.
6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// create(PassRefPtr<Document>, const Position&, const Position&); will use deprecatedEditingOffset
6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Use this function instead of create a regular range object (avoiding editing offset).
6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<Range> createRange(PassRefPtr<Document> document, const VisiblePosition& start, const VisiblePosition& end, ExceptionCode& ec)
6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ec = 0;
6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<Range> selectedRange = Range::create(document);
6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec);
6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!ec)
6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        selectedRange->setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return selectedRange.release();
6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Extend rangeToExtend to include nodes that wraps range and visibly starts and ends inside or at the boudnaries of maximumRange
6290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// e.g. if the original range spaned "hello" in <div>hello</div>, then this function extends the range to contain div's around it.
6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Call this function before copying / moving paragraphs to contain all wrapping nodes.
6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// This function stops extending the range immediately below rootNode; i.e. the extended range can contain a child node of rootNode
6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// but it can never contain rootNode itself.
6330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<Range> extendRangeToWrappingNodes(PassRefPtr<Range> range, const Range* maximumRange, const Node* rootNode)
6340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(range);
6360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(maximumRange);
6370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ExceptionCode ec = 0;
6390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Node* ancestor = range->commonAncestorContainer(ec);// find the cloeset common ancestor
6400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Node* highestNode = 0;
6410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // traverse through ancestors as long as they are contained within the range, content-editable, and below rootNode (could be =0).
6420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (ancestor && ancestor->isContentEditable() && isNodeVisiblyContainedWithin(ancestor, maximumRange) && ancestor != rootNode) {
6430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        highestNode = ancestor;
6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ancestor = ancestor->parentNode();
6450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
6460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!highestNode)
6480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return range;
6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Create new range with the highest editable node contained within the range
6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<Range> extendedRange = Range::create(range->ownerDocument());
6520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    extendedRange->selectNode(highestNode, ec);
6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return extendedRange.release();
6540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isListElement(Node *n)
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(dlTag)));
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockbool isListItem(Node *n)
6628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
6638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return n && n->renderer() && n->renderer()->isListItem();
6648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
6658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName)
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(p);
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode()) {
6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (root && !n->isContentEditable())
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(tagName))
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), bool onlyReturnEditableNodes)
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(p);
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode()) {
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Don't return a non-editable node if the input position was editable, since
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // the callers from editing will no doubt want to perform editing inside the returned node.
6930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (root && !n->isContentEditable() && onlyReturnEditableNodes)
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if ((*nodeIsOfType)(n))
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
704635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectNode* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*))
705635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
706635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Node* highest = 0;
707635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Node* root = highestEditableRoot(p);
708635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode()) {
709635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if ((*nodeIsOfType)(n))
710635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            highest = n;
711635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (n == root)
712635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            break;
713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
714635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
715635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return highest;
716635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
717635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingTableCell(const Position& p)
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
720635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return static_cast<Element*>(enclosingNodeOfType(p, isTableCell));
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingAnchorElement(const Position& p)
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (p.isNull())
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = p.node();
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (node && !(node->isElementNode() && node->isLink()))
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = node->parentNode();
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node;
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
734635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectHTMLElement* enclosingList(Node* node)
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(Position(node, 0));
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = node->parentNode(); n; n = n->parentNode()) {
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(ulTag) || n->hasTagName(olTag))
743635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return static_cast<HTMLElement*>(n);
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root)
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochHTMLElement* enclosingListChild(Node *node)
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check for a list item element, or for a node whose parent is a list element.  Such a node
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // will appear visually as a list item (but without a list marker)
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* root = highestEditableRoot(Position(node, 0));
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n->hasTagName(liTag) || isListElement(n->parentNode()))
7620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return static_cast<HTMLElement*>(n);
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (n == root || isTableCell(n))
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
770635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic HTMLElement* embeddedSublist(Node* listItem)
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the DOM so that we'll find collapsed sublists without renderers.
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isListElement(n))
775635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return static_cast<HTMLElement*>(n);
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Node* appendedSublist(Node* listItem)
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the DOM so that we'll find collapsed sublists without renderers.
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isListElement(n))
786635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return static_cast<HTMLElement*>(n);
7878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        if (isListItem(listItem))
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0;
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// FIXME: This method should not need to call isStartOfParagraph/isEndOfParagraph
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* enclosingEmptyListItem(const VisiblePosition& visiblePos)
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check that position is on a line by itself inside a list item
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().node());
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(visiblePos))
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
8018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    VisiblePosition firstInListChild(firstDeepEditingPositionForNode(listChildNode));
8038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    VisiblePosition lastInListChild(lastDeepEditingPositionForNode(listChildNode));
8048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (firstInListChild != visiblePos || lastInListChild != visiblePos)
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return listChildNode;
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
814635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectHTMLElement* outermostEnclosingList(Node* node)
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
816635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    HTMLElement* list = enclosingList(node);
817635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!list)
818635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
819635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while (HTMLElement* nextList = enclosingList(list))
820635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        list = nextList;
821635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return list;
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool canMergeLists(Element* firstList, Element* secondList)
8250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
8260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!firstList || !secondList)
8270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
8280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return firstList->hasTagName(secondList->tagQName())// make sure the list types match (ol vs. ul)
8300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    && firstList->isContentEditable() && secondList->isContentEditable()// both lists are editable
8310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    && firstList->rootEditableElement() == secondList->rootEditableElement()// don't cross editing boundaries
832231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    && isVisiblyAdjacent(positionInParentAfterNode(firstList), positionInParentBeforeNode(secondList));
8330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Make sure there is no visible content between this li and the previous list
8340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
8350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode* highestAncestor(Node* node)
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(node);
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* parent = node;
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((node = node->parentNode()))
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        parent = node;
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return parent;
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: do not require renderer, so that this can be used within fragments, or rename to isRenderedTable()
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableElement(Node* n)
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!n || !n->isElementNode())
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* renderer = n->renderer();
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (renderer && (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE));
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTableCell(const Node* node)
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = node->renderer();
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!r)
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return node->hasTagName(tdTag) || node->hasTagName(thTag);
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return r->isTableCell();
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
864d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool isEmptyTableCell(const Node* node)
865d0825bca7fe65beaee391d30da42e937db621564Steve Block{
866d0825bca7fe65beaee391d30da42e937db621564Steve Block    return node && node->renderer() && (node->renderer()->isTableCell() || (node->renderer()->isBR() && node->parentNode()->renderer() && node->parentNode()->renderer()->isTableCell()));
867d0825bca7fe65beaee391d30da42e937db621564Steve Block}
868d0825bca7fe65beaee391d30da42e937db621564Steve Block
869635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createDefaultParagraphElement(Document* document)
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
871635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return new HTMLDivElement(divTag, document);
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
874635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createBreakElement(Document* document)
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
876635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return new HTMLBRElement(brTag, document);
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
879635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createOrderedListElement(Document* document)
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
881635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return new HTMLOListElement(olTag, document);
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
884635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createUnorderedListElement(Document* document)
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
886635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return new HTMLUListElement(ulTag, document);
8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
889635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createListItemElement(Document* document)
8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
891635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return new HTMLLIElement(liTag, document);
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
894635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createHTMLElement(Document* document, const QualifiedName& name)
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
896635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return HTMLElementFactory::createHTMLElement(name, document, 0, false);
897635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
898635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
899635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectPassRefPtr<HTMLElement> createHTMLElement(Document* document, const AtomicString& tagName)
900635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
901635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return createHTMLElement(document, QualifiedName(nullAtom, tagName, xhtmlNamespaceURI));
9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTabSpanNode(const Node *node)
9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->hasTagName(spanTag) && node->isElementNode() && static_cast<const Element *>(node)->getAttribute(classAttr) == AppleTabSpanClass;
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isTabSpanTextNode(const Node *node)
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return node && node->isTextNode() && node->parentNode() && isTabSpanNode(node->parentNode());
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode *tabSpanNode(const Node *node)
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return isTabSpanTextNode(node) ? node->parentNode() : 0;
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockbool isNodeInTextFormControl(Node* node)
9208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
9218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!node)
9228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return false;
9238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    Node* ancestor = node->shadowAncestorNode();
9248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (ancestor == node)
9258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return false;
9268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return ancestor->isElementNode() && static_cast<Element*>(ancestor)->isTextFormControl();
9278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
9288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPosition positionBeforeTabSpan(const Position& pos)
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node *node = pos.node();
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isTabSpanTextNode(node))
9338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        node = tabSpanNode(node);
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (!isTabSpanNode(node))
9358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return pos;
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
937231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return positionInParentBeforeNode(node);
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document, PassRefPtr<Node> tabTextNode)
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Make the span to hold the tab.
9438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<Element> spanElement = document->createElement(spanTag, false);
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->setAttribute(classAttr, AppleTabSpanClass);
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->setAttribute(styleAttr, "white-space:pre");
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Add tab text to that span.
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!tabTextNode)
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        tabTextNode = document->createEditingTextNode("\t");
9508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ExceptionCode ec = 0;
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    spanElement->appendChild(tabTextNode, ec);
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(ec == 0);
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return spanElement.release();
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document, const String& tabText)
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return createTabSpanElement(document, document->createTextNode(tabText));
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Element> createTabSpanElement(Document* document)
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return createTabSpanElement(document, PassRefPtr<Node>());
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isNodeRendered(const Node *node)
9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node)
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject *renderer = node->renderer();
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return renderer->style()->visibility() == VISIBLE;
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNode *nearestMailBlockquote(const Node *node)
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node *n = const_cast<Node *>(node); n; n = n->parentNode()) {
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isMailBlockquote(n))
9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return n;
9858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
989635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectunsigned numEnclosingMailBlockquotes(const Position& p)
990635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
991635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    unsigned num = 0;
992635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (Node* n = p.node(); n; n = n->parentNode())
993635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (isMailBlockquote(n))
994635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            num++;
995635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
996635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return num;
997635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
998635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool isMailBlockquote(const Node *node)
10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1001d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!node || !node->hasTagName(blockquoteTag))
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return static_cast<const Element *>(node)->getAttribute("type") == "cite";
10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint caretMinOffset(const Node* n)
10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* r = n->renderer();
10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The 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.
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return r ? r->caretMinOffset() : 0;
10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1014635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise
1015635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// return the number of children for container nodes and the length for unrendered text nodes.
10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint caretMaxOffset(const Node* n)
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1018635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // For rendered text nodes, return the last position that a caret could occupy.
1019635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (n->isTextNode() && n->renderer())
1020635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return n->renderer()->caretMaxOffset();
1021635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // For containers return the number of children.  For others do the same as above.
10228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return lastOffsetForEditing(n);
10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition)
10268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream());
10285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
10295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool lineBreakExistsAtPosition(const Position& position)
10315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
10325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (position.isNull())
10338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
10345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPositionForNode())
10365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return true;
10375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer()->style()->preserveNewline())
10395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
10405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Text* textNode = static_cast<Text*>(position.anchorNode());
10425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned offset = position.offsetInContainerNode();
10435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return offset < textNode->length() && textNode->data()[offset] == '\n';
10448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Modifies selections that have an end point at the edge of a table
10478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// that contains the other endpoint so that they don't confuse
10488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// code that iterates over selected paragraphs.
10498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisibleSelection selectionForParagraphIteration(const VisibleSelection& original)
10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    VisibleSelection newSelection(original);
10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition startOfSelection(newSelection.visibleStart());
10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    VisiblePosition endOfSelection(newSelection.visibleEnd());
10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the end of the selection to modify is just after a table, and
10568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if the start of the selection is inside that table, then the last paragraph
10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // that we'll want modify is the last one inside the table, not the table itself
10588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // (a table is itself a paragraph).
10598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* table = isFirstPositionAfterTable(endOfSelection))
10608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (startOfSelection.deepEquivalent().node()->isDescendantOf(table))
10618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            newSelection = VisibleSelection(startOfSelection, endOfSelection.previous(true));
10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the start of the selection to modify is just before a table,
10648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and if the end of the selection is inside that table, then the first paragraph
10658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we'll want to modify is the first one inside the table, not the paragraph
10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // containing the table itself.
10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (Node* table = isLastPositionBeforeTable(startOfSelection))
10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endOfSelection.deepEquivalent().node()->isDescendantOf(table))
10698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            newSelection = VisibleSelection(startOfSelection.next(true), endOfSelection);
10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return newSelection;
10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint indexForVisiblePosition(const VisiblePosition& visiblePosition)
10768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (visiblePosition.isNull())
10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Position p(visiblePosition.deepEquivalent());
10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Range> range = Range::create(p.node()->document(), Position(p.node()->document(), 0), rangeCompliantEquivalent(p));
10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return TextIterator::rangeLength(range.get(), true);
10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Determines whether two positions are visibly next to each other (first then second)
10850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// while ignoring whitespaces and unrendered nodes
10860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool isVisiblyAdjacent(const Position& first, const Position& second)
10870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return VisiblePosition(first) == VisiblePosition(second.upstream());
10890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
10900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range.
10920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Call this function to determine whether a node is visibly fit inside selectedRange
10930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool isNodeVisiblyContainedWithin(Node* node, const Range* selectedRange)
10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
10950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(node);
10960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(selectedRange);
10970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If the node is inside the range, then it surely is contained within
10980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ExceptionCode ec = 0;
10990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (selectedRange->compareNode(node, ec) == Range::NODE_INSIDE)
11000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
11010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If the node starts and ends at where selectedRange starts and ends, the node is contained within
11030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return visiblePositionBeforeNode(node) == selectedRange->startPosition()
11040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        && visiblePositionAfterNode(node) == selectedRange->endPosition();
11050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
11060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1107643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool isRenderedAsNonInlineTableImageOrHR(const Node* node)
1108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
1109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!node)
1110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return false;
1111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    RenderObject* renderer = node->renderer();
1112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return renderer && ((renderer->isTable() && !renderer->isInline()) || (renderer->isImage() && !renderer->isInline()) || renderer->isHR());
1113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
1114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<Range> avoidIntersectionWithNode(const Range* range, Node* node)
11168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
11178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!range)
11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Document* document = range->ownerDocument();
11218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* startContainer = range->startContainer();
11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int startOffset = range->startOffset();
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* endContainer = range->endContainer();
11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int endOffset = range->endOffset();
11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!startContainer)
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(endContainer);
11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (startContainer == node || startContainer->isDescendantOf(node)) {
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startContainer = node->parentNode();
11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startOffset = node->nodeIndex();
11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (endContainer == node || endContainer->isDescendantOf(node)) {
11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endContainer = node->parentNode();
11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        endOffset = node->nodeIndex();
11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Range::create(document, startContainer, startOffset, endContainer, endOffset);
11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianVisibleSelection avoidIntersectionWithNode(const VisibleSelection& selection, Node* node)
11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (selection.isNone())
11498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return VisibleSelection(selection);
11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    VisibleSelection updatedSelection(selection);
11528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* base = selection.base().node();
11538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* extent = selection.extent().node();
11548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(base);
11558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(extent);
11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (base == node || base->isDescendantOf(node)) {
11588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
11598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updatedSelection.setBase(Position(node->parentNode(), node->nodeIndex()));
11608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (extent == node || extent->isDescendantOf(node)) {
11638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(node->parentNode());
11648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updatedSelection.setExtent(Position(node->parentNode(), node->nodeIndex()));
11658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return updatedSelection;
11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
1171