2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef RangeBoundaryPoint_h
27 #define RangeBoundaryPoint_h
34 class RangeBoundaryPoint {
36 explicit RangeBoundaryPoint(PassRefPtr<Node> container);
38 explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
40 const Position toPosition() const;
42 Node* container() const;
44 Node* childBefore() const;
48 void set(PassRefPtr<Node> container, int offset, Node* childBefore);
49 void setOffset(int offset);
51 void setToBeforeChild(Node&);
52 void setToAfterChild(Node&);
53 void setToStartOfNode(PassRefPtr<Node>);
54 void setToEndOfNode(PassRefPtr<Node>);
56 void childBeforeWillBeRemoved();
57 void invalidateOffset() const;
58 void ensureOffsetIsValid() const;
61 static const int invalidOffset = -1;
63 RefPtr<Node> m_containerNode;
64 mutable int m_offsetInContainer { 0 };
65 RefPtr<Node> m_childBeforeBoundary;
68 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
69 : m_containerNode(container)
71 ASSERT(m_containerNode);
74 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
75 : m_containerNode(other.container())
76 , m_offsetInContainer(other.offset())
77 , m_childBeforeBoundary(other.childBefore())
81 inline Node* RangeBoundaryPoint::container() const
83 return m_containerNode.get();
86 inline Node* RangeBoundaryPoint::childBefore() const
88 return m_childBeforeBoundary.get();
91 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
93 if (m_offsetInContainer >= 0)
96 ASSERT(m_childBeforeBoundary);
97 m_offsetInContainer = m_childBeforeBoundary->computeNodeIndex() + 1;
100 inline const Position RangeBoundaryPoint::toPosition() const
102 ensureOffsetIsValid();
103 return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
106 inline int RangeBoundaryPoint::offset() const
108 ensureOffsetIsValid();
109 return m_offsetInContainer;
112 inline void RangeBoundaryPoint::clear()
114 m_containerNode = nullptr;
115 m_offsetInContainer = 0;
116 m_childBeforeBoundary = nullptr;
119 inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
123 ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0));
124 m_containerNode = container;
125 m_offsetInContainer = offset;
126 m_childBeforeBoundary = childBefore;
129 inline void RangeBoundaryPoint::setOffset(int offset)
131 ASSERT(m_containerNode);
132 ASSERT(m_containerNode->offsetInCharacters());
133 ASSERT(m_offsetInContainer >= 0);
134 ASSERT(!m_childBeforeBoundary);
135 m_offsetInContainer = offset;
138 inline void RangeBoundaryPoint::setToBeforeChild(Node& child)
140 ASSERT(child.parentNode());
141 m_childBeforeBoundary = child.previousSibling();
142 m_containerNode = child.parentNode();
143 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
146 inline void RangeBoundaryPoint::setToAfterChild(Node& child)
148 ASSERT(child.parentNode());
149 m_childBeforeBoundary = &child;
150 m_containerNode = child.parentNode();
151 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
154 inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
157 m_containerNode = container;
158 m_offsetInContainer = 0;
159 m_childBeforeBoundary = nullptr;
162 inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
165 m_containerNode = container;
166 if (m_containerNode->offsetInCharacters()) {
167 m_offsetInContainer = m_containerNode->maxCharacterOffset();
168 m_childBeforeBoundary = nullptr;
170 m_childBeforeBoundary = m_containerNode->lastChild();
171 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
175 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
177 ASSERT(m_offsetInContainer);
178 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
179 if (!m_childBeforeBoundary)
180 m_offsetInContainer = 0;
181 else if (m_offsetInContainer > 0)
182 --m_offsetInContainer;
185 inline void RangeBoundaryPoint::invalidateOffset() const
187 m_offsetInContainer = invalidOffset;
190 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
192 if (a.container() != b.container())
194 if (a.childBefore() || b.childBefore()) {
195 if (a.childBefore() != b.childBefore())
198 if (a.offset() != b.offset())