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