15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef Position_h 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define Position_h 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ContainerNode.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/EditingBoundary.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/TextAffinity.h" 321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextDirection.h" 33e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/Assertions.h" 34e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/PassRefPtr.h" 35e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/RefPtr.h" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class CSSComputedStyleDeclaration; 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Element; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class InlineBox; 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Node; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Range; 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class RenderObject; 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Text; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum PositionMoveType { 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CodePoint, // Move by a single code point. 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Character, // Move to the next Unicode character break. 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BackwardDeletion // Subject to platform conventions. 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Position { 54f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) DISALLOW_ALLOCATION(); 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enum AnchorType { 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PositionIsOffsetInAnchor, 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PositionIsBeforeAnchor, 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PositionIsAfterAnchor, 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PositionIsBeforeChildren, 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PositionIsAfterChildren, 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position() 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_offset(0) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_anchorType(PositionIsOffsetInAnchor) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isLegacyEditingPosition(false) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For creating legacy editing positions: (Anchor type will be determined from editingIgnoresContent(node)) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) class LegacyEditingOffset { 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) public: 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int value() const { return m_offset; } 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) private: 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) explicit LegacyEditingOffset(int offset) : m_offset(offset) { } 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 79f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) friend Position createLegacyEditingPosition(PassRefPtrWillBeRawPtr<Node>, int offset); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int m_offset; 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 83f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) Position(PassRefPtrWillBeRawPtr<Node> anchorNode, LegacyEditingOffset); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For creating before/after positions: 86f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) Position(PassRefPtrWillBeRawPtr<Node> anchorNode, AnchorType); 87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) Position(PassRefPtrWillBeRawPtr<Text> textNode, unsigned offset); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For creating offset positions: 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This constructor should eventually go away. See bug 63040. 91f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) Position(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset, AnchorType); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AnchorType anchorType() const { return static_cast<AnchorType>(m_anchorType); } 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void clear() { m_anchorNode.clear(); m_offset = 0; m_anchorType = PositionIsOffsetInAnchor; m_isLegacyEditingPosition = false; } 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These are always DOM compliant values. Editing positions like [img, 0] (aka [img, before]) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will return img->parentNode() and img->nodeIndex() from these functions. 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* containerNode() const; // NULL for a before/after position anchored to a node with no parent 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Text* containerText() const; 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int computeOffsetInContainerNode() const; // O(n) for before/after-anchored positions, O(1) for parent-anchored positions 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position parentAnchoredEquivalent() const; // Convenience method for DOM positions that also fixes up some positions for editing 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Inline O(1) access for Positions which callers know to be parent-anchored 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int offsetInContainerNode() const 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(anchorType() == PositionIsOffsetInAnchor); 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_offset; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // New code should not use this function. 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int deprecatedEditingOffset() const 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_isLegacyEditingPosition || (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_offset; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return offsetForPositionAfterAnchor(); 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These are convenience methods which are smart about whether the position is neighbor anchored or parent anchored 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* computeNodeBeforePosition() const; 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* computeNodeAfterPosition() const; 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* anchorNode() const { return m_anchorNode.get(); } 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Callers should be moved off of node(), node() is not always the container for this position. 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For nodes which editingIgnoresContent(node()) returns true, positions like [ignoredNode, 0] 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will be treated as before ignoredNode (thus node() is really after the position, not containing it). 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* deprecatedNode() const { return m_anchorNode.get(); } 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1318abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) Document* document() const { return m_anchorNode ? &m_anchorNode->document() : 0; } 1328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) bool inDocument() const { return m_anchorNode && m_anchorNode->inDocument(); } 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Element* rootEditableElement() const 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* container = containerNode(); 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return container ? container->rootEditableElement() : 0; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These should only be used for PositionIsOffsetInAnchor positions, unless 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the position is a legacy editing position. 141f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) void moveToPosition(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void moveToOffset(int offset); 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isNull() const { return !m_anchorNode; } 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isNotNull() const { return m_anchorNode; } 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isOrphan() const { return m_anchorNode && !m_anchorNode->inDocument(); } 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Element* element() const; 149323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) PassRefPtrWillBeRawPtr<CSSComputedStyleDeclaration> computedStyle() const; 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Move up or down the DOM by one position. 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Offsets are computed using render text for nodes that have renderers - but note that even when 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // using composed characters, the result may be inside a single user-visible character if a ligature is formed. 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position previous(PositionMoveType = CodePoint) const; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position next(PositionMoveType = CodePoint) const; 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static int uncheckedPreviousOffset(const Node*, int current); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static int uncheckedPreviousOffsetForBackwardDeletion(const Node*, int current); 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static int uncheckedNextOffset(const Node*, int current); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These can be either inside or just before/after the node, depending on 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // if the node is ignored by editing or not. 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: These should go away. They only make sense for legacy positions. 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atFirstEditingPositionForNode() const; 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atLastEditingPositionForNode() const; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Returns true if the visually equivalent positions around have different editability 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atEditingBoundary() const; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* parentEditingBoundary() const; 16902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atStartOfTree() const; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atEndOfTree() const; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Make these non-member functions and put them somewhere in the editing directory. 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These aren't really basic "position" operations. More high level editing helper functions. 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position leadingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace = false) const; 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position trailingWhitespacePosition(EAffinity, bool considerNonCollapsibleWhitespace = false) const; 17702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These return useful visually equivalent positions. 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position upstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const; 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position downstream(EditingBoundaryCrossingRule = CannotCrossEditingBoundary) const; 18102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isCandidate() const; 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool inRenderedText() const; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isRenderedCharacter() const; 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool rendersInDifferentPosition(const Position&) const; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void getInlineBoxAndOffset(EAffinity, InlineBox*&, int& caretOffset) const; 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void getInlineBoxAndOffset(EAffinity, TextDirection primaryDirection, InlineBox*&, int& caretOffset) const; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TextDirection primaryDirection() const; 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject*); 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static bool nodeIsUserSelectNone(Node*); 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static bool nodeIsUserSelectAll(const Node*); 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static Node* rootUserSelectAllForNode(Node*); 1963c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static ContainerNode* findParent(const Node*); 19802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void debugPosition(const char* msg = "") const; 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void formatForDebugger(char* buffer, unsigned length) const; 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void showAnchorTypeAndOffset() const; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void showTreeForThis() const; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 20602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 207f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) void trace(Visitor*); 208f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int offsetForPositionAfterAnchor() const; 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int renderedOffset() const; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position previousCharacterPosition(EAffinity) const; 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static AnchorType anchorTypeForLegacyEditingPosition(Node* anchorNode, int offset); 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 218f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RefPtrWillBeMember<Node> m_anchorNode; 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m_offset can be the offset inside m_anchorNode, or if editingIgnoresContent(m_anchorNode) 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // returns true, then other places in editing will treat m_offset == 0 as "before the anchor" 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and m_offset > 0 as "after the anchor node". See parentAnchoredEquivalent for more info. 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int m_offset; 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned m_anchorType : 3; 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool m_isLegacyEditingPosition : 1; 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 227f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)inline Position createLegacyEditingPosition(PassRefPtrWillBeRawPtr<Node> node, int offset) 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(node, Position::LegacyEditingOffset(offset)); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator==(const Position& a, const Position& b) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // editing code will treat them as identical. 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset() && a.anchorType() == b.anchorType(); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator!=(const Position& a, const Position& b) 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !(a == b); 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// We define position creation functions to make callsites more readable. 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// These are inline to prevent ref-churn when returning a Position object. 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// If we ever add a PassPosition we can make these non-inline. 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 248d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)inline Position positionInParentBeforeNode(const Node& node) 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 250d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // FIXME: This should ASSERT(node.parentNode()) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // At least one caller currently hits this ASSERT though, which indicates 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // that the caller is trying to make a position relative to a disconnected node (which is likely an error) 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Specifically, editing/deleting/delete-ligature-001.html crashes with ASSERT(node->parentNode()) 254d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return Position(node.parentNode(), node.nodeIndex(), Position::PositionIsOffsetInAnchor); 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 257d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)inline Position positionInParentAfterNode(const Node& node) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 259d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT(node.parentNode()); 260d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return Position(node.parentNode(), node.nodeIndex() + 1, Position::PositionIsOffsetInAnchor); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// positionBeforeNode and positionAfterNode return neighbor-anchored positions, construction is O(1) 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline Position positionBeforeNode(Node* anchorNode) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(anchorNode); 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, Position::PositionIsBeforeAnchor); 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline Position positionAfterNode(Node* anchorNode) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(anchorNode); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, Position::PositionIsAfterAnchor); 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline int lastOffsetInNode(Node* node) 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 278d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return node->offsetInCharacters() ? node->maxCharacterOffset() : static_cast<int>(node->countChildren()); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to countChildren() 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline Position firstPositionInNode(Node* anchorNode) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (anchorNode->isTextNode()) 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, 0, Position::PositionIsOffsetInAnchor); 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, Position::PositionIsBeforeChildren); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline Position lastPositionInNode(Node* anchorNode) 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (anchorNode->isTextNode()) 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor); 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(anchorNode, Position::PositionIsAfterChildren); 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline int minOffsetForNode(Node* anchorNode, int offset) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (anchorNode->offsetInCharacters()) 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return std::min(offset, anchorNode->maxCharacterOffset()); 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int newOffset = 0; 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Node* node = anchorNode->firstChild(); node && newOffset < offset; node = node->nextSibling()) 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newOffset++; 30402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return newOffset; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (anchorNode->offsetInCharacters()) 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return offset < anchorNode->maxCharacterOffset(); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int currentOffset = 0; 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Node* node = anchorNode->firstChild(); node && currentOffset < offset; node = node->nextSibling()) 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) currentOffset++; 31602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 31702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return offset < currentOffset; 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 321f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)class PositionWithAffinity { 322f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) DISALLOW_ALLOCATION(); 323f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)public: 324f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) PositionWithAffinity() 325f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) : m_affinity(DOWNSTREAM) 326f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) { 327f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 328f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 329f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) PositionWithAffinity(const Position& position, EAffinity affinity = DOWNSTREAM) 330f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) : m_position(position) 331f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) , m_affinity(affinity) 332f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) { 333f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 334f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 335f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) EAffinity affinity() const { return m_affinity; } 336f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) const Position& position() const { return m_position; } 337f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 338f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) void trace(Visitor* visitor) 339f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) { 340f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) visitor->trace(m_position); 341f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 342f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 343f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)private: 344f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) Position m_position; 345f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) EAffinity m_affinity; 346f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}; 347f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Outside the WebCore namespace for ease of invocation from gdb. 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void showTree(const WebCore::Position&); 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void showTree(const WebCore::Position*); 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // Position_h 357