Text::splitText doesn't update Range end points anchored on parent nodes
[WebKit.git] / Source / WebCore / dom / RangeBoundaryPoint.h
1 /*
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
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef RangeBoundaryPoint_h
27 #define RangeBoundaryPoint_h
28
29 #include "Node.h"
30 #include "Position.h"
31
32 namespace WebCore {
33
34 class RangeBoundaryPoint {
35 public:
36     explicit RangeBoundaryPoint(PassRefPtr<Node> container);
37
38     explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
39
40     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 setToAfterChild(Node&);
53     void setToStartOfNode(PassRefPtr<Node>);
54     void setToEndOfNode(PassRefPtr<Node>);
55
56     void childBeforeWillBeRemoved();
57     void invalidateOffset() const;
58     void ensureOffsetIsValid() const;
59
60 private:
61     static const int invalidOffset = -1;
62
63     RefPtr<Node> m_containerNode;
64     mutable int m_offsetInContainer { 0 };
65     RefPtr<Node> m_childBeforeBoundary;
66 };
67
68 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container)
69     : m_containerNode(container)
70 {
71     ASSERT(m_containerNode);
72 }
73
74 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
75     : m_containerNode(other.container())
76     , m_offsetInContainer(other.offset())
77     , m_childBeforeBoundary(other.childBefore())
78 {
79 }
80
81 inline Node* RangeBoundaryPoint::container() const
82 {
83     return m_containerNode.get();
84 }
85
86 inline Node* RangeBoundaryPoint::childBefore() const
87 {
88     return m_childBeforeBoundary.get();
89 }
90
91 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
92 {
93     if (m_offsetInContainer >= 0)
94         return;
95
96     ASSERT(m_childBeforeBoundary);
97     m_offsetInContainer = m_childBeforeBoundary->computeNodeIndex() + 1;
98 }
99
100 inline const Position RangeBoundaryPoint::toPosition() const
101 {
102     ensureOffsetIsValid();
103     return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer);
104 }
105
106 inline int RangeBoundaryPoint::offset() const
107 {
108     ensureOffsetIsValid();
109     return m_offsetInContainer;
110 }
111
112 inline void RangeBoundaryPoint::clear()
113 {
114     m_containerNode = nullptr;
115     m_offsetInContainer = 0;
116     m_childBeforeBoundary = nullptr;
117 }
118
119 inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node* childBefore)
120 {
121     ASSERT(container);
122     ASSERT(offset >= 0);
123     ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0));
124     m_containerNode = container;
125     m_offsetInContainer = offset;
126     m_childBeforeBoundary = childBefore;
127 }
128
129 inline void RangeBoundaryPoint::setOffset(int offset)
130 {
131     ASSERT(m_containerNode);
132     ASSERT(m_containerNode->offsetInCharacters());
133     ASSERT(m_offsetInContainer >= 0);
134     ASSERT(!m_childBeforeBoundary);
135     m_offsetInContainer = offset;
136 }
137
138 inline void RangeBoundaryPoint::setToBeforeChild(Node& child)
139 {
140     ASSERT(child.parentNode());
141     m_childBeforeBoundary = child.previousSibling();
142     m_containerNode = child.parentNode();
143     m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
144 }
145
146 inline void RangeBoundaryPoint::setToAfterChild(Node& child)
147 {
148     ASSERT(child.parentNode());
149     m_childBeforeBoundary = &child;
150     m_containerNode = child.parentNode();
151     m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
152 }
153
154 inline void RangeBoundaryPoint::setToStartOfNode(PassRefPtr<Node> container)
155 {
156     ASSERT(container);
157     m_containerNode = container;
158     m_offsetInContainer = 0;
159     m_childBeforeBoundary = nullptr;
160 }
161
162 inline void RangeBoundaryPoint::setToEndOfNode(PassRefPtr<Node> container)
163 {
164     ASSERT(container);
165     m_containerNode = container;
166     if (m_containerNode->offsetInCharacters()) {
167         m_offsetInContainer = m_containerNode->maxCharacterOffset();
168         m_childBeforeBoundary = nullptr;
169     } else {
170         m_childBeforeBoundary = m_containerNode->lastChild();
171         m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
172     }
173 }
174
175 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
176 {
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;
183 }
184
185 inline void RangeBoundaryPoint::invalidateOffset() const
186 {
187     m_offsetInContainer = invalidOffset;
188 }
189
190 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
191 {
192     if (a.container() != b.container())
193         return false;
194     if (a.childBefore() || b.childBefore()) {
195         if (a.childBefore() != b.childBefore())
196             return false;
197     } else {
198         if (a.offset() != b.offset())
199             return false;
200     }
201     return true;
202 }
203
204 }
205
206 #endif