blob: c1a4625ffddae4b5b7c32483f07533a7cf14a90a [file] [log] [blame]
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001/*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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
Ben Murdoch02772c62013-07-26 10:21:05 +010023 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010024 */
25
26#ifndef RangeBoundaryPoint_h
27#define RangeBoundaryPoint_h
28
29#include "core/dom/Node.h"
30#include "core/dom/Position.h"
31
32namespace WebCore {
33
34class RangeBoundaryPoint {
35public:
36 explicit RangeBoundaryPoint(PassRefPtr<Node> container);
37
Ben Murdoch591b9582013-07-10 11:41:44 +010038 explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
39
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010040 const Position toPosition() const;
41
42 Node* container() const;
43 int offset() const;
44 Node* childBefore() const;
45
46 void clear();
47
48 void set(PassRefPtr<Node> container, int offset, Node* childBefore);
49 void setOffset(int offset);
50
51 void setToBeforeChild(Node*);
52 void setToStartOfNode(PassRefPtr<Node>);
53 void setToEndOfNode(PassRefPtr<Node>);
54
55 void childBeforeWillBeRemoved();
56 void invalidateOffset() const;
57 void ensureOffsetIsValid() const;
58
59private:
60 static const int invalidOffset = -1;
Ben Murdoch591b9582013-07-10 11:41:44 +010061
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010062 RefPtr<Node> m_containerNode;
63 mutable int m_offsetInContainer;
64 RefPtr<Node> m_childBeforeBoundary;
65};
66
67inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
68 : m_containerNode(container)
69 , m_offsetInContainer(0)
70 , m_childBeforeBoundary(0)
71{
72 ASSERT(m_containerNode);
73}
74
Ben Murdoch591b9582013-07-10 11:41:44 +010075inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
76 : m_containerNode(other.container())
77 , m_offsetInContainer(other.offset())
78 , m_childBeforeBoundary(other.childBefore())
79{
80}
81
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010082inline Node* RangeBoundaryPoint::container() const
83{
84 return m_containerNode.get();
85}
86
87inline Node* RangeBoundaryPoint::childBefore() const
88{
89 return m_childBeforeBoundary.get();
90}
91
92inline void RangeBoundaryPoint::ensureOffsetIsValid() const
93{
94 if (m_offsetInContainer >= 0)
95 return;
96
97 ASSERT(m_childBeforeBoundary);
98 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
99}
100
101inline const Position RangeBoundaryPoint::toPosition() const
102{
103 ensureOffsetIsValid();
104 return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
105}
106
107inline int RangeBoundaryPoint::offset() const
108{
109 ensureOffsetIsValid();
110 return m_offsetInContainer;
111}
112
113inline void RangeBoundaryPoint::clear()
114{
115 m_containerNode.clear();
116 m_offsetInContainer = 0;
117 m_childBeforeBoundary = 0;
118}
119
120inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
121{
122 ASSERT(container);
123 ASSERT(offset >= 0);
124 ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0));
125 m_containerNode = container;
126 m_offsetInContainer = offset;
127 m_childBeforeBoundary = childBefore;
128}
129
130inline void RangeBoundaryPoint::setOffset(int offset)
131{
132 ASSERT(m_containerNode);
133 ASSERT(m_containerNode->offsetInCharacters());
134 ASSERT(m_offsetInContainer >= 0);
135 ASSERT(!m_childBeforeBoundary);
136 m_offsetInContainer = offset;
137}
138
139inline void RangeBoundaryPoint::setToBeforeChild(Node* child)
140{
141 ASSERT(child);
142 ASSERT(child->parentNode());
143 m_childBeforeBoundary = child->previousSibling();
144 m_containerNode = child->parentNode();
145 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
146}
147
148inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
149{
150 ASSERT(container);
151 m_containerNode = container;
152 m_offsetInContainer = 0;
153 m_childBeforeBoundary = 0;
154}
155
156inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
157{
158 ASSERT(container);
159 m_containerNode = container;
160 if (m_containerNode->offsetInCharacters()) {
161 m_offsetInContainer = m_containerNode->maxCharacterOffset();
162 m_childBeforeBoundary = 0;
163 } else {
164 m_childBeforeBoundary = m_containerNode->lastChild();
165 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
166 }
167}
168
169inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
170{
171 ASSERT(m_offsetInContainer);
172 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
173 if (!m_childBeforeBoundary)
174 m_offsetInContainer = 0;
175 else if (m_offsetInContainer > 0)
176 --m_offsetInContainer;
177}
178
179inline void RangeBoundaryPoint::invalidateOffset() const
180{
181 m_offsetInContainer = invalidOffset;
182}
183
184inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
185{
186 if (a.container() != b.container())
187 return false;
188 if (a.childBefore() || b.childBefore()) {
189 if (a.childBefore() != b.childBefore())
190 return false;
191 } else {
192 if (a.offset() != b.offset())
193 return false;
194 }
195 return true;
196}
197
198}
199
200#endif