| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 public: | 38 public: |
| 39 explicit RangeBoundaryPoint(Node* container); | 39 explicit RangeBoundaryPoint(Node* container); |
| 40 | 40 |
| 41 explicit RangeBoundaryPoint(const RangeBoundaryPoint&); | 41 explicit RangeBoundaryPoint(const RangeBoundaryPoint&); |
| 42 | 42 |
| 43 bool isConnected() const; | 43 bool isConnected() const; |
| 44 const Position toPosition() const; | 44 const Position toPosition() const; |
| 45 | 45 |
| 46 Node* container() const; | 46 Node* container() const; |
| 47 int offset() const; | 47 unsigned offset() const; |
| 48 Node* childBefore() const; | 48 Node* childBefore() const; |
| 49 | 49 |
| 50 void clear(); | 50 void clear(); |
| 51 | 51 |
| 52 void set(Node* container, int offset, Node* childBefore); | 52 void set(Node* container, unsigned offset, Node* childBefore); |
| 53 void setOffset(int); | 53 void setOffset(unsigned); |
| 54 | 54 |
| 55 void setToBeforeChild(Node&); | 55 void setToBeforeChild(Node&); |
| 56 void setToStartOfNode(Node&); | 56 void setToStartOfNode(Node&); |
| 57 void setToEndOfNode(Node&); | 57 void setToEndOfNode(Node&); |
| 58 | 58 |
| 59 void childBeforeWillBeRemoved(); | 59 void childBeforeWillBeRemoved(); |
| 60 void invalidateOffset(); | |
| 61 void markValid() const; | 60 void markValid() const; |
| 62 | 61 |
| 63 DEFINE_INLINE_TRACE() { | 62 DEFINE_INLINE_TRACE() { |
| 64 visitor->trace(m_containerNode); | 63 visitor->trace(m_containerNode); |
| 65 visitor->trace(m_childBeforeBoundary); | 64 visitor->trace(m_childBeforeBoundary); |
| 66 } | 65 } |
| 67 | 66 |
| 68 private: | 67 private: |
| 69 uint64_t domTreeVersion() const; | 68 uint64_t domTreeVersion() const; |
| 70 void ensureOffsetIsValid() const; | 69 void ensureOffsetIsValid() const; |
| 71 bool isOffsetValid() const; | 70 bool isOffsetValid() const; |
| 72 | 71 |
| 73 static const int invalidOffset = -1; | |
| 74 | |
| 75 Member<Node> m_containerNode; | 72 Member<Node> m_containerNode; |
| 76 Member<Node> m_childBeforeBoundary; | 73 Member<Node> m_childBeforeBoundary; |
| 74 |
| 75 mutable bool m_isValidOffset; |
| 77 mutable uint64_t m_domTreeVersion; | 76 mutable uint64_t m_domTreeVersion; |
| 78 mutable int m_offsetInContainer; | 77 mutable unsigned m_offsetInContainer; |
| 79 }; | 78 }; |
| 80 | 79 |
| 81 inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container) | 80 inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container) |
| 82 : m_containerNode(container), | 81 : m_containerNode(container), |
| 83 m_childBeforeBoundary(nullptr), | 82 m_childBeforeBoundary(nullptr), |
| 83 m_isValidOffset(true), |
| 84 m_domTreeVersion(domTreeVersion()), | 84 m_domTreeVersion(domTreeVersion()), |
| 85 m_offsetInContainer(0) {} | 85 m_offsetInContainer(0) {} |
| 86 | 86 |
| 87 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other) | 87 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other) |
| 88 : m_containerNode(other.container()), | 88 : m_containerNode(other.container()), |
| 89 m_childBeforeBoundary(other.childBefore()), | 89 m_childBeforeBoundary(other.childBefore()), |
| 90 m_isValidOffset(true), |
| 90 m_domTreeVersion(other.m_domTreeVersion), | 91 m_domTreeVersion(other.m_domTreeVersion), |
| 91 m_offsetInContainer(other.offset()) {} | 92 m_offsetInContainer(other.offset()) {} |
| 92 | 93 |
| 93 inline Node* RangeBoundaryPoint::container() const { | 94 inline Node* RangeBoundaryPoint::container() const { |
| 94 return m_containerNode.get(); | 95 return m_containerNode.get(); |
| 95 } | 96 } |
| 96 | 97 |
| 97 inline Node* RangeBoundaryPoint::childBefore() const { | 98 inline Node* RangeBoundaryPoint::childBefore() const { |
| 98 return m_childBeforeBoundary.get(); | 99 return m_childBeforeBoundary.get(); |
| 99 } | 100 } |
| 100 | 101 |
| 101 inline uint64_t RangeBoundaryPoint::domTreeVersion() const { | 102 inline uint64_t RangeBoundaryPoint::domTreeVersion() const { |
| 102 return m_containerNode->document().domTreeVersion(); | 103 return m_containerNode->document().domTreeVersion(); |
| 103 } | 104 } |
| 104 | 105 |
| 105 inline void RangeBoundaryPoint::ensureOffsetIsValid() const { | 106 inline void RangeBoundaryPoint::ensureOffsetIsValid() const { |
| 106 if (isOffsetValid()) | 107 if (isOffsetValid()) |
| 107 return; | 108 return; |
| 108 DCHECK(!m_containerNode->isCharacterDataNode()); | 109 DCHECK(!m_containerNode->isCharacterDataNode()); |
| 109 markValid(); | 110 markValid(); |
| 111 m_isValidOffset = true; |
| 110 if (!m_childBeforeBoundary) { | 112 if (!m_childBeforeBoundary) { |
| 111 m_offsetInContainer = 0; | 113 m_offsetInContainer = 0; |
| 112 return; | 114 return; |
| 113 } | 115 } |
| 114 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; | 116 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; |
| 115 } | 117 } |
| 116 | 118 |
| 117 inline bool RangeBoundaryPoint::isConnected() const { | 119 inline bool RangeBoundaryPoint::isConnected() const { |
| 118 return m_containerNode && m_containerNode->isConnected(); | 120 return m_containerNode && m_containerNode->isConnected(); |
| 119 } | 121 } |
| 120 | 122 |
| 121 inline bool RangeBoundaryPoint::isOffsetValid() const { | 123 inline bool RangeBoundaryPoint::isOffsetValid() const { |
| 122 if (m_offsetInContainer == invalidOffset) { | 124 if (!m_isValidOffset) { |
| 123 DCHECK(!m_containerNode->isTextNode()); | 125 DCHECK(!m_containerNode->isTextNode()); |
| 124 return false; | 126 return false; |
| 125 } | 127 } |
| 128 |
| 126 return domTreeVersion() == m_domTreeVersion || | 129 return domTreeVersion() == m_domTreeVersion || |
| 127 m_containerNode->isCharacterDataNode(); | 130 m_containerNode->isCharacterDataNode(); |
| 128 } | 131 } |
| 129 | 132 |
| 130 inline const Position RangeBoundaryPoint::toPosition() const { | 133 inline const Position RangeBoundaryPoint::toPosition() const { |
| 131 ensureOffsetIsValid(); | 134 ensureOffsetIsValid(); |
| 132 // TODO(yosin): We should return |Position::beforeAnchor| when | 135 // TODO(yosin): We should return |Position::beforeAnchor| when |
| 133 // |m_containerNode| isn't |Text| node. | 136 // |m_containerNode| isn't |Text| node. |
| 134 return Position::editingPositionOf(m_containerNode.get(), | 137 return Position::editingPositionOf(m_containerNode.get(), |
| 135 m_offsetInContainer); | 138 m_offsetInContainer); |
| 136 } | 139 } |
| 137 | 140 |
| 138 inline int RangeBoundaryPoint::offset() const { | 141 inline unsigned RangeBoundaryPoint::offset() const { |
| 139 ensureOffsetIsValid(); | 142 ensureOffsetIsValid(); |
| 140 return m_offsetInContainer; | 143 return m_offsetInContainer; |
| 141 } | 144 } |
| 142 | 145 |
| 143 inline void RangeBoundaryPoint::clear() { | 146 inline void RangeBoundaryPoint::clear() { |
| 144 m_containerNode.clear(); | 147 m_containerNode.clear(); |
| 148 m_isValidOffset = true; |
| 145 m_offsetInContainer = 0; | 149 m_offsetInContainer = 0; |
| 146 m_childBeforeBoundary = nullptr; | 150 m_childBeforeBoundary = nullptr; |
| 147 m_domTreeVersion = 0; | 151 m_domTreeVersion = 0; |
| 148 } | 152 } |
| 149 | 153 |
| 150 inline void RangeBoundaryPoint::set(Node* container, | 154 inline void RangeBoundaryPoint::set(Node* container, |
| 151 int offset, | 155 unsigned offset, |
| 152 Node* childBefore) { | 156 Node* childBefore) { |
| 153 DCHECK(container); | 157 DCHECK(container); |
| 154 DCHECK_GE(offset, 0); | |
| 155 DCHECK_EQ(childBefore, | 158 DCHECK_EQ(childBefore, |
| 156 offset ? NodeTraversal::childAt(*container, offset - 1) : 0); | 159 offset ? NodeTraversal::childAt(*container, offset - 1) : 0); |
| 157 m_containerNode = container; | 160 m_containerNode = container; |
| 161 m_isValidOffset = true; |
| 158 m_offsetInContainer = offset; | 162 m_offsetInContainer = offset; |
| 159 m_childBeforeBoundary = childBefore; | 163 m_childBeforeBoundary = childBefore; |
| 160 markValid(); | 164 markValid(); |
| 161 } | 165 } |
| 162 | 166 |
| 163 inline void RangeBoundaryPoint::setOffset(int offset) { | 167 inline void RangeBoundaryPoint::setOffset(unsigned offset) { |
| 164 DCHECK(m_containerNode); | 168 DCHECK(m_containerNode); |
| 165 DCHECK(m_containerNode->isCharacterDataNode()); | 169 DCHECK(m_containerNode->isCharacterDataNode()); |
| 166 DCHECK_GE(m_offsetInContainer, 0); | |
| 167 DCHECK(!m_childBeforeBoundary); | 170 DCHECK(!m_childBeforeBoundary); |
| 171 m_isValidOffset = true; |
| 168 m_offsetInContainer = offset; | 172 m_offsetInContainer = offset; |
| 169 markValid(); | 173 markValid(); |
| 170 } | 174 } |
| 171 | 175 |
| 172 inline void RangeBoundaryPoint::setToBeforeChild(Node& child) { | 176 inline void RangeBoundaryPoint::setToBeforeChild(Node& child) { |
| 173 DCHECK(child.parentNode()); | 177 DCHECK(child.parentNode()); |
| 174 m_childBeforeBoundary = child.previousSibling(); | 178 m_childBeforeBoundary = child.previousSibling(); |
| 175 m_containerNode = child.parentNode(); | 179 m_containerNode = child.parentNode(); |
| 176 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; | 180 if (m_childBeforeBoundary) { |
| 181 m_isValidOffset = false; |
| 182 } else { |
| 183 m_isValidOffset = true; |
| 184 m_offsetInContainer = 0; |
| 185 } |
| 177 markValid(); | 186 markValid(); |
| 178 } | 187 } |
| 179 | 188 |
| 180 inline void RangeBoundaryPoint::setToStartOfNode(Node& container) { | 189 inline void RangeBoundaryPoint::setToStartOfNode(Node& container) { |
| 181 m_containerNode = &container; | 190 m_containerNode = &container; |
| 191 m_isValidOffset = true; |
| 182 m_offsetInContainer = 0; | 192 m_offsetInContainer = 0; |
| 183 m_childBeforeBoundary = nullptr; | 193 m_childBeforeBoundary = nullptr; |
| 184 markValid(); | 194 markValid(); |
| 185 } | 195 } |
| 186 | 196 |
| 187 inline void RangeBoundaryPoint::setToEndOfNode(Node& container) { | 197 inline void RangeBoundaryPoint::setToEndOfNode(Node& container) { |
| 188 m_containerNode = &container; | 198 m_containerNode = &container; |
| 189 if (m_containerNode->isCharacterDataNode()) { | 199 if (m_containerNode->isCharacterDataNode()) { |
| 200 m_isValidOffset = true; |
| 190 m_offsetInContainer = m_containerNode->maxCharacterOffset(); | 201 m_offsetInContainer = m_containerNode->maxCharacterOffset(); |
| 191 m_childBeforeBoundary = nullptr; | 202 m_childBeforeBoundary = nullptr; |
| 192 } else { | 203 } else { |
| 193 m_childBeforeBoundary = m_containerNode->lastChild(); | 204 m_childBeforeBoundary = m_containerNode->lastChild(); |
| 194 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; | 205 if (m_childBeforeBoundary) { |
| 206 m_isValidOffset = false; |
| 207 } else { |
| 208 m_isValidOffset = true; |
| 209 m_offsetInContainer = 0; |
| 210 } |
| 195 } | 211 } |
| 196 markValid(); | 212 markValid(); |
| 197 } | 213 } |
| 198 | 214 |
| 199 inline void RangeBoundaryPoint::childBeforeWillBeRemoved() { | 215 inline void RangeBoundaryPoint::childBeforeWillBeRemoved() { |
| 200 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling(); | 216 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling(); |
| 201 if (!isOffsetValid()) | 217 if (!isOffsetValid()) |
| 202 return; | 218 return; |
| 203 DCHECK_GT(m_offsetInContainer, 0); | |
| 204 if (!m_childBeforeBoundary) | 219 if (!m_childBeforeBoundary) |
| 205 m_offsetInContainer = 0; | 220 m_offsetInContainer = 0; |
| 206 else if (m_offsetInContainer > 0) | 221 else if (m_offsetInContainer > 0) |
| 207 --m_offsetInContainer; | 222 --m_offsetInContainer; |
| 208 markValid(); | 223 markValid(); |
| 209 } | 224 } |
| 210 | 225 |
| 211 inline void RangeBoundaryPoint::invalidateOffset() { | |
| 212 m_offsetInContainer = invalidOffset; | |
| 213 } | |
| 214 | |
| 215 inline void RangeBoundaryPoint::markValid() const { | 226 inline void RangeBoundaryPoint::markValid() const { |
| 216 m_domTreeVersion = domTreeVersion(); | 227 m_domTreeVersion = domTreeVersion(); |
| 217 } | 228 } |
| 218 | 229 |
| 219 inline bool operator==(const RangeBoundaryPoint& a, | 230 inline bool operator==(const RangeBoundaryPoint& a, |
| 220 const RangeBoundaryPoint& b) { | 231 const RangeBoundaryPoint& b) { |
| 221 if (a.container() != b.container()) | 232 if (a.container() != b.container()) |
| 222 return false; | 233 return false; |
| 223 if (a.childBefore() || b.childBefore()) { | 234 if (a.childBefore() || b.childBefore()) { |
| 224 if (a.childBefore() != b.childBefore()) | 235 if (a.childBefore() != b.childBefore()) |
| 225 return false; | 236 return false; |
| 226 } else { | 237 } else { |
| 227 if (a.offset() != b.offset()) | 238 if (a.offset() != b.offset()) |
| 228 return false; | 239 return false; |
| 229 } | 240 } |
| 230 return true; | 241 return true; |
| 231 } | 242 } |
| 232 | 243 |
| 233 } // namespace blink | 244 } // namespace blink |
| 234 | 245 |
| 235 #endif | 246 #endif |
| OLD | NEW |