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 "core/dom/Node.h" 30 #include "core/dom/Position.h" 31 32 namespace WebCore { 33 34 class RangeBoundaryPoint { 35 DISALLOW_ALLOCATION(); 36 public: 37 explicit RangeBoundaryPoint(PassRefPtrWillBeRawPtr<Node> container); 38 39 explicit RangeBoundaryPoint(const RangeBoundaryPoint&); 40 41 const Position toPosition() const; 42 43 Node* container() const; 44 int offset() const; 45 Node* childBefore() const; 46 47 void clear(); 48 49 void set(PassRefPtrWillBeRawPtr<Node> container, int offset, Node* childBefore); 50 void setOffset(int offset); 51 52 void setToBeforeChild(Node&); 53 void setToStartOfNode(Node&); 54 void setToEndOfNode(Node&); 55 56 void childBeforeWillBeRemoved(); 57 void invalidateOffset() const; 58 void ensureOffsetIsValid() const; 59 60 void trace(Visitor*); 61 62 private: 63 static const int invalidOffset = -1; 64 65 RefPtrWillBeMember<Node> m_containerNode; 66 mutable int m_offsetInContainer; 67 RefPtrWillBeMember<Node> m_childBeforeBoundary; 68 }; 69 70 inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtrWillBeRawPtr<Node> container) 71 : m_containerNode(container) 72 , m_offsetInContainer(0) 73 , m_childBeforeBoundary(nullptr) 74 { 75 ASSERT(m_containerNode); 76 } 77 78 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other) 79 : m_containerNode(other.container()) 80 , m_offsetInContainer(other.offset()) 81 , m_childBeforeBoundary(other.childBefore()) 82 { 83 } 84 85 inline Node* RangeBoundaryPoint::container() const 86 { 87 return m_containerNode.get(); 88 } 89 90 inline Node* RangeBoundaryPoint::childBefore() const 91 { 92 return m_childBeforeBoundary.get(); 93 } 94 95 inline void RangeBoundaryPoint::ensureOffsetIsValid() const 96 { 97 if (m_offsetInContainer >= 0) 98 return; 99 100 ASSERT(m_childBeforeBoundary); 101 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; 102 } 103 104 inline const Position RangeBoundaryPoint::toPosition() const 105 { 106 ensureOffsetIsValid(); 107 return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer); 108 } 109 110 inline int RangeBoundaryPoint::offset() const 111 { 112 ensureOffsetIsValid(); 113 return m_offsetInContainer; 114 } 115 116 inline void RangeBoundaryPoint::clear() 117 { 118 m_containerNode.clear(); 119 m_offsetInContainer = 0; 120 m_childBeforeBoundary = nullptr; 121 } 122 123 inline void RangeBoundaryPoint::set(PassRefPtrWillBeRawPtr<Node> container, int offset, Node* childBefore) 124 { 125 ASSERT(container); 126 ASSERT(offset >= 0); 127 ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0)); 128 m_containerNode = container; 129 m_offsetInContainer = offset; 130 m_childBeforeBoundary = childBefore; 131 } 132 133 inline void RangeBoundaryPoint::setOffset(int offset) 134 { 135 ASSERT(m_containerNode); 136 ASSERT(m_containerNode->offsetInCharacters()); 137 ASSERT(m_offsetInContainer >= 0); 138 ASSERT(!m_childBeforeBoundary); 139 m_offsetInContainer = offset; 140 } 141 142 inline void RangeBoundaryPoint::setToBeforeChild(Node& child) 143 { 144 ASSERT(child.parentNode()); 145 m_childBeforeBoundary = child.previousSibling(); 146 m_containerNode = child.parentNode(); 147 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; 148 } 149 150 inline void RangeBoundaryPoint::setToStartOfNode(Node& container) 151 { 152 m_containerNode = &container; 153 m_offsetInContainer = 0; 154 m_childBeforeBoundary = nullptr; 155 } 156 157 inline void RangeBoundaryPoint::setToEndOfNode(Node& container) 158 { 159 m_containerNode = &container; 160 if (m_containerNode->offsetInCharacters()) { 161 m_offsetInContainer = m_containerNode->maxCharacterOffset(); 162 m_childBeforeBoundary = nullptr; 163 } else { 164 m_childBeforeBoundary = m_containerNode->lastChild(); 165 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; 166 } 167 } 168 169 inline 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 179 inline void RangeBoundaryPoint::invalidateOffset() const 180 { 181 m_offsetInContainer = invalidOffset; 182 } 183 184 inline void RangeBoundaryPoint::trace(Visitor* visitor) 185 { 186 visitor->trace(m_containerNode); 187 visitor->trace(m_childBeforeBoundary); 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 207