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
29 #include "core/dom/Node.h"
30 #include "core/dom/NodeTraversal.h"
31 #include "core/editing/Position.h"
35 class RangeBoundaryPoint
{
36 DISALLOW_ALLOCATION();
38 explicit RangeBoundaryPoint(PassRefPtrWillBeRawPtr
<Node
> container
);
40 explicit RangeBoundaryPoint(const RangeBoundaryPoint
&);
42 const Position
toPosition() const;
44 Node
* container() const;
46 Node
* childBefore() const;
50 void set(PassRefPtrWillBeRawPtr
<Node
> container
, int offset
, Node
* childBefore
);
53 void setToBeforeChild(Node
&);
54 void setToStartOfNode(Node
&);
55 void setToEndOfNode(Node
&);
57 void childBeforeWillBeRemoved();
58 void invalidateOffset() const;
59 void ensureOffsetIsValid() const;
63 visitor
->trace(m_containerNode
);
64 visitor
->trace(m_childBeforeBoundary
);
68 static const int invalidOffset
= -1;
70 RefPtrWillBeMember
<Node
> m_containerNode
;
71 mutable int m_offsetInContainer
;
72 RefPtrWillBeMember
<Node
> m_childBeforeBoundary
;
75 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtrWillBeRawPtr
<Node
> container
)
76 : m_containerNode(container
)
77 , m_offsetInContainer(0)
78 , m_childBeforeBoundary(nullptr)
80 ASSERT(m_containerNode
);
83 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint
& other
)
84 : m_containerNode(other
.container())
85 , m_offsetInContainer(other
.offset())
86 , m_childBeforeBoundary(other
.childBefore())
90 inline Node
* RangeBoundaryPoint::container() const
92 return m_containerNode
.get();
95 inline Node
* RangeBoundaryPoint::childBefore() const
97 return m_childBeforeBoundary
.get();
100 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
102 if (m_offsetInContainer
>= 0)
105 ASSERT(m_childBeforeBoundary
);
106 m_offsetInContainer
= m_childBeforeBoundary
->nodeIndex() + 1;
109 inline const Position
RangeBoundaryPoint::toPosition() const
111 ensureOffsetIsValid();
112 return Position::editingPositionOf(m_containerNode
.get(), m_offsetInContainer
);
115 inline int RangeBoundaryPoint::offset() const
117 ensureOffsetIsValid();
118 return m_offsetInContainer
;
121 inline void RangeBoundaryPoint::clear()
123 m_containerNode
.clear();
124 m_offsetInContainer
= 0;
125 m_childBeforeBoundary
= nullptr;
128 inline void RangeBoundaryPoint::set(PassRefPtrWillBeRawPtr
<Node
> container
, int offset
, Node
* childBefore
)
132 ASSERT(childBefore
== (offset
? NodeTraversal::childAt(*container
, offset
- 1) : 0));
133 m_containerNode
= container
;
134 m_offsetInContainer
= offset
;
135 m_childBeforeBoundary
= childBefore
;
138 inline void RangeBoundaryPoint::setOffset(int offset
)
140 ASSERT(m_containerNode
);
141 ASSERT(m_containerNode
->offsetInCharacters());
142 ASSERT(m_offsetInContainer
>= 0);
143 ASSERT(!m_childBeforeBoundary
);
144 m_offsetInContainer
= offset
;
147 inline void RangeBoundaryPoint::setToBeforeChild(Node
& child
)
149 ASSERT(child
.parentNode());
150 m_childBeforeBoundary
= child
.previousSibling();
151 m_containerNode
= child
.parentNode();
152 m_offsetInContainer
= m_childBeforeBoundary
? invalidOffset
: 0;
155 inline void RangeBoundaryPoint::setToStartOfNode(Node
& container
)
157 m_containerNode
= &container
;
158 m_offsetInContainer
= 0;
159 m_childBeforeBoundary
= nullptr;
162 inline void RangeBoundaryPoint::setToEndOfNode(Node
& container
)
164 m_containerNode
= &container
;
165 if (m_containerNode
->offsetInCharacters()) {
166 m_offsetInContainer
= m_containerNode
->maxCharacterOffset();
167 m_childBeforeBoundary
= nullptr;
169 m_childBeforeBoundary
= m_containerNode
->lastChild();
170 m_offsetInContainer
= m_childBeforeBoundary
? invalidOffset
: 0;
174 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
176 ASSERT(m_offsetInContainer
);
177 m_childBeforeBoundary
= m_childBeforeBoundary
->previousSibling();
178 if (!m_childBeforeBoundary
)
179 m_offsetInContainer
= 0;
180 else if (m_offsetInContainer
> 0)
181 --m_offsetInContainer
;
184 inline void RangeBoundaryPoint::invalidateOffset() const
186 m_offsetInContainer
= invalidOffset
;
189 inline bool operator==(const RangeBoundaryPoint
& a
, const RangeBoundaryPoint
& b
)
191 if (a
.container() != b
.container())
193 if (a
.childBefore() || b
.childBefore()) {
194 if (a
.childBefore() != b
.childBefore())
197 if (a
.offset() != b
.offset())