Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: Source/core/dom/Range.cpp

Issue 252783002: Make Range.detach() a no-op (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/Range.h ('k') | Source/core/dom/Range.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * (C) 1999 Lars Knoll (knoll@kde.org) 2 * (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
5 * (C) 2001 Peter Kelly (pmk@post.com) 5 * (C) 2001 Peter Kelly (pmk@post.com)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved.
7 * Copyright (C) 2011 Motorola Mobility. All rights reserved. 7 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 { 118 {
119 ASSERT(m_ownerDocument != document); 119 ASSERT(m_ownerDocument != document);
120 ASSERT(m_ownerDocument); 120 ASSERT(m_ownerDocument);
121 m_ownerDocument->detachRange(this); 121 m_ownerDocument->detachRange(this);
122 m_ownerDocument = &document; 122 m_ownerDocument = &document;
123 m_start.setToStartOfNode(document); 123 m_start.setToStartOfNode(document);
124 m_end.setToStartOfNode(document); 124 m_end.setToStartOfNode(document);
125 m_ownerDocument->attachRange(this); 125 m_ownerDocument->attachRange(this);
126 } 126 }
127 127
128 Node* Range::startContainer(ExceptionState& exceptionState) const 128 Node* Range::commonAncestorContainer() const
129 { 129 {
130 if (!m_start.container()) {
131 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
132 return 0;
133 }
134
135 return m_start.container();
136 }
137
138 int Range::startOffset(ExceptionState& exceptionState) const
139 {
140 if (!m_start.container()) {
141 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
142 return 0;
143 }
144
145 return m_start.offset();
146 }
147
148 Node* Range::endContainer(ExceptionState& exceptionState) const
149 {
150 if (!m_start.container()) {
151 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
152 return 0;
153 }
154
155 return m_end.container();
156 }
157
158 int Range::endOffset(ExceptionState& exceptionState) const
159 {
160 if (!m_start.container()) {
161 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
162 return 0;
163 }
164
165 return m_end.offset();
166 }
167
168 Node* Range::commonAncestorContainer(ExceptionState& exceptionState) const
169 {
170 if (!m_start.container()) {
171 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
172 return 0;
173 }
174
175 return commonAncestorContainer(m_start.container(), m_end.container()); 130 return commonAncestorContainer(m_start.container(), m_end.container());
176 } 131 }
177 132
178 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB) 133 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
179 { 134 {
180 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) { 135 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
181 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode( )) { 136 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode( )) {
182 if (parentA == parentB) 137 if (parentA == parentB)
183 return parentA; 138 return parentA;
184 } 139 }
185 } 140 }
186 return 0; 141 return 0;
187 } 142 }
188 143
189 bool Range::collapsed(ExceptionState& exceptionState) const
190 {
191 if (!m_start.container()) {
192 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
193 return 0;
194 }
195
196 return m_start == m_end;
197 }
198
199 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star t, const RangeBoundaryPoint& end) 144 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star t, const RangeBoundaryPoint& end)
200 { 145 {
201 Node* endRootContainer = end.container(); 146 Node* endRootContainer = end.container();
202 while (endRootContainer->parentNode()) 147 while (endRootContainer->parentNode())
203 endRootContainer = endRootContainer->parentNode(); 148 endRootContainer = endRootContainer->parentNode();
204 Node* startRootContainer = start.container(); 149 Node* startRootContainer = start.container();
205 while (startRootContainer->parentNode()) 150 while (startRootContainer->parentNode())
206 startRootContainer = startRootContainer->parentNode(); 151 startRootContainer = startRootContainer->parentNode();
207 152
208 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin ts(start, end, ASSERT_NO_EXCEPTION) > 0); 153 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin ts(start, end, ASSERT_NO_EXCEPTION) > 0);
209 } 154 }
210 155
211 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep tionState) 156 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep tionState)
212 { 157 {
213 if (!m_start.container()) {
214 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
215 return;
216 }
217
218 if (!refNode) { 158 if (!refNode) {
219 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 159 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
220 return; 160 return;
221 } 161 }
222 162
223 bool didMoveDocument = false; 163 bool didMoveDocument = false;
224 if (refNode->document() != m_ownerDocument) { 164 if (refNode->document() != m_ownerDocument) {
225 setDocument(refNode->document()); 165 setDocument(refNode->document());
226 didMoveDocument = true; 166 didMoveDocument = true;
227 } 167 }
228 168
229 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); 169 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState);
230 if (exceptionState.hadException()) 170 if (exceptionState.hadException())
231 return; 171 return;
232 172
233 m_start.set(refNode, offset, childNode); 173 m_start.set(refNode, offset, childNode);
234 174
235 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 175 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
236 collapse(true, exceptionState); 176 collapse(true);
237 } 177 }
238 178
239 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti onState) 179 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti onState)
240 { 180 {
241 if (!m_start.container()) {
242 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
243 return;
244 }
245
246 if (!refNode) { 181 if (!refNode) {
247 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 182 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
248 return; 183 return;
249 } 184 }
250 185
251 bool didMoveDocument = false; 186 bool didMoveDocument = false;
252 if (refNode->document() != m_ownerDocument) { 187 if (refNode->document() != m_ownerDocument) {
253 setDocument(refNode->document()); 188 setDocument(refNode->document());
254 didMoveDocument = true; 189 didMoveDocument = true;
255 } 190 }
256 191
257 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); 192 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState);
258 if (exceptionState.hadException()) 193 if (exceptionState.hadException())
259 return; 194 return;
260 195
261 m_end.set(refNode, offset, childNode); 196 m_end.set(refNode, offset, childNode);
262 197
263 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 198 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
264 collapse(false, exceptionState); 199 collapse(false);
265 } 200 }
266 201
267 void Range::setStart(const Position& start, ExceptionState& exceptionState) 202 void Range::setStart(const Position& start, ExceptionState& exceptionState)
268 { 203 {
269 Position parentAnchored = start.parentAnchoredEquivalent(); 204 Position parentAnchored = start.parentAnchoredEquivalent();
270 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod e(), exceptionState); 205 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod e(), exceptionState);
271 } 206 }
272 207
273 void Range::setEnd(const Position& end, ExceptionState& exceptionState) 208 void Range::setEnd(const Position& end, ExceptionState& exceptionState)
274 { 209 {
275 Position parentAnchored = end.parentAnchoredEquivalent(); 210 Position parentAnchored = end.parentAnchoredEquivalent();
276 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode( ), exceptionState); 211 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode( ), exceptionState);
277 } 212 }
278 213
279 void Range::collapse(bool toStart, ExceptionState& exceptionState) 214 void Range::collapse(bool toStart)
280 { 215 {
281 if (!m_start.container()) {
282 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
283 return;
284 }
285
286 if (toStart) 216 if (toStart)
287 m_end = m_start; 217 m_end = m_start;
288 else 218 else
289 m_start = m_end; 219 m_start = m_end;
290 } 220 }
291 221
292 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS tate) 222 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS tate)
293 { 223 {
294 if (!m_start.container()) {
295 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
296 return false;
297 }
298
299 if (!refNode) { 224 if (!refNode) {
300 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null."); 225 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null.");
301 return false; 226 return false;
302 } 227 }
303 228
304 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { 229 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) {
305 return false; 230 return false;
306 } 231 }
307 232
308 checkNodeWOffset(refNode, offset, exceptionState); 233 checkNodeWOffset(refNode, offset, exceptionState);
309 if (exceptionState.hadException()) 234 if (exceptionState.hadException())
310 return false; 235 return false;
311 236
312 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o ffset(), exceptionState) >= 0 && !exceptionState.hadException() 237 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o ffset(), exceptionState) >= 0 && !exceptionState.hadException()
313 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse t(), exceptionState) <= 0 && !exceptionState.hadException(); 238 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse t(), exceptionState) <= 0 && !exceptionState.hadException();
314 } 239 }
315 240
316 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt ate) const 241 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt ate) const
317 { 242 {
318 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint 243 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
319 // This method returns -1, 0 or 1 depending on if the point described by the 244 // This method returns -1, 0 or 1 depending on if the point described by the
320 // refNode node and an offset within the node is before, same as, or after t he range respectively. 245 // refNode node and an offset within the node is before, same as, or after t he range respectively.
321 246
322 if (!m_start.container()) {
323 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
324 return 0;
325 }
326
327 if (!refNode) { 247 if (!refNode) {
328 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null."); 248 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null.");
329 return 0; 249 return 0;
330 } 250 }
331 251
332 if (!refNode->inActiveDocument()) { 252 if (!refNode->inActiveDocument()) {
333 exceptionState.throwDOMException(WrongDocumentError, "The node provided is not in an active document."); 253 exceptionState.throwDOMException(WrongDocumentError, "The node provided is not in an active document.");
334 return 0; 254 return 0;
335 } 255 }
336 256
(...skipping 25 matching lines...) Expand all
362 { 282 {
363 // http://developer.mozilla.org/en/docs/DOM:range.compareNode 283 // http://developer.mozilla.org/en/docs/DOM:range.compareNode
364 // This method returns 0, 1, 2, or 3 based on if the node is before, after, 284 // This method returns 0, 1, 2, or 3 based on if the node is before, after,
365 // before and after(surrounds), or inside the range, respectively 285 // before and after(surrounds), or inside the range, respectively
366 286
367 if (!refNode) { 287 if (!refNode) {
368 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 288 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
369 return NODE_BEFORE; 289 return NODE_BEFORE;
370 } 290 }
371 291
372 if (!m_start.container() && refNode->inActiveDocument()) { 292 if (!refNode->inActiveDocument()) {
373 exceptionState.throwDOMException(InvalidStateError, "This Range is detac hed, and the provided node is not.");
374 return NODE_BEFORE;
375 }
376
377 if (m_start.container() && !refNode->inActiveDocument()) {
378 // Firefox doesn't throw an exception for this case; it returns 0. 293 // Firefox doesn't throw an exception for this case; it returns 0.
379 return NODE_BEFORE; 294 return NODE_BEFORE;
380 } 295 }
381 296
382 if (refNode->document() != m_ownerDocument) { 297 if (refNode->document() != m_ownerDocument) {
383 // Firefox doesn't throw an exception for this case; it returns 0. 298 // Firefox doesn't throw an exception for this case; it returns 0.
384 return NODE_BEFORE; 299 return NODE_BEFORE;
385 } 300 }
386 301
387 ContainerNode* parentNode = refNode->parentNode(); 302 ContainerNode* parentNode = refNode->parentNode();
(...skipping 12 matching lines...) Expand all
400 return NODE_BEFORE; // ends before or in the range 315 return NODE_BEFORE; // ends before or in the range
401 } 316 }
402 // starts at or after the range start 317 // starts at or after the range start
403 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft er the range 318 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft er the range
404 return NODE_AFTER; 319 return NODE_AFTER;
405 return NODE_INSIDE; // ends inside the range 320 return NODE_INSIDE; // ends inside the range
406 } 321 }
407 322
408 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc eptionState& exceptionState) const 323 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc eptionState& exceptionState) const
409 { 324 {
410 if (!m_start.container()) {
411 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
412 return 0;
413 }
414
415 if (!sourceRange) { 325 if (!sourceRange) {
416 exceptionState.throwDOMException(NotFoundError, "The source range provid ed was null."); 326 exceptionState.throwDOMException(NotFoundError, "The source range provid ed was null.");
417 return 0; 327 return 0;
418 } 328 }
419 329
420 Node* thisCont = commonAncestorContainer(exceptionState); 330 Node* thisCont = commonAncestorContainer();
421 if (exceptionState.hadException()) 331 Node* sourceCont = sourceRange->commonAncestorContainer();
422 return 0;
423 Node* sourceCont = sourceRange->commonAncestorContainer(exceptionState);
424 if (exceptionState.hadException())
425 return 0;
426
427 if (thisCont->document() != sourceCont->document()) { 332 if (thisCont->document() != sourceCont->document()) {
428 exceptionState.throwDOMException(WrongDocumentError, "The source range i s in a different document than this range."); 333 exceptionState.throwDOMException(WrongDocumentError, "The source range i s in a different document than this range.");
429 return 0; 334 return 0;
430 } 335 }
431 336
432 Node* thisTop = thisCont; 337 Node* thisTop = thisCont;
433 Node* sourceTop = sourceCont; 338 Node* sourceTop = sourceCont;
434 while (thisTop->parentNode()) 339 while (thisTop->parentNode())
435 thisTop = thisTop->parentNode(); 340 thisTop = thisTop->parentNode();
436 while (sourceTop->parentNode()) 341 while (sourceTop->parentNode())
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 } 454 }
550 455
551 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState) 456 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState)
552 { 457 {
553 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun daryB.container(), boundaryB.offset(), exceptionState); 458 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun daryB.container(), boundaryB.offset(), exceptionState);
554 } 459 }
555 460
556 bool Range::boundaryPointsValid() const 461 bool Range::boundaryPointsValid() const
557 { 462 {
558 TrackExceptionState exceptionState; 463 TrackExceptionState exceptionState;
559 return m_start.container() && compareBoundaryPoints(m_start, m_end, exceptio nState) <= 0 && !exceptionState.hadException(); 464 return compareBoundaryPoints(m_start, m_end, exceptionState) <= 0 && !except ionState.hadException();
560 } 465 }
561 466
562 void Range::deleteContents(ExceptionState& exceptionState) 467 void Range::deleteContents(ExceptionState& exceptionState)
563 { 468 {
564 checkDeleteExtract(exceptionState); 469 checkDeleteExtract(exceptionState);
565 if (exceptionState.hadException()) 470 if (exceptionState.hadException())
566 return; 471 return;
567 472
568 processContents(DELETE_CONTENTS, exceptionState); 473 processContents(DELETE_CONTENTS, exceptionState);
569 } 474 }
570 475
571 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState) 476 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState)
572 { 477 {
573 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode 478 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
574 // Returns a bool if the node intersects the range. 479 // Returns a bool if the node intersects the range.
575
576 // Throw exception if the range is already detached.
577 if (!m_start.container()) {
578 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
579 return false;
580 }
581 if (!refNode) { 480 if (!refNode) {
582 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 481 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
583 return false; 482 return false;
584 } 483 }
585 484
586 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { 485 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) {
587 // Firefox doesn't throw an exception for these cases; it returns false. 486 // Firefox doesn't throw an exception for these cases; it returns false.
588 return false; 487 return false;
589 } 488 }
590 489
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 } 566 }
668 567
669 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception State& exceptionState) 568 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception State& exceptionState)
670 { 569 {
671 typedef Vector<RefPtr<Node> > NodeVector; 570 typedef Vector<RefPtr<Node> > NodeVector;
672 571
673 RefPtr<DocumentFragment> fragment; 572 RefPtr<DocumentFragment> fragment;
674 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) 573 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
675 fragment = DocumentFragment::create(*m_ownerDocument.get()); 574 fragment = DocumentFragment::create(*m_ownerDocument.get());
676 575
677 if (collapsed(exceptionState)) 576 if (collapsed())
678 return fragment.release(); 577 return fragment.release();
679 if (exceptionState.hadException())
680 return nullptr;
681 578
682 RefPtr<Node> commonRoot = commonAncestorContainer(exceptionState); 579 RefPtr<Node> commonRoot = commonAncestorContainer();
683 if (exceptionState.hadException())
684 return nullptr;
685 ASSERT(commonRoot); 580 ASSERT(commonRoot);
686 581
687 if (m_start.container() == m_end.container()) { 582 if (m_start.container() == m_end.container()) {
688 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s tart.offset(), m_end.offset(), exceptionState); 583 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s tart.offset(), m_end.offset(), exceptionState);
689 return fragment; 584 return fragment;
690 } 585 }
691 586
692 // Since mutation observers can modify the range during the process, the bou ndary points need to be saved. 587 // Since mutation observers can modify the range during the process, the bou ndary points need to be saved.
693 RangeBoundaryPoint originalStart(m_start); 588 RangeBoundaryPoint originalStart(m_start);
694 RangeBoundaryPoint originalEnd(m_end); 589 RangeBoundaryPoint originalEnd(m_end);
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 { 825 {
931 checkDeleteExtract(exceptionState); 826 checkDeleteExtract(exceptionState);
932 if (exceptionState.hadException()) 827 if (exceptionState.hadException())
933 return nullptr; 828 return nullptr;
934 829
935 return processContents(EXTRACT_CONTENTS, exceptionState); 830 return processContents(EXTRACT_CONTENTS, exceptionState);
936 } 831 }
937 832
938 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState ) 833 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState )
939 { 834 {
940 if (!m_start.container()) {
941 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
942 return nullptr;
943 }
944
945 return processContents(CLONE_CONTENTS, exceptionState); 835 return processContents(CLONE_CONTENTS, exceptionState);
946 } 836 }
947 837
948 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta te) 838 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta te)
949 { 839 {
950 RefPtr<Node> newNode = prpNewNode; 840 RefPtr<Node> newNode = prpNewNode;
951 841
952 if (!m_start.container()) {
953 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
954 return;
955 }
956
957 if (!newNode) { 842 if (!newNode) {
958 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 843 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
959 return; 844 return;
960 } 845 }
961 846
962 // HierarchyRequestError: Raised if the container of the start of the Range is of a type that 847 // HierarchyRequestError: Raised if the container of the start of the Range is of a type that
963 // does not allow children of the type of newNode or if newNode is an ancest or of the container. 848 // does not allow children of the type of newNode or if newNode is an ancest or of the container.
964 849
965 // an extra one here - if a text node is going to split, it must have a pare nt to insert into 850 // an extra one here - if a text node is going to split, it must have a pare nt to insert into
966 bool startIsText = m_start.container()->isTextNode(); 851 bool startIsText = m_start.container()->isTextNode();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 if (exceptionState.hadException()) 935 if (exceptionState.hadException())
1051 return; 936 return;
1052 937
1053 // Note that m_start.offset() may have changed as a result of container- >insertBefore, 938 // Note that m_start.offset() may have changed as a result of container- >insertBefore,
1054 // when the node we are inserting comes before the range in the same con tainer. 939 // when the node we are inserting comes before the range in the same con tainer.
1055 if (collapsed && numNewChildren) 940 if (collapsed && numNewChildren)
1056 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la stChild.get()); 941 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la stChild.get());
1057 } 942 }
1058 } 943 }
1059 944
1060 String Range::toString(ExceptionState& exceptionState) const 945 String Range::toString() const
1061 { 946 {
1062 if (!m_start.container()) {
1063 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1064 return String();
1065 }
1066
1067 StringBuilder builder; 947 StringBuilder builder;
1068 948
1069 Node* pastLast = pastLastNode(); 949 Node* pastLast = pastLastNode();
1070 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { 950 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) {
1071 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC TION_NODE) { 951 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC TION_NODE) {
1072 String data = toCharacterData(n)->data(); 952 String data = toCharacterData(n)->data();
1073 int length = data.length(); 953 int length = data.length();
1074 int start = (n == m_start.container()) ? min(max(0, m_start.offset() ), length) : 0; 954 int start = (n == m_start.container()) ? min(max(0, m_start.offset() ), length) : 0;
1075 int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length; 955 int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
1076 builder.append(data, start, end - start); 956 builder.append(data, start, end - start);
1077 } 957 }
1078 } 958 }
1079 959
1080 return builder.toString(); 960 return builder.toString();
1081 } 961 }
1082 962
1083 String Range::toHTML() const 963 String Range::toHTML() const
1084 { 964 {
1085 return createMarkup(this); 965 return createMarkup(this);
1086 } 966 }
1087 967
1088 String Range::text() const 968 String Range::text() const
1089 { 969 {
1090 if (!m_start.container())
1091 return String();
1092
1093 // We need to update layout, since plainText uses line boxes in the render t ree. 970 // We need to update layout, since plainText uses line boxes in the render t ree.
1094 // FIXME: As with innerText, we'd like this to work even if there are no ren der objects. 971 // FIXME: As with innerText, we'd like this to work even if there are no ren der objects.
1095 m_start.container()->document().updateLayout(); 972 m_start.container()->document().updateLayout();
1096 973
1097 return plainText(this); 974 return plainText(this);
1098 } 975 }
1099 976
1100 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku p, ExceptionState& exceptionState) 977 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku p, ExceptionState& exceptionState)
1101 { 978 {
1102 if (!m_start.container()) {
1103 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1104 return nullptr;
1105 }
1106
1107 Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode(); 979 Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
1108 if (!element || !element->isHTMLElement()) { 980 if (!element || !element->isHTMLElement()) {
1109 exceptionState.throwDOMException(NotSupportedError, "The range's contain er must be an HTML element."); 981 exceptionState.throwDOMException(NotSupportedError, "The range's contain er must be an HTML element.");
1110 return nullptr; 982 return nullptr;
1111 } 983 }
1112 984
1113 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup , toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, excep tionState); 985 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup , toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, excep tionState);
1114 if (!fragment) 986 if (!fragment)
1115 return nullptr; 987 return nullptr;
1116 988
1117 return fragment.release(); 989 return fragment.release();
1118 } 990 }
1119 991
1120 992
1121 void Range::detach(ExceptionState& exceptionState) 993 void Range::detach()
1122 { 994 {
1123 // Check first to see if we've already detached: 995 // This is now a no-op as per the DOM specification.
1124 if (!m_start.container()) {
1125 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1126 return;
1127 }
1128
1129 m_ownerDocument->detachRange(this);
1130
1131 m_start.clear();
1132 m_end.clear();
1133 } 996 }
1134 997
1135 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat e) const 998 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat e) const
1136 { 999 {
1137 switch (n->nodeType()) { 1000 switch (n->nodeType()) {
1138 case Node::DOCUMENT_TYPE_NODE: 1001 case Node::DOCUMENT_TYPE_NODE:
1139 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'."); 1002 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'.");
1140 return 0; 1003 return 0;
1141 case Node::CDATA_SECTION_NODE: 1004 case Node::CDATA_SECTION_NODE:
1142 case Node::COMMENT_NODE: 1005 case Node::COMMENT_NODE:
(...skipping 16 matching lines...) Expand all
1159 exceptionState.throwDOMException(IndexSizeError, "There is no ch ild at offset " + String::number(offset) + "."); 1022 exceptionState.throwDOMException(IndexSizeError, "There is no ch ild at offset " + String::number(offset) + ".");
1160 return childBefore; 1023 return childBefore;
1161 } 1024 }
1162 } 1025 }
1163 ASSERT_NOT_REACHED(); 1026 ASSERT_NOT_REACHED();
1164 return 0; 1027 return 0;
1165 } 1028 }
1166 1029
1167 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const 1030 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const
1168 { 1031 {
1169 if (!m_start.container()) {
1170 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1171 return;
1172 }
1173
1174 if (!n) { 1032 if (!n) {
1175 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1033 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1176 return; 1034 return;
1177 } 1035 }
1178 1036
1179 // InvalidNodeTypeError: Raised if the root container of refNode is not an 1037 // InvalidNodeTypeError: Raised if the root container of refNode is not an
1180 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha dow DOM tree, 1038 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha dow DOM tree,
1181 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node. 1039 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node.
1182 1040
1183 if (!n->parentNode()) { 1041 if (!n->parentNode()) {
(...skipping 29 matching lines...) Expand all
1213 case Node::CDATA_SECTION_NODE: 1071 case Node::CDATA_SECTION_NODE:
1214 case Node::COMMENT_NODE: 1072 case Node::COMMENT_NODE:
1215 case Node::DOCUMENT_TYPE_NODE: 1073 case Node::DOCUMENT_TYPE_NODE:
1216 case Node::PROCESSING_INSTRUCTION_NODE: 1074 case Node::PROCESSING_INSTRUCTION_NODE:
1217 case Node::TEXT_NODE: 1075 case Node::TEXT_NODE:
1218 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'."); 1076 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'.");
1219 return; 1077 return;
1220 } 1078 }
1221 } 1079 }
1222 1080
1223 PassRefPtrWillBeRawPtr<Range> Range::cloneRange(ExceptionState& exceptionState) const 1081 PassRefPtrWillBeRawPtr<Range> Range::cloneRange() const
1224 { 1082 {
1225 if (!m_start.container()) {
1226 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1227 return nullptr;
1228 }
1229
1230 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of fset(), m_end.container(), m_end.offset()); 1083 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of fset(), m_end.container(), m_end.offset());
1231 } 1084 }
1232 1085
1233 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState) 1086 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState)
1234 { 1087 {
1235 checkNodeBA(refNode, exceptionState); 1088 checkNodeBA(refNode, exceptionState);
1236 if (exceptionState.hadException()) 1089 if (exceptionState.hadException())
1237 return; 1090 return;
1238 1091
1239 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); 1092 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState);
(...skipping 12 matching lines...) Expand all
1252 { 1105 {
1253 checkNodeBA(refNode, exceptionState); 1106 checkNodeBA(refNode, exceptionState);
1254 if (exceptionState.hadException()) 1107 if (exceptionState.hadException())
1255 return; 1108 return;
1256 1109
1257 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); 1110 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState);
1258 } 1111 }
1259 1112
1260 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) 1113 void Range::selectNode(Node* refNode, ExceptionState& exceptionState)
1261 { 1114 {
1262 if (!m_start.container()) {
1263 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1264 return;
1265 }
1266
1267 if (!refNode) { 1115 if (!refNode) {
1268 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1116 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1269 return; 1117 return;
1270 } 1118 }
1271 1119
1272 if (!refNode->parentNode()) { 1120 if (!refNode->parentNode()) {
1273 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h as no parent."); 1121 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h as no parent.");
1274 return; 1122 return;
1275 } 1123 }
1276 1124
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 1159
1312 if (m_ownerDocument != refNode->document()) 1160 if (m_ownerDocument != refNode->document())
1313 setDocument(refNode->document()); 1161 setDocument(refNode->document());
1314 1162
1315 setStartBefore(refNode); 1163 setStartBefore(refNode);
1316 setEndAfter(refNode); 1164 setEndAfter(refNode);
1317 } 1165 }
1318 1166
1319 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) 1167 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState)
1320 { 1168 {
1321 if (!m_start.container()) {
1322 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1323 return;
1324 }
1325
1326 if (!refNode) { 1169 if (!refNode) {
1327 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1170 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1328 return; 1171 return;
1329 } 1172 }
1330 1173
1331 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E ntity, Notation 1174 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E ntity, Notation
1332 // or DocumentType node. 1175 // or DocumentType node.
1333 for (Node* n = refNode; n; n = n->parentNode()) { 1176 for (Node* n = refNode; n; n = n->parentNode()) {
1334 switch (n->nodeType()) { 1177 switch (n->nodeType()) {
1335 case Node::ATTRIBUTE_NODE: 1178 case Node::ATTRIBUTE_NODE:
(...skipping 14 matching lines...) Expand all
1350 if (m_ownerDocument != refNode->document()) 1193 if (m_ownerDocument != refNode->document())
1351 setDocument(refNode->document()); 1194 setDocument(refNode->document());
1352 1195
1353 m_start.setToStartOfNode(*refNode); 1196 m_start.setToStartOfNode(*refNode);
1354 m_end.setToEndOfNode(*refNode); 1197 m_end.setToEndOfNode(*refNode);
1355 } 1198 }
1356 1199
1357 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc eptionState) 1200 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc eptionState)
1358 { 1201 {
1359 RefPtr<Node> newParent = passNewParent; 1202 RefPtr<Node> newParent = passNewParent;
1360
1361 if (!m_start.container()) {
1362 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1363 return;
1364 }
1365
1366 if (!newParent) { 1203 if (!newParent) {
1367 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1204 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1368 return; 1205 return;
1369 } 1206 }
1370 1207
1371 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No tation, 1208 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No tation,
1372 // Document, or DocumentFragment node. 1209 // Document, or DocumentFragment node.
1373 switch (newParent->nodeType()) { 1210 switch (newParent->nodeType()) {
1374 case Node::ATTRIBUTE_NODE: 1211 case Node::ATTRIBUTE_NODE:
1375 case Node::DOCUMENT_FRAGMENT_NODE: 1212 case Node::DOCUMENT_FRAGMENT_NODE:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 { 1282 {
1446 checkNodeBA(refNode, exceptionState); 1283 checkNodeBA(refNode, exceptionState);
1447 if (exceptionState.hadException()) 1284 if (exceptionState.hadException())
1448 return; 1285 return;
1449 1286
1450 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState); 1287 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState);
1451 } 1288 }
1452 1289
1453 void Range::checkDeleteExtract(ExceptionState& exceptionState) 1290 void Range::checkDeleteExtract(ExceptionState& exceptionState)
1454 { 1291 {
1455 if (!m_start.container()) {
1456 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1457 return;
1458 }
1459
1460 ASSERT(boundaryPointsValid()); 1292 ASSERT(boundaryPointsValid());
1461 1293
1462 if (!commonAncestorContainer(exceptionState) || exceptionState.hadException( )) 1294 if (!commonAncestorContainer())
1463 return; 1295 return;
1464 1296
1465 Node* pastLast = pastLastNode(); 1297 Node* pastLast = pastLastNode();
1466 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { 1298 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) {
1467 if (n->isDocumentTypeNode()) { 1299 if (n->isDocumentTypeNode()) {
1468 exceptionState.throwDOMException(HierarchyRequestError, "The Range c ontains a doctype node."); 1300 exceptionState.throwDOMException(HierarchyRequestError, "The Range c ontains a doctype node.");
1469 return; 1301 return;
1470 } 1302 }
1471 } 1303 }
1472 } 1304 }
1473 1305
1474 Node* Range::firstNode() const 1306 Node* Range::firstNode() const
1475 { 1307 {
1476 if (!m_start.container())
1477 return 0;
1478 if (m_start.container()->offsetInCharacters()) 1308 if (m_start.container()->offsetInCharacters())
1479 return m_start.container(); 1309 return m_start.container();
1480 if (Node* child = m_start.container()->traverseToChildAt(m_start.offset())) 1310 if (Node* child = m_start.container()->traverseToChildAt(m_start.offset()))
1481 return child; 1311 return child;
1482 if (!m_start.offset()) 1312 if (!m_start.offset())
1483 return m_start.container(); 1313 return m_start.container();
1484 return NodeTraversal::nextSkippingChildren(*m_start.container()); 1314 return NodeTraversal::nextSkippingChildren(*m_start.container());
1485 } 1315 }
1486 1316
1487 ShadowRoot* Range::shadowRoot() const 1317 ShadowRoot* Range::shadowRoot() const
1488 { 1318 {
1489 return startContainer() ? startContainer()->containingShadowRoot() : 0; 1319 return startContainer() ? startContainer()->containingShadowRoot() : 0;
1490 } 1320 }
1491 1321
1492 Node* Range::pastLastNode() const 1322 Node* Range::pastLastNode() const
1493 { 1323 {
1494 if (!m_start.container() || !m_end.container())
1495 return 0;
1496 if (m_end.container()->offsetInCharacters()) 1324 if (m_end.container()->offsetInCharacters())
1497 return NodeTraversal::nextSkippingChildren(*m_end.container()); 1325 return NodeTraversal::nextSkippingChildren(*m_end.container());
1498 if (Node* child = m_end.container()->traverseToChildAt(m_end.offset())) 1326 if (Node* child = m_end.container()->traverseToChildAt(m_end.offset()))
1499 return child; 1327 return child;
1500 return NodeTraversal::nextSkippingChildren(*m_end.container()); 1328 return NodeTraversal::nextSkippingChildren(*m_end.container());
1501 } 1329 }
1502 1330
1503 IntRect Range::boundingBox() const 1331 IntRect Range::boundingBox() const
1504 { 1332 {
1505 IntRect result; 1333 IntRect result;
1506 Vector<IntRect> rects; 1334 Vector<IntRect> rects;
1507 textRects(rects); 1335 textRects(rects);
1508 const size_t n = rects.size(); 1336 const size_t n = rects.size();
1509 for (size_t i = 0; i < n; ++i) 1337 for (size_t i = 0; i < n; ++i)
1510 result.unite(rects[i]); 1338 result.unite(rects[i]);
1511 return result; 1339 return result;
1512 } 1340 }
1513 1341
1514 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFi xedPosition* inFixed) const 1342 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFi xedPosition* inFixed) const
1515 { 1343 {
1516 Node* startContainer = m_start.container(); 1344 Node* startContainer = m_start.container();
1345 ASSERT(startContainer);
1517 Node* endContainer = m_end.container(); 1346 Node* endContainer = m_end.container();
1518 1347 ASSERT(endContainer);
1519 if (!startContainer || !endContainer) {
1520 if (inFixed)
1521 *inFixed = NotFixedPosition;
1522 return;
1523 }
1524 1348
1525 bool allFixed = true; 1349 bool allFixed = true;
1526 bool someFixed = false; 1350 bool someFixed = false;
1527 1351
1528 Node* stopNode = pastLastNode(); 1352 Node* stopNode = pastLastNode();
1529 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) { 1353 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) {
1530 RenderObject* r = node->renderer(); 1354 RenderObject* r = node->renderer();
1531 if (!r || !r->isText()) 1355 if (!r || !r->isText())
1532 continue; 1356 continue;
1533 RenderText* renderText = toRenderText(r); 1357 RenderText* renderText = toRenderText(r);
1534 int startOffset = node == startContainer ? m_start.offset() : 0; 1358 int startOffset = node == startContainer ? m_start.offset() : 0;
1535 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max(); 1359 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max();
1536 bool isFixed = false; 1360 bool isFixed = false;
1537 renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSele ctionHeight, &isFixed); 1361 renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSele ctionHeight, &isFixed);
1538 allFixed &= isFixed; 1362 allFixed &= isFixed;
1539 someFixed |= isFixed; 1363 someFixed |= isFixed;
1540 } 1364 }
1541 1365
1542 if (inFixed) 1366 if (inFixed)
1543 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition); 1367 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition);
1544 } 1368 }
1545 1369
1546 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeIn FixedPosition* inFixed) const 1370 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeIn FixedPosition* inFixed) const
1547 { 1371 {
1548 Node* startContainer = m_start.container(); 1372 Node* startContainer = m_start.container();
1373 ASSERT(startContainer);
1549 Node* endContainer = m_end.container(); 1374 Node* endContainer = m_end.container();
1550 1375 ASSERT(endContainer);
1551 if (!startContainer || !endContainer) {
1552 if (inFixed)
1553 *inFixed = NotFixedPosition;
1554 return;
1555 }
1556 1376
1557 bool allFixed = true; 1377 bool allFixed = true;
1558 bool someFixed = false; 1378 bool someFixed = false;
1559 1379
1560 Node* stopNode = pastLastNode(); 1380 Node* stopNode = pastLastNode();
1561 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) { 1381 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) {
1562 RenderObject* r = node->renderer(); 1382 RenderObject* r = node->renderer();
1563 if (!r || !r->isText()) 1383 if (!r || !r->isText())
1564 continue; 1384 continue;
1565 RenderText* renderText = toRenderText(r); 1385 RenderText* renderText = toRenderText(r);
1566 int startOffset = node == startContainer ? m_start.offset() : 0; 1386 int startOffset = node == startContainer ? m_start.offset() : 0;
1567 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max(); 1387 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max();
1568 bool isFixed = false; 1388 bool isFixed = false;
1569 renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSele ctionHeight, &isFixed); 1389 renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSele ctionHeight, &isFixed);
1570 allFixed &= isFixed; 1390 allFixed &= isFixed;
1571 someFixed |= isFixed; 1391 someFixed |= isFixed;
1572 } 1392 }
1573 1393
1574 if (inFixed) 1394 if (inFixed)
1575 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition); 1395 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition);
1576 } 1396 }
1577 1397
1578 #ifndef NDEBUG 1398 #ifndef NDEBUG
1579 void Range::formatForDebugger(char* buffer, unsigned length) const 1399 void Range::formatForDebugger(char* buffer, unsigned length) const
1580 { 1400 {
1581 StringBuilder result; 1401 StringBuilder result;
1582 String s;
1583 1402
1584 if (!m_start.container() || !m_end.container()) 1403 const int FormatBufferSize = 1024;
1585 result.appendLiteral("<empty>"); 1404 char s[FormatBufferSize];
1586 else { 1405 result.appendLiteral("from offset ");
1587 const int FormatBufferSize = 1024; 1406 result.appendNumber(m_start.offset());
1588 char s[FormatBufferSize]; 1407 result.appendLiteral(" of ");
1589 result.appendLiteral("from offset "); 1408 m_start.container()->formatForDebugger(s, FormatBufferSize);
1590 result.appendNumber(m_start.offset()); 1409 result.append(s);
1591 result.appendLiteral(" of "); 1410 result.appendLiteral(" to offset ");
1592 m_start.container()->formatForDebugger(s, FormatBufferSize); 1411 result.appendNumber(m_end.offset());
1593 result.append(s); 1412 result.appendLiteral(" of ");
1594 result.appendLiteral(" to offset "); 1413 m_end.container()->formatForDebugger(s, FormatBufferSize);
1595 result.appendNumber(m_end.offset()); 1414 result.append(s);
1596 result.appendLiteral(" of ");
1597 m_end.container()->formatForDebugger(s, FormatBufferSize);
1598 result.append(s);
1599 }
1600 1415
1601 strncpy(buffer, result.toString().utf8().data(), length - 1); 1416 strncpy(buffer, result.toString().utf8().data(), length - 1);
1602 } 1417 }
1603 #endif 1418 #endif
1604 1419
1605 bool areRangesEqual(const Range* a, const Range* b) 1420 bool areRangesEqual(const Range* a, const Range* b)
1606 { 1421 {
1607 if (a == b) 1422 if (a == b)
1608 return true; 1423 return true;
1609 if (!a || !b) 1424 if (!a || !b)
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 start = startOfDocument(start); 1600 start = startOfDocument(start);
1786 end = endOfDocument(end); 1601 end = endOfDocument(end);
1787 } else 1602 } else
1788 return; 1603 return;
1789 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp uteOffsetInContainerNode(), exceptionState); 1604 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp uteOffsetInContainerNode(), exceptionState);
1790 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff setInContainerNode(), exceptionState); 1605 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff setInContainerNode(), exceptionState);
1791 } 1606 }
1792 1607
1793 PassRefPtrWillBeRawPtr<ClientRectList> Range::getClientRects() const 1608 PassRefPtrWillBeRawPtr<ClientRectList> Range::getClientRects() const
1794 { 1609 {
1795 if (!m_start.container())
1796 return ClientRectList::create();
1797
1798 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); 1610 m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1799 1611
1800 Vector<FloatQuad> quads; 1612 Vector<FloatQuad> quads;
1801 getBorderAndTextQuads(quads); 1613 getBorderAndTextQuads(quads);
1802 1614
1803 return ClientRectList::create(quads); 1615 return ClientRectList::create(quads);
1804 } 1616 }
1805 1617
1806 PassRefPtrWillBeRawPtr<ClientRect> Range::getBoundingClientRect() const 1618 PassRefPtrWillBeRawPtr<ClientRect> Range::getBoundingClientRect() const
1807 { 1619 {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1842 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQu ads, renderText); 1654 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQu ads, renderText);
1843 1655
1844 quads.appendVector(textQuads); 1656 quads.appendVector(textQuads);
1845 } 1657 }
1846 } 1658 }
1847 } 1659 }
1848 } 1660 }
1849 1661
1850 FloatRect Range::boundingRect() const 1662 FloatRect Range::boundingRect() const
1851 { 1663 {
1852 if (!m_start.container())
1853 return FloatRect();
1854
1855 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); 1664 m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1856 1665
1857 Vector<FloatQuad> quads; 1666 Vector<FloatQuad> quads;
1858 getBorderAndTextQuads(quads); 1667 getBorderAndTextQuads(quads);
1859 if (quads.isEmpty()) 1668 if (quads.isEmpty())
1860 return FloatRect(); 1669 return FloatRect();
1861 1670
1862 FloatRect result; 1671 FloatRect result;
1863 for (size_t i = 0; i < quads.size(); ++i) 1672 for (size_t i = 0; i < quads.size(); ++i)
1864 result.unite(quads[i].boundingBox()); 1673 result.unite(quads[i].boundingBox());
(...skipping 11 matching lines...) Expand all
1876 1685
1877 void showTree(const WebCore::Range* range) 1686 void showTree(const WebCore::Range* range)
1878 { 1687 {
1879 if (range && range->boundaryPointsValid()) { 1688 if (range && range->boundaryPointsValid()) {
1880 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r ange->endContainer(), "E"); 1689 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r ange->endContainer(), "E");
1881 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset (), range->endOffset()); 1690 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset (), range->endOffset());
1882 } 1691 }
1883 } 1692 }
1884 1693
1885 #endif 1694 #endif
OLDNEW
« no previous file with comments | « Source/core/dom/Range.h ('k') | Source/core/dom/Range.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698